summaryrefslogtreecommitdiff
path: root/drivers/net/vrf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/vrf.c')
-rw-r--r--drivers/net/vrf.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 85c271c70d42..3bca24651dc0 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -272,11 +272,6 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
if (IS_ERR(rt))
goto err;
- if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) {
- ip_rt_put(rt);
- goto err;
- }
-
skb_dst_drop(skb);
/* if dst.dev is loopback or the VRF device again this is locally
@@ -611,6 +606,10 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
struct dst_entry *dst = NULL;
struct rtable *rth;
+ /* don't divert multicast */
+ if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+ return skb;
+
rcu_read_lock();
rth = rcu_dereference(vrf->rth);
@@ -956,6 +955,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
if (skb->pkt_type == PACKET_LOOPBACK) {
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
skb->pkt_type = PACKET_HOST;
goto out;
}
@@ -996,6 +996,10 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
{
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IPCB(skb)->flags |= IPSKB_L3SLAVE;
+
+ if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+ goto out;
/* loopback traffic; do not push through packet taps again.
* Reset pkt_type for upper layers to process skb
@@ -1160,8 +1164,19 @@ static int vrf_add_fib_rules(const struct net_device *dev)
if (err < 0)
goto ipv6_err;
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+ err = vrf_fib_rule(dev, RTNL_FAMILY_IPMR, true);
+ if (err < 0)
+ goto ipmr_err;
+#endif
+
return 0;
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+ipmr_err:
+ vrf_fib_rule(dev, AF_INET6, false);
+#endif
+
ipv6_err:
vrf_fib_rule(dev, AF_INET, false);