[ovs-dev] [patch_v8 4/9] dpdk: Add more ICMP Related NAT support.

Darrell Ball dlu998 at gmail.com
Tue May 30 17:49:28 UTC 2017


This patch includes more complete support
for icmp4 and icmp6 related NAT handling.

Signed-off-by: Darrell Ball <dlu998 at gmail.com>
Acked-by: Daniele Di Proietto <diproiettod at ovn.org>
---
 lib/conntrack.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 lib/packets.h   |  7 +++++
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index 5edaf40..616e23b 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -330,6 +330,95 @@ un_pat_packet(struct dp_packet *pkt, const struct conn *conn)
 }
 
 static void
+reverse_pat_packet(struct dp_packet *pkt, const struct conn *conn)
+{
+
+    if (conn->nat_info->nat_action & NAT_ACTION_SRC) {
+        if (conn->key.nw_proto == IPPROTO_TCP) {
+            struct tcp_header *th_in = dp_packet_l4(pkt);
+            packet_set_tcp_port(pkt, conn->key.src.port,
+                                th_in->tcp_dst);
+        } else if (conn->key.nw_proto == IPPROTO_UDP) {
+            struct udp_header *uh_in = dp_packet_l4(pkt);
+            packet_set_udp_port(pkt, conn->key.src.port,
+                                uh_in->udp_dst);
+        }
+    } else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
+        if (conn->key.nw_proto == IPPROTO_TCP) {
+            struct tcp_header *th_in = dp_packet_l4(pkt);
+            packet_set_tcp_port(pkt, th_in->tcp_src,
+                                conn->key.dst.port);
+        } else if (conn->key.nw_proto == IPPROTO_UDP) {
+            struct udp_header *uh_in = dp_packet_l4(pkt);
+            packet_set_udp_port(pkt, uh_in->udp_src,
+                                conn->key.dst.port);
+        }
+    }
+}
+
+static void
+reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn)
+{
+    char *tail = dp_packet_tail(pkt);
+    char pad = dp_packet_l2_pad_size(pkt);
+    struct conn_key inner_key;
+    const char *inner_l4 = NULL;
+    uint16_t orig_l3_ofs = pkt->l3_ofs;
+    uint16_t orig_l4_ofs = pkt->l4_ofs;
+
+    if (conn->key.dl_type == htons(ETH_TYPE_IP)) {
+        struct ip_header *nh = dp_packet_l3(pkt);
+        struct icmp_header *icmp = dp_packet_l4(pkt);
+        struct ip_header *inner_l3 = (struct ip_header *) (icmp + 1);
+        extract_l3_ipv4(&inner_key, inner_l3, tail - ((char *)inner_l3)
+                        -pad, &inner_l4, false);
+
+        pkt->l3_ofs += (char *) inner_l3 - (char *) nh;
+        pkt->l4_ofs += inner_l4 - (char *) icmp;
+
+        if (conn->nat_info->nat_action & NAT_ACTION_SRC) {
+            packet_set_ipv4_addr(pkt, &inner_l3->ip_src,
+                conn->key.src.addr.ipv4_aligned);
+        } else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
+            packet_set_ipv4_addr(pkt, &inner_l3->ip_dst,
+                conn->key.dst.addr.ipv4_aligned);
+        }
+        reverse_pat_packet(pkt, conn);
+        icmp->icmp_csum = 0;
+        icmp->icmp_csum = csum(icmp, tail - (char *) icmp - pad);
+    } else {
+        struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt);
+        struct icmp6_error_header *icmp6 = dp_packet_l4(pkt);
+        struct ovs_16aligned_ip6_hdr *inner_l3_6 =
+            (struct ovs_16aligned_ip6_hdr *) (icmp6 + 1);
+        extract_l3_ipv6(&inner_key, inner_l3_6,
+                        tail - ((char *)inner_l3_6) - pad,
+                        &inner_l4);
+        pkt->l3_ofs += (char *) inner_l3_6 - (char *) nh6;
+        pkt->l4_ofs += inner_l4 - (char *) icmp6;
+
+        if (conn->nat_info->nat_action & NAT_ACTION_SRC) {
+             packet_set_ipv6_addr(pkt, conn->key.nw_proto,
+                                  inner_l3_6->ip6_src.be32,
+                                  &conn->key.src.addr.ipv6_aligned,
+                                  true);
+        } else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
+             packet_set_ipv6_addr(pkt, conn->key.nw_proto,
+                                  inner_l3_6->ip6_dst.be32,
+                                  &conn->key.dst.addr.ipv6_aligned,
+                                  true);
+        }
+        reverse_pat_packet(pkt, conn);
+        uint32_t icmp6_csum = packet_csum_pseudoheader6(nh6);
+        icmp6->icmp6_base.icmp6_cksum = 0;
+        icmp6->icmp6_base.icmp6_cksum = csum_finish(
+            csum_continue(icmp6_csum, icmp6, tail - (char *) icmp6 - pad));
+    }
+    pkt->l3_ofs = orig_l3_ofs;
+    pkt->l4_ofs = orig_l4_ofs;
+}
+
+static void
 un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
               bool related)
 {
@@ -346,7 +435,9 @@ un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
                                  &conn->key.src.addr.ipv6_aligned, true);
         }
 
-        if (!related) {
+        if (OVS_UNLIKELY(related)) {
+            reverse_nat_packet(pkt, conn);
+        } else {
             un_pat_packet(pkt, conn);
         }
     } else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
@@ -362,7 +453,9 @@ un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
                                  &conn->key.dst.addr.ipv6_aligned, true);
         }
 
-        if (!related) {
+        if (OVS_UNLIKELY(related)) {
+            reverse_nat_packet(pkt, conn);
+        } else {
             un_pat_packet(pkt, conn);
         }
     }
diff --git a/lib/packets.h b/lib/packets.h
index 65ab8e8..b16bd2a 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -890,6 +890,13 @@ struct icmp6_header {
 };
 BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(struct icmp6_header));
 
+#define ICMP6_ERROR_HEADER_LEN 8
+struct icmp6_error_header {
+    struct icmp6_header icmp6_base;
+    ovs_be32 icmp6_error_ext;
+};
+BUILD_ASSERT_DECL(ICMP6_ERROR_HEADER_LEN == sizeof(struct icmp6_error_header));
+
 uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *);
 uint16_t packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *,
                                  const void *, uint8_t, uint16_t);
-- 
1.9.1



More information about the dev mailing list