Re: VRF: Ingress IPv6 Linklocal/Multicast destined pkt from slave VRF device does not map to Master device socket

2018-04-24 Thread David Ahern
On 4/23/18 11:57 PM, Sukumar Gopalakrishnan wrote:
> 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));
> 

Packets destined to a linklocal and mcast address stay bound to the
actual ingress device as that is their scope.


VRF: Ingress IPv6 Linklocal/Multicast destined pkt from slave VRF device does not map to Master device socket

2018-04-23 Thread Sukumar Gopalakrishnan
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:  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:  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) {

..
if (sk->sk_bound_dev_if &&
sk->sk_bound_dev_if != dif &&
sk->sk_bound_dev_if != sdif)
..



}


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