summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2019-12-18 05:54:40 +0000
committerNeale Ranns <nranns@cisco.com>2019-12-18 05:54:40 +0000
commit568acbb7c980608e238b25b1330d2730b8534599 (patch)
tree1044b7dc36f8779286d47ae5c6bce6eb977fec77
parent6461b7a319e53490e04e5e59d7909766fca86209 (diff)
ipsec: Fix decap of IPSEC/GRE in transport mode
Type: fix in transport mode the header sequence is: MAC - IP (tun) - ESP - GRE - L2 so popping the GRE header is done in the ESP decrypt node. Change-Id: Ia125eb65b9300368617d2bffca09683851e43be0 Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/vnet/ipsec/esp_decrypt.c50
-rw-r--r--test/test_ipsec_tun_if_esp.py126
2 files changed, 169 insertions, 7 deletions
diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c
index a56a7843ef5..8afea9b32a0 100644
--- a/src/vnet/ipsec/esp_decrypt.c
+++ b/src/vnet/ipsec/esp_decrypt.c
@@ -24,10 +24,13 @@
#include <vnet/ipsec/ipsec_io.h>
#include <vnet/ipsec/ipsec_tun.h>
+#include <vnet/gre/gre.h>
+
#define foreach_esp_decrypt_next \
_(DROP, "error-drop") \
_(IP4_INPUT, "ip4-input-no-checksum") \
_(IP6_INPUT, "ip6-input") \
+_(L2_INPUT, "l2-input") \
_(HANDOFF, "handoff")
#define _(v, s) ESP_DECRYPT_NEXT_##v,
@@ -487,9 +490,40 @@ esp_decrypt_inline (vlib_main_t * vm,
}
else
{
- next[0] = ESP_DECRYPT_NEXT_DROP;
- b[0]->error = node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
- goto trace;
+ if (is_tun && f->next_header == IP_PROTOCOL_GRE)
+ {
+ gre_header_t *gre;
+
+ b[0]->current_data = pd->current_data + adv;
+ b[0]->current_length = pd->current_length - adv - tail;
+
+ gre = vlib_buffer_get_current (b[0]);
+
+ vlib_buffer_advance (b[0], sizeof (*gre));
+
+ switch (clib_net_to_host_u16 (gre->protocol))
+ {
+ case GRE_PROTOCOL_teb:
+ next[0] = ESP_DECRYPT_NEXT_L2_INPUT;
+ break;
+ case GRE_PROTOCOL_ip4:
+ next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
+ break;
+ case GRE_PROTOCOL_ip6:
+ next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
+ break;
+ default:
+ next[0] = ESP_DECRYPT_NEXT_DROP;
+ break;
+ }
+ }
+ else
+ {
+ next[0] = ESP_DECRYPT_NEXT_DROP;
+ b[0]->error =
+ node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED];
+ goto trace;
+ }
}
if (is_tun)
{
@@ -501,9 +535,9 @@ esp_decrypt_inline (vlib_main_t * vm,
*/
const ipsec_tun_protect_t *itp;
- itp =
- ipsec_tun_protect_get (vnet_buffer (b[0])->
- ipsec.protect_index);
+ itp = ipsec_tun_protect_get
+ (vnet_buffer (b[0])->ipsec.protect_index);
+
if (PREDICT_TRUE (f->next_header == IP_PROTOCOL_IP_IN_IP))
{
const ip4_header_t *ip4;
@@ -614,6 +648,7 @@ VLIB_REGISTER_NODE (esp4_decrypt_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+ [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
},
};
@@ -632,6 +667,7 @@ VLIB_REGISTER_NODE (esp6_decrypt_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+ [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF]= "esp6-decrypt-handoff",
},
};
@@ -648,6 +684,7 @@ VLIB_REGISTER_NODE (esp4_decrypt_tun_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+ [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
},
};
@@ -664,6 +701,7 @@ VLIB_REGISTER_NODE (esp6_decrypt_tun_node) = {
[ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
[ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+ [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
[ESP_DECRYPT_NEXT_HANDOFF]= "esp6-decrypt-handoff",
},
};
diff --git a/test/test_ipsec_tun_if_esp.py b/test/test_ipsec_tun_if_esp.py
index 3e578fabaf9..68d6b588b3c 100644
--- a/test/test_ipsec_tun_if_esp.py
+++ b/test/test_ipsec_tun_if_esp.py
@@ -47,6 +47,25 @@ def config_tun_params(p, encryption_type, tun_if):
esn_en=esn_en)
+def config_tra_params(p, encryption_type, tun_if):
+ ip_class_by_addr_type = {socket.AF_INET: IP, socket.AF_INET6: IPv6}
+ esn_en = bool(p.flags & (VppEnum.vl_api_ipsec_sad_flags_t.
+ IPSEC_API_SAD_FLAG_USE_ESN))
+ crypt_key = mk_scapy_crypt_key(p)
+ p.scapy_tun_sa = SecurityAssociation(
+ encryption_type, spi=p.vpp_tun_spi,
+ crypt_algo=p.crypt_algo,
+ crypt_key=crypt_key,
+ auth_algo=p.auth_algo, auth_key=p.auth_key,
+ esn_en=esn_en)
+ p.vpp_tun_sa = SecurityAssociation(
+ encryption_type, spi=p.scapy_tun_spi,
+ crypt_algo=p.crypt_algo,
+ crypt_key=crypt_key,
+ auth_algo=p.auth_algo, auth_key=p.auth_key,
+ esn_en=esn_en)
+
+
class TemplateIpsec4TunIfEsp(TemplateIpsec):
""" IPsec tunnel interface tests """
@@ -657,6 +676,111 @@ class TestIpsecGreTebIfEsp(TemplateIpsec,
super(TestIpsecGreTebIfEsp, self).tearDown()
+class TestIpsecGreTebIfEspTra(TemplateIpsec,
+ IpsecTun4Tests):
+ """ Ipsec GRE TEB ESP - Tra tests """
+ tun4_encrypt_node_name = "esp4-encrypt-tun"
+ tun4_decrypt_node_name = "esp4-decrypt-tun"
+ encryption_type = ESP
+ omac = "00:11:22:33:44:55"
+
+ def gen_encrypt_pkts(self, sa, sw_intf, src, dst, count=1,
+ payload_size=100):
+ return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
+ sa.encrypt(IP(src=self.pg0.remote_ip4,
+ dst=self.pg0.local_ip4) /
+ GRE() /
+ Ether(dst=self.omac) /
+ IP(src="1.1.1.1", dst="1.1.1.2") /
+ UDP(sport=1144, dport=2233) /
+ Raw(b'X' * payload_size))
+ for i in range(count)]
+
+ def gen_pkts(self, sw_intf, src, dst, count=1,
+ payload_size=100):
+ return [Ether(dst=self.omac) /
+ IP(src="1.1.1.1", dst="1.1.1.2") /
+ UDP(sport=1144, dport=2233) /
+ Raw(b'X' * payload_size)
+ for i in range(count)]
+
+ def verify_decrypted(self, p, rxs):
+ for rx in rxs:
+ self.assert_equal(rx[Ether].dst, self.omac)
+ self.assert_equal(rx[IP].dst, "1.1.1.2")
+
+ def verify_encrypted(self, p, sa, rxs):
+ for rx in rxs:
+ try:
+ pkt = sa.decrypt(rx[IP])
+ if not pkt.haslayer(IP):
+ pkt = IP(pkt[Raw].load)
+ self.assert_packet_checksums_valid(pkt)
+ self.assert_equal(pkt[IP].dst, self.pg0.remote_ip4)
+ self.assert_equal(pkt[IP].src, self.pg0.local_ip4)
+ self.assertTrue(pkt.haslayer(GRE))
+ e = pkt[Ether]
+ self.assertEqual(e[Ether].dst, self.omac)
+ self.assertEqual(e[IP].dst, "1.1.1.2")
+ except (IndexError, AssertionError):
+ self.logger.debug(ppp("Unexpected packet:", rx))
+ try:
+ self.logger.debug(ppp("Decrypted packet:", pkt))
+ except:
+ pass
+ raise
+
+ def setUp(self):
+ super(TestIpsecGreTebIfEspTra, self).setUp()
+
+ self.tun_if = self.pg0
+
+ p = self.ipv4_params
+
+ bd1 = VppBridgeDomain(self, 1)
+ bd1.add_vpp_config()
+
+ p.tun_sa_out = VppIpsecSA(self, p.scapy_tun_sa_id, p.scapy_tun_spi,
+ p.auth_algo_vpp_id, p.auth_key,
+ p.crypt_algo_vpp_id, p.crypt_key,
+ self.vpp_esp_protocol)
+ p.tun_sa_out.add_vpp_config()
+
+ p.tun_sa_in = VppIpsecSA(self, p.vpp_tun_sa_id, p.vpp_tun_spi,
+ p.auth_algo_vpp_id, p.auth_key,
+ p.crypt_algo_vpp_id, p.crypt_key,
+ self.vpp_esp_protocol)
+ p.tun_sa_in.add_vpp_config()
+
+ p.tun_if = VppGreInterface(self,
+ self.pg0.local_ip4,
+ self.pg0.remote_ip4,
+ type=(VppEnum.vl_api_gre_tunnel_type_t.
+ GRE_API_TUNNEL_TYPE_TEB))
+ p.tun_if.add_vpp_config()
+
+ p.tun_protect = VppIpsecTunProtect(self,
+ p.tun_if,
+ p.tun_sa_out,
+ [p.tun_sa_in])
+
+ p.tun_protect.add_vpp_config()
+
+ p.tun_if.admin_up()
+ p.tun_if.config_ip4()
+ config_tra_params(p, self.encryption_type, p.tun_if)
+
+ VppBridgeDomainPort(self, bd1, p.tun_if).add_vpp_config()
+ VppBridgeDomainPort(self, bd1, self.pg1).add_vpp_config()
+
+ self.vapi.cli("clear ipsec sa")
+
+ def tearDown(self):
+ p = self.ipv4_params
+ p.tun_if.unconfig_ip4()
+ super(TestIpsecGreTebIfEspTra, self).tearDown()
+
+
class TestIpsecGreIfEsp(TemplateIpsec,
IpsecTun4Tests):
""" Ipsec GRE ESP - TUN tests """
@@ -845,7 +969,7 @@ class TestIpsecGreIfEspTra(TemplateIpsec,
p.tun_if.admin_up()
p.tun_if.config_ip4()
- config_tun_params(p, self.encryption_type, p.tun_if)
+ config_tra_params(p, self.encryption_type, p.tun_if)
VppIpRoute(self, "1.1.1.2", 32,
[VppRoutePath(p.tun_if.remote_ip4,