mirror of
https://github.com/openvswitch/ovs
synced 2025-09-04 08:15:25 +00:00
dpdk: Add more ICMP Related NAT support.
This patch includes more complete support for icmp4 and icmp6 related NAT handling. Signed-off-by: Darrell Ball <dlu998@gmail.com> Acked-by: Daniele Di Proietto <diproiettod@ovn.org> Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -323,6 +323,94 @@ 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
|
static void
|
||||||
un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
|
un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
|
||||||
bool related)
|
bool related)
|
||||||
@@ -339,7 +427,10 @@ un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
|
|||||||
nh6->ip6_dst.be32,
|
nh6->ip6_dst.be32,
|
||||||
&conn->key.src.addr.ipv6_aligned, true);
|
&conn->key.src.addr.ipv6_aligned, true);
|
||||||
}
|
}
|
||||||
if (!related) {
|
|
||||||
|
if (OVS_UNLIKELY(related)) {
|
||||||
|
reverse_nat_packet(pkt, conn);
|
||||||
|
} else {
|
||||||
un_pat_packet(pkt, conn);
|
un_pat_packet(pkt, conn);
|
||||||
}
|
}
|
||||||
} else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
|
} else if (conn->nat_info->nat_action & NAT_ACTION_DST) {
|
||||||
@@ -354,7 +445,10 @@ un_nat_packet(struct dp_packet *pkt, const struct conn *conn,
|
|||||||
nh6->ip6_src.be32,
|
nh6->ip6_src.be32,
|
||||||
&conn->key.dst.addr.ipv6_aligned, true);
|
&conn->key.dst.addr.ipv6_aligned, true);
|
||||||
}
|
}
|
||||||
if (!related) {
|
|
||||||
|
if (OVS_UNLIKELY(related)) {
|
||||||
|
reverse_nat_packet(pkt, conn);
|
||||||
|
} else {
|
||||||
un_pat_packet(pkt, conn);
|
un_pat_packet(pkt, conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -889,6 +889,13 @@ struct icmp6_header {
|
|||||||
};
|
};
|
||||||
BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(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 *);
|
uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *);
|
||||||
uint16_t packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *,
|
uint16_t packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *,
|
||||||
const void *, uint8_t, uint16_t);
|
const void *, uint8_t, uint16_t);
|
||||||
|
Reference in New Issue
Block a user