On 7/2/23 17:19, wushao...@chinatelecom.cn wrote: > From: Shaohua Wu <wushao...@chinatelecom.cn> > > The icmp_id maybe conflicts in snat > Description: > If multiple devices send icmp packets with the same icmp_id, > the sip of the packets changes to the same source ip address after the snat > operation, > and the packets are sent to the same destination ip address. > Only one ct entry is created.The data packets sent by other devices cannot be > sent to the peer device
Hi. Thanks for the new version! I didn't review the code, but see some comments inline. > > ovs-appctl dpctl/dump-conntrack > icmp,orig=(src=10.0.0.4,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=500,type=0,code=0) > > After fixing the problem: > ovs-appctl dpctl/dump-conntrack > icmp,orig=(src=10.0.0.3,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=501,type=0,code=0) > icmp,orig=(src=10.0.0.1,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=500,type=0,code=0) > icmp,orig=(src=10.0.0.7,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=505,type=0,code=0) > icmp,orig=(src=10.0.0.4,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=502,type=0,code=0) > icmp,orig=(src=10.0.0.5,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=503,type=0,code=0) > icmp,orig=(src=10.0.0.6,dst=10.0.0.2,id=500,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.201,id=504,type=0,code=0) There should be an empty line here. > Signed-off-by: Shaohua Wu <wushao...@chinatelecom.cn> > --- Please, add here the version log, i.e. what changed between versions of the patch. > lib/conntrack.c | 39 +++++++++++++++++++++++++++++++++++---- > lib/packets.c | 22 ++++++++++++++++++++++ > lib/packets.h | 2 ++ > tests/system-traffic.at | 40 ++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 99 insertions(+), 4 deletions(-) > > diff --git a/lib/conntrack.c b/lib/conntrack.c > index 4375c03e2..07c6da6be 100644 > --- a/lib/conntrack.c > +++ b/lib/conntrack.c > @@ -698,6 +698,25 @@ get_ip_proto(const struct dp_packet *pkt) > return ip_proto; > } > > +static bool > +packet_is_icmpv4_info_message(const struct dp_packet *pkt) > +{ > + uint8_t ip_proto,icmp_type; > + > + ip_proto = get_ip_proto(pkt); > + if (ip_proto == IPPROTO_ICMP) { > + icmp_type = packet_get_icmp_type(pkt); > + if (icmp_type == ICMP4_ECHO_REQUEST || > + icmp_type == ICMP4_ECHO_REPLY || > + icmp_type == ICMP4_TIMESTAMP || > + icmp_type == ICMP4_TIMESTAMPREPLY || > + icmp_type == ICMP4_INFOREQUEST || > + icmp_type == ICMP4_INFOREPLY) > + return true; > + } > + return false; > +} > + > static bool > is_ftp_ctl(const enum ct_alg_ctl_type ct_alg_ctl) > { > @@ -771,6 +790,9 @@ pat_packet(struct dp_packet *pkt, const struct conn_key > *key) > packet_set_tcp_port(pkt, key->dst.port, key->src.port); > } else if (key->nw_proto == IPPROTO_UDP) { > packet_set_udp_port(pkt, key->dst.port, key->src.port); > + } else if (packet_is_icmpv4_info_message(pkt) && > + key->nw_proto == IPPROTO_ICMP) { > + packet_set_icmp_id(pkt, key->src.icmp_id); > } > } > > @@ -2306,8 +2328,8 @@ store_addr_to_key(union ct_addr *addr, struct conn_key > *key, > > static bool > nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn, > - ovs_be16 *port, uint16_t curr, uint16_t min, > - uint16_t max) > + ovs_be16 *port, ovs_be16 *peer_port, > + uint16_t curr, uint16_t min, uint16_t max) > { > static const unsigned int max_attempts = 128; > uint16_t range = max - min + 1; > @@ -2328,6 +2350,9 @@ another_round: > } > > *port = htons(curr); > + if (peer_port) { > + *peer_port = htons(curr); > + } > if (!conn_lookup(ct, &nat_conn->rev_key, > time_msec(), NULL, NULL)) { > return true; > @@ -2341,6 +2366,9 @@ another_round: > } > > *port = htons(orig); > + if (peer_port) { > + *peer_port = htons(orig); > + } > > return false; > } > @@ -2374,7 +2402,8 @@ nat_get_unique_tuple(struct conntrack *ct, const struct > conn *conn, > uint32_t hash = nat_range_hash(conn, ct->hash_basis, nat_info); > union ct_addr min_addr = {0}, max_addr = {0}, addr = {0}; > bool pat_proto = conn->key.nw_proto == IPPROTO_TCP || > - conn->key.nw_proto == IPPROTO_UDP; > + conn->key.nw_proto == IPPROTO_UDP || > + conn->key.nw_proto == IPPROTO_ICMP; > uint16_t min_dport, max_dport, curr_dport; > uint16_t min_sport, max_sport, curr_sport; > > @@ -2409,11 +2438,13 @@ nat_get_unique_tuple(struct conntrack *ct, const > struct conn *conn, > bool found = false; > if (nat_info->nat_action & NAT_ACTION_DST_PORT) { > found = nat_get_unique_l4(ct, nat_conn, &nat_conn->rev_key.src.port, > - curr_dport, min_dport, max_dport); > + NULL,curr_dport, min_dport, max_dport); > } > > if (!found) { > found = nat_get_unique_l4(ct, nat_conn, &nat_conn->rev_key.dst.port, > + nat_conn->rev_key.nw_proto == IPPROTO_ICMP > ? > + &nat_conn->rev_key.src.port : NULL, > curr_sport, min_sport, max_sport); > } > > diff --git a/lib/packets.c b/lib/packets.c > index 462b51f92..f8e33cd68 100644 > --- a/lib/packets.c > +++ b/lib/packets.c > @@ -1492,6 +1492,28 @@ packet_set_icmp(struct dp_packet *packet, uint8_t > type, uint8_t code) > pkt_metadata_init_conn(&packet->md); > } > > +/* Sets the ICMP id of the ICMP header contained in 'packet'. > + * 'packet' must be a valid ICMP packet with its l4 offset properly > + * populated. */ > +void > +packet_set_icmp_id(struct dp_packet *packet, ovs_be16 icmp_id) > +{ > + struct icmp_header *ih = dp_packet_l4(packet); > + ovs_be16 orig_ic = ih->icmp_fields.echo.id; > + > + if (icmp_id != orig_ic) { > + ih->icmp_fields.echo.id = icmp_id; > + ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_ic, icmp_id); > + } > + pkt_metadata_init_conn(&packet->md); Indentation is off here. One too many spaces. > +} > + > +uint8_t > +packet_get_icmp_type(const struct dp_packet *packet) > +{ > + struct icmp_header *ih = dp_packet_l4(packet); > + return ih->icmp_type; > +} > /* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the > * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3 > * query packet with its l4 offset properly populated. > diff --git a/lib/packets.h b/lib/packets.h > index 200b25cf0..57b433f73 100644 > --- a/lib/packets.h > +++ b/lib/packets.h > @@ -1628,6 +1628,8 @@ void packet_set_tcp_port(struct dp_packet *, ovs_be16 > src, ovs_be16 dst); > void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); > void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); > void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code); > +void packet_set_icmp_id(struct dp_packet *, ovs_be16 icmp_id); > +uint8_t packet_get_icmp_type(const struct dp_packet *packet); > void packet_set_nd(struct dp_packet *, const struct in6_addr *target, > const struct eth_addr sll, const struct eth_addr tll); > void packet_set_nd_ext(struct dp_packet *packet, > diff --git a/tests/system-traffic.at b/tests/system-traffic.at > index a05ca311c..0a918c669 100644 > --- a/tests/system-traffic.at > +++ b/tests/system-traffic.at > @@ -3219,6 +3219,46 @@ > tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src= > OVS_TRAFFIC_VSWITCHD_STOP > AT_CLEANUP > > +AT_SETUP([conntrack - SNAT with icmp_id]) > +CHECK_CONNTRACK() > +CHECK_CONNTRACK_NAT() > +OVS_TRAFFIC_VSWITCHD_START() > + > +ADD_NAMESPACES(at_ns0, at_ns1) > +ADD_VETH(p0, at_ns0, br0, "10.0.0.1/24") > +NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address 80:88:88:88:88:88]) > +ADD_VETH(p1, at_ns1, br0, "10.0.0.2/24") > + > +dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from > ns1->ns0. > +AT_DATA([flows.txt], [dnl > +table=0,in_port=2,ct_state=-trk,icmp,action=ct(table=1, nat) > +table=0,in_port=1,ct_state=-trk,icmp,action=ct(table=1, nat) > +table=1,in_port=1,ct_state=+trk+new,action=ct(commit, > nat(src=10.0.0.201)),ovs-p1 > +table=1,in_port=1,ct_state=+trk+est,action=2 > +table=1,in_port=2,ct_state=+trk+est,action=1 > +]) > + > +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) Not sure why you sent the patch twice, but the test in this version is always failing with: ./system-traffic.at:3241: ovs-ofctl --bundle add-flows br0 flows.txt --- /dev/null 2023-06-06 14:05:49.440000000 +0000 +++ /root/ovs/tests/system-userspace-testsuite.dir/at-groups/67/stderr 2023-07-04 13:47:17.748000000 +0000 @@ -0,0 +1 @@ +ovs-ofctl: flows.txt:3: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT) Please, fix that and send v3. Best regards, Ilya Maximets. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev