Add buffering support for IPv6 packets that will be processed by
nd_ns {} action when L2 address is not discovered yet since
otherwise the packet will be substituted with a Neighbor Solicitation
frame and this will result in the lost of the first packet of the
connectionSigned-off-by: Lorenzo Bianconi <[email protected]> --- ovn/controller/pinctrl.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 3f8c0ac4e..6436be428 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -99,6 +99,7 @@ static void pinctrl_handle_put_nd_ra_opts( struct ofputil_packet_in *pin, struct ofpbuf *userdata, struct ofpbuf *continuation); static void pinctrl_handle_nd_ns(const struct flow *ip_flow, + struct dp_packet *pkt_in, const struct match *md, struct ofpbuf *userdata); static void init_ipv6_ras(void); @@ -1358,7 +1359,8 @@ process_packet_in(const struct ofp_header *msg, break; case ACTION_OPCODE_ND_NS: - pinctrl_handle_nd_ns(&headers, &pin.flow_metadata, &userdata); + pinctrl_handle_nd_ns(&headers, &packet, &pin.flow_metadata, + &userdata); break; case ACTION_OPCODE_ICMP: @@ -2569,9 +2571,13 @@ pinctrl_handle_nd_na(const struct flow *ip_flow, const struct match *md, } static void -pinctrl_handle_nd_ns(const struct flow *ip_flow, const struct match *md, - struct ofpbuf *userdata) +pinctrl_handle_nd_ns(const struct flow *ip_flow, struct dp_packet *pkt_in, + const struct match *md, struct ofpbuf *userdata) { + struct dp_packet *clone, packet; + uint64_t packet_stub[128 / 8]; + char ip[INET6_ADDRSTRLEN]; + /* This action only works for IPv6 packets. */ if (get_dl_type(ip_flow) != htons(ETH_TYPE_IPV6)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -2579,8 +2585,27 @@ pinctrl_handle_nd_ns(const struct flow *ip_flow, const struct match *md, return; } - uint64_t packet_stub[128 / 8]; - struct dp_packet packet; + inet_ntop(AF_INET6, &ip_flow->ipv6_dst, ip, sizeof(ip)); + uint32_t hash = hash_string(ip, 0); + struct buffered_packets *bp = pinctrl_find_buffered_packets(ip, hash); + if (!bp) { + if (hmap_count(&buffered_packets_map) >= 1000) { + COVERAGE_INC(pinctrl_drop_buffered_packets_map); + goto send_ns; + } + + bp = xmalloc(sizeof *bp); + hmap_insert(&buffered_packets_map, &bp->hmap_node, hash); + ovs_strlcpy_arrays(bp->ip, ip); + bp->head = bp->tail = 0; + } + bp->timestamp = time_msec(); + /* clone the packet to send it later with correct L2 address */ + clone = dp_packet_clone_data(dp_packet_data(pkt_in), + dp_packet_size(pkt_in)); + buffered_push_packet(bp, clone, md); + +send_ns: dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); compose_nd_ns(&packet, ip_flow->dl_src, &ip_flow->ipv6_src, -- 2.17.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
