VRF: Ingress IPv6 Linklocal/Multicast pkt from slave VRF device does not map to Master device socket.
KERNEL VERSION: ================ 4.14.28 BUG REPORT: ============ https://bugzilla.kernel.org/show_bug.cgi?id=199409 CONFIGURATION AND PROBLEM ROOT CAUSE: ======================================== 1) Created VRF device(Vrf_258) and enslaved network device(v1_F4246) to this VRF. /exos/bin # ip link show v1_F4246 54: v1_F4246: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vrf_258 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether 00:04:96:98:c9:18 brd ff:ff:ff:ff:ff:ff /exos/bin # ip link show vrf_258 14: vrf_258: <NOARP,MASTER,UP,LOWER_UP> mtu 65536 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 00:04:96:98:c9:18 brd ff:ff:ff:ff:ff:ff 2) Opened PIM protocol raw socket for AF_INET6 family pim_socket = socket(AF_INET6, SOCK_RAW , IPPROTO_PIM ) 3) PIM user daemon process per VRF so opened RX socket SO_BINDTODEVICE to VRF_258 netdevice. PIM control packets ingressing any slave devices belongs to this master VRF device should be sent to this socket. 4) Ingressing PIM hello control packets which is having SrcIP = fe80::204:96ff:fe98:c918 (IPv6 Link-local) and DestIP = ff02::0d (Multicast pkt) does not mapped to vrf_258 bounded socket and gets dropped in socket lookup function. 5) inet6_iif() is returning v1_F4246's ifindex 54 and inet6_sdif() returns value zero. __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb), inet6_sdif(skb)); sk->sk_bound_dev_if is having vrf_258(ifIndex value 14) but dif(value 54) and sdif(value 0) does not match this socket hence socket not found. struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, unsigned short num, const struct in6_addr *loc_addr, const struct in6_addr *rmt_addr, int dif, int sdif) { <snip> .. if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif && sk->sk_bound_dev_if != sdif) .. <snip> } 6) This problem is seen for Raw, Udp and TCP socket look up function for IPv6 packets destined to linklocal or multicast address. 7) This issue do not occur for all types of IPV4 address and IPv6 unicast global address. TEMP FIX: ========= Get master device address from (skb->dev) and pass master to socket lookup up function for Ipv6 Linklocal/Multicast address. ipv6_raw_deliver() { int mdif; .. .. mdif = (((nexthdr == IPPROTO_PIM || nexthdr == 89 /* IPPROTO_OSPF */ || nexthdr == IPPROTO_ICMPV6 || nexthdr == 112 /*IPPROTO_VRRP*/) && (ipv6_addr_type(daddr) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL))) ? l3mdev_master_ifindex_rcu(skb->dev) : inet6_iif(skb)); sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, mdif, inet6_sdif(skb)); ... .. } Regards, Sukumar