@@ -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,
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 connection Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> --- ovn/controller/pinctrl.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)