[ovs-dev] [PATCH RFC 3/5] Tunnel: Snoop ingress packets and update neigh cache if needed.

Paolo Valerio pvalerio at redhat.com
Mon Nov 1 08:07:23 UTC 2021


Flavio Leitner <fbl at sysclose.org> writes:

> On Thu, Oct 07, 2021 at 02:35:28PM +0200, Paolo Valerio wrote:
>> In case of native tunnel with bfd enabled, if the MAC address of the
>> remote end's interface changes (e.g. because it got rebooted, and the
>> MAC address is allocated dinamically), the BFD session will never be
>> re-established.
>> 
>> This happens because the local tunnel neigh entry doesn't get updated,
>> and the local end keeps sending BFD packets with the old destination
>> MAC address. This was not an issue until
>> b23ddcc57d41 ("tnl-neigh-cache: tighten arp and nd snooping.")
>> because ARP requests were snooped as well avoiding the problem.
>> 
>> Fix this by snooping the incoming packets, and updating the neigh
>> cache accordingly.
>
>
> Can we add a mention that this only affects slow path?
> Otherwise it may suggests a performance impact.
>

Sure.

>
>> Signed-off-by: Paolo Valerio <pvalerio at redhat.com>
>> Fixes: b23ddcc57d41 ("tnl-neigh-cache: tighten arp and nd snooping.")
>> ---
>>  lib/tnl-neigh-cache.c        |   12 ++++++------
>>  lib/tnl-neigh-cache.h        |    3 +++
>>  ofproto/ofproto-dpif-xlate.c |   14 ++++++++++++++
>>  3 files changed, 23 insertions(+), 6 deletions(-)
>> 
>> diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
>> index c8a7b60cd..9d3f00ad9 100644
>> --- a/lib/tnl-neigh-cache.c
>> +++ b/lib/tnl-neigh-cache.c
>> @@ -135,9 +135,9 @@ tnl_neigh_delete(struct tnl_neigh_entry *neigh)
>>      ovsrcu_postpone(neigh_entry_free, neigh);
>>  }
>>  
>> -static void
>> -tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
>> -                const struct eth_addr mac)
>> +void
>> +tnl_neigh_set(const char name[IFNAMSIZ], const struct in6_addr *dst,
>> +              const struct eth_addr mac)
>>  {
>>      ovs_mutex_lock(&mutex);
>>      struct tnl_neigh_entry *neigh = tnl_neigh_lookup__(name, dst);
>> @@ -168,7 +168,7 @@ tnl_arp_set(const char name[IFNAMSIZ], ovs_be32 dst,
>>              const struct eth_addr mac)
>>  {
>>      struct in6_addr dst6 = in6_addr_mapped_ipv4(dst);
>> -    tnl_neigh_set__(name, &dst6, mac);
>> +    tnl_neigh_set(name, &dst6, mac);
>>  }
>>  
>>  static int
>> @@ -208,7 +208,7 @@ tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
>>      memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
>>      memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
>>  
>> -    tnl_neigh_set__(name, &flow->nd_target, flow->arp_tha);
>> +    tnl_neigh_set(name, &flow->nd_target, flow->arp_tha);
>>      return 0;
>>  }
>>  
>> @@ -355,7 +355,7 @@ tnl_neigh_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED,
>>          return;
>>      }
>>  
>> -    tnl_neigh_set__(br_name, &ip6, mac);
>> +    tnl_neigh_set(br_name, &ip6, mac);
>>      unixctl_command_reply(conn, "OK");
>>  }
>>  
>> diff --git a/lib/tnl-neigh-cache.h b/lib/tnl-neigh-cache.h
>> index e4b42b059..92fdf5a93 100644
>> --- a/lib/tnl-neigh-cache.h
>> +++ b/lib/tnl-neigh-cache.h
>> @@ -33,6 +33,9 @@
>>  
>>  int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
>>                      const char dev_name[IFNAMSIZ]);
>> +void
>> +tnl_neigh_set(const char name[IFNAMSIZ], const struct in6_addr *dst,
>> +              const struct eth_addr mac);
>>  int tnl_neigh_lookup(const char dev_name[IFNAMSIZ], const struct in6_addr *dst,
>>                       struct eth_addr *mac);
>>  void tnl_neigh_cache_init(void);
>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
>> index 8723cb4e8..4430ac073 100644
>> --- a/ofproto/ofproto-dpif-xlate.c
>> +++ b/ofproto/ofproto-dpif-xlate.c
>> @@ -4098,6 +4098,20 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow,
>>               flow->nw_proto == IPPROTO_ICMPV6) &&
>>               is_neighbor_reply_correct(ctx, flow)) {
>>              tnl_neigh_snoop(flow, wc, ctx->xbridge->name);
>> +        } else if (*tnl_port != ODPP_NONE &&
>> +                   ctx->xin->allow_side_effects &&
>> +                   (flow->dl_type == htons(ETH_TYPE_IP) ||
>> +                    flow->dl_type == htons(ETH_TYPE_IPV6))) {
>> +            struct eth_addr mac = flow->dl_src;
>> +            struct in6_addr s_ip6;
>> +
>> +            if (flow->nw_src) {
>
> I don't think we will have zeros as valid source IP addr at this
> point, but this looks odd. Why not repeating the same check?
>                if (flow->dl_type == htons(ETH_TYPE_IP)) {
>

ACK. Will do.

>
>> +                in6_addr_set_mapped_ipv4(&s_ip6, flow->nw_src);
>> +            } else {
>> +                s_ip6 = flow->ipv6_src;
>> +            }
>> +
>> +            tnl_neigh_set(ctx->xbridge->name, &s_ip6, mac);
>>          }
>>      }
>>  
>> 
>> _______________________________________________
>> dev mailing list
>> dev at openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
> -- 
> fbl



More information about the dev mailing list