[ovs-dev] [PATCH v2] OVN: Fix learning of neighbors from ARP/ND packets.
Dumitru Ceara
dceara at redhat.com
Mon Jul 29 09:32:20 UTC 2019
On Fri, Jul 26, 2019 at 8:33 AM Dumitru Ceara <dceara at redhat.com> wrote:
>
> Add a restriction on the target protocol addresses to match the configured
> subnets. All other ARP/ND packets are invalid in this context.
>
> One exception is for ARP replies that are received for route next-hops
> that are only reachable via a port but can't be directly resolved
> through route lookups. Such support was introduced by commit:
>
> 6b785fd8fe29 ("ovn-util: Allow /32 IP addresses for router ports.")
>
> Reported-at: https://bugzilla.redhat.com/1729846
> Reported-by: Haidong Li <haili at redhat.com>
> CC: Han Zhou <zhouhan at gmail.com>
> CC: Guru Shetty <guru at ovn.org>
> Fixes: b068454082f5 ("ovn-northd: Support learning neighbor from ARP request.")
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> ---
>
> v2:
> - Update commit message.
> - Implement the fix also for ARP replies and IPv6 ND.
Hi Han, Guru,
I resubmitted this patch against the ovn-org repo. The new patchwork
is: https://patchwork.ozlabs.org/patch/1138261/
Thanks,
Dumitru
> ---
> ovn/northd/ovn-northd.c | 95 +++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 81 insertions(+), 14 deletions(-)
>
> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
> index eb6c47c..1e3ec68 100644
> --- a/ovn/northd/ovn-northd.c
> +++ b/ovn/northd/ovn-northd.c
> @@ -5815,10 +5815,32 @@ build_static_route_flow(struct hmap *lflows, struct ovn_datapath *od,
> if (is_ipv4) {
> if (out_port->lrp_networks.n_ipv4_addrs) {
> lrp_addr_s = out_port->lrp_networks.ipv4_addrs[0].addr_s;
> +
> + /* Explicitly allow ARP replies for the next-hop. */
> + struct ds match;
> + ds_init(&match);
> + ds_put_format(&match, "inport == %s && arp.op == 2 && "
> + "arp.spa == %s", out_port->json_key,
> + route->nexthop);
> + ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 90,
> + ds_cstr(&match),
> + "put_arp(inport, arp.spa, arp.sha);");
> + ds_destroy(&match);
> }
> } else {
> if (out_port->lrp_networks.n_ipv6_addrs) {
> lrp_addr_s = out_port->lrp_networks.ipv6_addrs[0].addr_s;
> +
> + /* Explicitly allow NA for the next-hop. */
> + struct ds match;
> + ds_init(&match);
> + ds_put_format(&match, "inport == %s && nd_na && "
> + "ip6.src == %s", out_port->json_key,
> + route->nexthop);
> + ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 90,
> + ds_cstr(&match),
> + "put_nd(inport, nd.target, nd.tll);");
> + ds_destroy(&match);
> }
> }
> }
> @@ -6159,10 +6181,6 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
> "ip4.dst == 0.0.0.0/8",
> "drop;");
>
> - /* ARP reply handling. Use ARP replies to populate the logical
> - * router's ARP table. */
> - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 90, "arp.op == 2",
> - "put_arp(inport, arp.spa, arp.sha);");
>
> /* Drop Ethernet local broadcast. By definition this traffic should
> * not be forwarded.*/
> @@ -6175,16 +6193,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
> ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 30,
> ds_cstr(&match), "drop;");
>
> - /* ND advertisement handling. Use advertisements to populate
> - * the logical router's ARP/ND table. */
> - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 90, "nd_na",
> - "put_nd(inport, nd.target, nd.tll);");
>
> - /* Lean from neighbor solicitations that were not directed at
> - * us. (A priority-90 flow will respond to requests to us and
> - * learn the sender's mac address. */
> - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, 80, "nd_ns",
> - "put_nd(inport, ip6.src, nd.sll);");
>
> /* Pass other traffic not already handled to the next table for
> * routing. */
> @@ -6320,15 +6329,34 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
> ds_cstr(&match), ds_cstr(&actions));
> }
>
> + /* ARP reply handling. Use ARP replies to populate the logical
> + * router's ARP table. */
> + for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
> + ds_clear(&match);
> + ds_put_format(&match, "inport == %s && arp.spa == %s/%u && "
> + "arp.tpa == %s/%u && arp.op == 2",
> + op->json_key,
> + op->lrp_networks.ipv4_addrs[i].network_s,
> + op->lrp_networks.ipv4_addrs[i].plen,
> + op->lrp_networks.ipv4_addrs[i].network_s,
> + op->lrp_networks.ipv4_addrs[i].plen);
> + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
> + ds_cstr(&match),
> + "put_arp(inport, arp.spa, arp.sha);");
> + }
> +
> /* Learn from ARP requests that were not directed at us. A typical
> * use case is GARP request handling. (A priority-90 flow will
> * respond to request to us and learn the sender's mac address.) */
> for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
> ds_clear(&match);
> ds_put_format(&match,
> - "inport == %s && arp.spa == %s/%u && arp.op == 1",
> + "inport == %s && arp.spa == %s/%u && "
> + "arp.tpa == %s/%u && arp.op == 1",
> op->json_key,
> op->lrp_networks.ipv4_addrs[i].network_s,
> + op->lrp_networks.ipv4_addrs[i].plen,
> + op->lrp_networks.ipv4_addrs[i].network_s,
> op->lrp_networks.ipv4_addrs[i].plen);
> if (op->od->l3dgw_port && op == op->od->l3dgw_port
> && op->od->l3redirect_port) {
> @@ -6669,6 +6697,45 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
> ds_cstr(&match), ds_cstr(&actions));
> }
>
> + /* NA reply handling. Use NA replies to populate the logical
> + * router's neighbor table. */
> + for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
> + ds_clear(&match);
> + ds_put_format(&match, "inport == %s && nd_na && "
> + "nd.target == %s/%u && ip6.src == %s/%u",
> + op->json_key,
> + op->lrp_networks.ipv6_addrs[i].network_s,
> + op->lrp_networks.ipv6_addrs[i].plen,
> + op->lrp_networks.ipv6_addrs[i].network_s,
> + op->lrp_networks.ipv6_addrs[i].plen);
> + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
> + ds_cstr(&match),
> + "put_nd(inport, nd.target, nd.tll);");
> + }
> +
> + /* Learn from ND requests that were not directed at us.
> + * (A priority-90 flow will respond to request to us and learn the
> + * sender's mac address.) */
> + for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
> + ds_clear(&match);
> + ds_put_format(&match,
> + "inport == %s && nd_ns && ip6.src == %s/%u && "
> + "ip6.dst == %s/%u",
> + op->json_key,
> + op->lrp_networks.ipv6_addrs[i].network_s,
> + op->lrp_networks.ipv6_addrs[i].plen,
> + op->lrp_networks.ipv6_addrs[i].network_s,
> + op->lrp_networks.ipv6_addrs[i].plen);
> + if (op->od->l3dgw_port && op == op->od->l3dgw_port
> + && op->od->l3redirect_port) {
> + ds_put_format(&match, " && is_chassis_resident(%s)",
> + op->od->l3redirect_port->json_key);
> + }
> + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
> + ds_cstr(&match),
> + "put_nd(inport, ip6.src, nd.sll);");
> + }
> +
> /* UDP/TCP port unreachable */
> if (!smap_get(&op->od->nbr->options, "chassis")
> && !op->od->l3dgw_port) {
> --
> 1.8.3.1
>
More information about the dev
mailing list