1 #include <linux/kernel.h> 2 #include <linux/list.h> 3 #include <linux/netdevice.h> 4 #include <linux/rtnetlink.h> 5 #include <linux/skbuff.h> 6 #include <net/switchdev.h> 7 8 #include "br_private.h" 9 10 static int br_switchdev_mark_get(struct net_bridge *br, struct net_device *dev) 11 { 12 struct net_bridge_port *p; 13 14 /* dev is yet to be added to the port list. */ 15 list_for_each_entry(p, &br->port_list, list) { 16 if (switchdev_port_same_parent_id(dev, p->dev)) 17 return p->offload_fwd_mark; 18 } 19 20 return ++br->offload_fwd_mark; 21 } 22 23 int nbp_switchdev_mark_set(struct net_bridge_port *p) 24 { 25 struct switchdev_attr attr = { 26 .orig_dev = p->dev, 27 .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, 28 }; 29 int err; 30 31 ASSERT_RTNL(); 32 33 err = switchdev_port_attr_get(p->dev, &attr); 34 if (err) { 35 if (err == -EOPNOTSUPP) 36 return 0; 37 return err; 38 } 39 40 p->offload_fwd_mark = br_switchdev_mark_get(p->br, p->dev); 41 42 return 0; 43 } 44 45 void nbp_switchdev_frame_mark(const struct net_bridge_port *p, 46 struct sk_buff *skb) 47 { 48 if (skb->offload_fwd_mark && !WARN_ON_ONCE(!p->offload_fwd_mark)) 49 BR_INPUT_SKB_CB(skb)->offload_fwd_mark = p->offload_fwd_mark; 50 } 51 52 bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, 53 const struct sk_buff *skb) 54 { 55 return !skb->offload_fwd_mark || 56 BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark; 57 } 58