Bug 199409 - VRF: Ingress IPv6 Linklocal/Multicast destined pkt from slave VRF device does not map to Master device socket.
Summary: VRF: Ingress IPv6 Linklocal/Multicast destined pkt from slave VRF device does...
Status: NEW
Alias: None
Product: Networking
Classification: Unclassified
Component: IPV6 (show other bugs)
Hardware: All Linux
: P1 blocking
Assignee: Hideaki YOSHIFUJI
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-04-16 06:54 UTC by Sukumar
Modified: 2018-04-16 06:55 UTC (History)
1 user (show)

See Also:
Kernel Version: 4.14.28
Subsystem:
Regression: No
Bisected commit-id:


Attachments

Description Sukumar 2018-04-16 06:54:15 UTC
VRF: Ingress IPv6 Linklocal/Multicast pkt from slave VRF device does not map to Master device socket.


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

Note You need to log in before you can comment on or make changes to this bug.