net: don't reforward packets already forwarded by offload device
authorScott Feldman <sfeldma@gmail.com>
Sun, 19 Jul 2015 01:24:48 +0000 (18:24 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2015 01:32:44 +0000 (18:32 -0700)
Just before queuing skb for xmit on port, check if skb has been marked by
switchdev port driver as already fordwarded by device.  If so, drop skb.  A
non-zero skb->offload_fwd_mark field is set by the switchdev port
driver/device on ingress to indicate the skb has already been forwarded by
the device to egress ports with matching dev->skb_mark.  The switchdev port
driver would assign a non-zero dev->offload_skb_mark for each device port
netdev during registration, for example.

Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/linux/skbuff.h
net/core/dev.c

index 45cfd797eb77e9e0bc53e1471c7701d82d0fb3c1..8364f29e08be2b9d0d46a5ef5aa6de6ade9b5613 100644 (file)
@@ -1456,6 +1456,8 @@ enum netdev_priv_flags {
  *
  *     @xps_maps:      XXX: need comments on this one
  *
+ *     @offload_fwd_mark:      Offload device fwding mark
+ *
  *     @trans_start:           Time (in jiffies) of last Tx
  *     @watchdog_timeo:        Represents the timeout that is used by
  *                             the watchdog ( see dev_watchdog() )
@@ -1697,6 +1699,10 @@ struct net_device {
        struct xps_dev_maps __rcu *xps_maps;
 #endif
 
+#ifdef CONFIG_NET_SWITCHDEV
+       u32                     offload_fwd_mark;
+#endif
+
        /* These may be needed for future network-power-down code. */
 
        /*
index d6cdd6e87d53bcd1b4f390f61f73b1c91b076bdd..af7a09650fa24b0181de169bc94f8341aae72e2b 100644 (file)
@@ -506,6 +506,7 @@ static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1,
  *     @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
   *    @napi_id: id of the NAPI struct this skb came from
  *     @secmark: security marking
+ *     @offload_fwd_mark: fwding offload mark
  *     @mark: Generic packet mark
  *     @vlan_proto: vlan encapsulation protocol
  *     @vlan_tci: vlan tag control information
@@ -650,9 +651,15 @@ struct sk_buff {
                unsigned int    sender_cpu;
        };
 #endif
+       union {
 #ifdef CONFIG_NETWORK_SECMARK
-       __u32                   secmark;
+               __u32           secmark;
+#endif
+#ifdef CONFIG_NET_SWITCHDEV
+               __u32           offload_fwd_mark;
 #endif
+       };
+
        union {
                __u32           mark;
                __u32           reserved_tailroom;
index 8810b6bbebfea237e33dc952e2ed4175a107fe72..2ee15afb412d78a1a9c109717f65da9eaba05bc6 100644 (file)
@@ -3061,6 +3061,16 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
        else
                skb_dst_force(skb);
 
+#ifdef CONFIG_NET_SWITCHDEV
+       /* Don't forward if offload device already forwarded */
+       if (skb->offload_fwd_mark &&
+           skb->offload_fwd_mark == dev->offload_fwd_mark) {
+               consume_skb(skb);
+               rc = NET_XMIT_SUCCESS;
+               goto out;
+       }
+#endif
+
        txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);