1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/kernel.h> 3 #include <linux/list.h> 4 #include <linux/netdevice.h> 5 #include <linux/rtnetlink.h> 6 #include <linux/skbuff.h> 7 #include <net/switchdev.h> 8 9 #include "br_private.h" 10 11 static struct static_key_false br_switchdev_tx_fwd_offload; 12 13 static bool nbp_switchdev_can_offload_tx_fwd(const struct net_bridge_port *p, 14 const struct sk_buff *skb) 15 { 16 if (!static_branch_unlikely(&br_switchdev_tx_fwd_offload)) 17 return false; 18 19 return (p->flags & BR_TX_FWD_OFFLOAD) && 20 (p->hwdom != BR_INPUT_SKB_CB(skb)->src_hwdom); 21 } 22 23 bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb) 24 { 25 if (!static_branch_unlikely(&br_switchdev_tx_fwd_offload)) 26 return false; 27 28 return BR_INPUT_SKB_CB(skb)->tx_fwd_offload; 29 } 30 31 void br_switchdev_frame_set_offload_fwd_mark(struct sk_buff *skb) 32 { 33 skb->offload_fwd_mark = br_switchdev_frame_uses_tx_fwd_offload(skb); 34 } 35 36 /* Mark the frame for TX forwarding offload if this egress port supports it */ 37 void nbp_switchdev_frame_mark_tx_fwd_offload(const struct net_bridge_port *p, 38 struct sk_buff *skb) 39 { 40 if (nbp_switchdev_can_offload_tx_fwd(p, skb)) 41 BR_INPUT_SKB_CB(skb)->tx_fwd_offload = true; 42 } 43 44 /* Lazily adds the hwdom of the egress bridge port to the bit mask of hwdoms 45 * that the skb has been already forwarded to, to avoid further cloning to 46 * other ports in the same hwdom by making nbp_switchdev_allowed_egress() 47 * return false. 48 */ 49 void nbp_switchdev_frame_mark_tx_fwd_to_hwdom(const struct net_bridge_port *p, 50 struct sk_buff *skb) 51 { 52 if (nbp_switchdev_can_offload_tx_fwd(p, skb)) 53 set_bit(p->hwdom, &BR_INPUT_SKB_CB(skb)->fwd_hwdoms); 54 } 55 56 void nbp_switchdev_frame_mark(const struct net_bridge_port *p, 57 struct sk_buff *skb) 58 { 59 if (p->hwdom) 60 BR_INPUT_SKB_CB(skb)->src_hwdom = p->hwdom; 61 } 62 63 bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, 64 const struct sk_buff *skb) 65 { 66 struct br_input_skb_cb *cb = BR_INPUT_SKB_CB(skb); 67 68 return !test_bit(p->hwdom, &cb->fwd_hwdoms) && 69 (!skb->offload_fwd_mark || cb->src_hwdom != p->hwdom); 70 } 71 72 /* Flags that can be offloaded to hardware */ 73 #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \ 74 BR_MCAST_FLOOD | BR_BCAST_FLOOD) 75 76 int br_switchdev_set_port_flag(struct net_bridge_port *p, 77 unsigned long flags, 78 unsigned long mask, 79 struct netlink_ext_ack *extack) 80 { 81 struct switchdev_attr attr = { 82 .orig_dev = p->dev, 83 }; 84 struct switchdev_notifier_port_attr_info info = { 85 .attr = &attr, 86 }; 87 int err; 88 89 mask &= BR_PORT_FLAGS_HW_OFFLOAD; 90 if (!mask) 91 return 0; 92 93 attr.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS; 94 attr.u.brport_flags.val = flags; 95 attr.u.brport_flags.mask = mask; 96 97 /* We run from atomic context here */ 98 err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, 99 &info.info, extack); 100 err = notifier_to_errno(err); 101 if (err == -EOPNOTSUPP) 102 return 0; 103 104 if (err) { 105 if (extack && !extack->_msg) 106 NL_SET_ERR_MSG_MOD(extack, 107 "bridge flag offload is not supported"); 108 return -EOPNOTSUPP; 109 } 110 111 attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS; 112 attr.flags = SWITCHDEV_F_DEFER; 113 114 err = switchdev_port_attr_set(p->dev, &attr, extack); 115 if (err) { 116 if (extack && !extack->_msg) 117 NL_SET_ERR_MSG_MOD(extack, 118 "error setting offload flag on port"); 119 return err; 120 } 121 122 return 0; 123 } 124 125 void 126 br_switchdev_fdb_notify(struct net_bridge *br, 127 const struct net_bridge_fdb_entry *fdb, int type) 128 { 129 const struct net_bridge_port *dst = READ_ONCE(fdb->dst); 130 struct switchdev_notifier_fdb_info info = { 131 .addr = fdb->key.addr.addr, 132 .vid = fdb->key.vlan_id, 133 .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), 134 .is_local = test_bit(BR_FDB_LOCAL, &fdb->flags), 135 .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), 136 }; 137 struct net_device *dev = (!dst || info.is_local) ? br->dev : dst->dev; 138 139 switch (type) { 140 case RTM_DELNEIGH: 141 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, 142 dev, &info.info, NULL); 143 break; 144 case RTM_NEWNEIGH: 145 call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, 146 dev, &info.info, NULL); 147 break; 148 } 149 } 150 151 int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, 152 struct netlink_ext_ack *extack) 153 { 154 struct switchdev_obj_port_vlan v = { 155 .obj.orig_dev = dev, 156 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 157 .flags = flags, 158 .vid = vid, 159 }; 160 161 return switchdev_port_obj_add(dev, &v.obj, extack); 162 } 163 164 int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid) 165 { 166 struct switchdev_obj_port_vlan v = { 167 .obj.orig_dev = dev, 168 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 169 .vid = vid, 170 }; 171 172 return switchdev_port_obj_del(dev, &v.obj); 173 } 174 175 static int nbp_switchdev_hwdom_set(struct net_bridge_port *joining) 176 { 177 struct net_bridge *br = joining->br; 178 struct net_bridge_port *p; 179 int hwdom; 180 181 /* joining is yet to be added to the port list. */ 182 list_for_each_entry(p, &br->port_list, list) { 183 if (netdev_phys_item_id_same(&joining->ppid, &p->ppid)) { 184 joining->hwdom = p->hwdom; 185 return 0; 186 } 187 } 188 189 hwdom = find_next_zero_bit(&br->busy_hwdoms, BR_HWDOM_MAX, 1); 190 if (hwdom >= BR_HWDOM_MAX) 191 return -EBUSY; 192 193 set_bit(hwdom, &br->busy_hwdoms); 194 joining->hwdom = hwdom; 195 return 0; 196 } 197 198 static void nbp_switchdev_hwdom_put(struct net_bridge_port *leaving) 199 { 200 struct net_bridge *br = leaving->br; 201 struct net_bridge_port *p; 202 203 /* leaving is no longer in the port list. */ 204 list_for_each_entry(p, &br->port_list, list) { 205 if (p->hwdom == leaving->hwdom) 206 return; 207 } 208 209 clear_bit(leaving->hwdom, &br->busy_hwdoms); 210 } 211 212 static int nbp_switchdev_add(struct net_bridge_port *p, 213 struct netdev_phys_item_id ppid, 214 bool tx_fwd_offload, 215 struct netlink_ext_ack *extack) 216 { 217 int err; 218 219 if (p->offload_count) { 220 /* Prevent unsupported configurations such as a bridge port 221 * which is a bonding interface, and the member ports are from 222 * different hardware switches. 223 */ 224 if (!netdev_phys_item_id_same(&p->ppid, &ppid)) { 225 NL_SET_ERR_MSG_MOD(extack, 226 "Same bridge port cannot be offloaded by two physical switches"); 227 return -EBUSY; 228 } 229 230 /* Tolerate drivers that call switchdev_bridge_port_offload() 231 * more than once for the same bridge port, such as when the 232 * bridge port is an offloaded bonding/team interface. 233 */ 234 p->offload_count++; 235 236 return 0; 237 } 238 239 p->ppid = ppid; 240 p->offload_count = 1; 241 242 err = nbp_switchdev_hwdom_set(p); 243 if (err) 244 return err; 245 246 if (tx_fwd_offload) { 247 p->flags |= BR_TX_FWD_OFFLOAD; 248 static_branch_inc(&br_switchdev_tx_fwd_offload); 249 } 250 251 return 0; 252 } 253 254 static void nbp_switchdev_del(struct net_bridge_port *p) 255 { 256 if (WARN_ON(!p->offload_count)) 257 return; 258 259 p->offload_count--; 260 261 if (p->offload_count) 262 return; 263 264 if (p->hwdom) 265 nbp_switchdev_hwdom_put(p); 266 267 if (p->flags & BR_TX_FWD_OFFLOAD) { 268 p->flags &= ~BR_TX_FWD_OFFLOAD; 269 static_branch_dec(&br_switchdev_tx_fwd_offload); 270 } 271 } 272 273 static int nbp_switchdev_sync_objs(struct net_bridge_port *p, const void *ctx, 274 struct notifier_block *atomic_nb, 275 struct notifier_block *blocking_nb, 276 struct netlink_ext_ack *extack) 277 { 278 struct net_device *br_dev = p->br->dev; 279 struct net_device *dev = p->dev; 280 int err; 281 282 err = br_vlan_replay(br_dev, dev, ctx, true, blocking_nb, extack); 283 if (err && err != -EOPNOTSUPP) 284 return err; 285 286 err = br_mdb_replay(br_dev, dev, ctx, true, blocking_nb, extack); 287 if (err && err != -EOPNOTSUPP) 288 return err; 289 290 err = br_fdb_replay(br_dev, ctx, true, atomic_nb); 291 if (err && err != -EOPNOTSUPP) 292 return err; 293 294 return 0; 295 } 296 297 static void nbp_switchdev_unsync_objs(struct net_bridge_port *p, 298 const void *ctx, 299 struct notifier_block *atomic_nb, 300 struct notifier_block *blocking_nb) 301 { 302 struct net_device *br_dev = p->br->dev; 303 struct net_device *dev = p->dev; 304 305 br_vlan_replay(br_dev, dev, ctx, false, blocking_nb, NULL); 306 307 br_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL); 308 309 br_fdb_replay(br_dev, ctx, false, atomic_nb); 310 } 311 312 /* Let the bridge know that this port is offloaded, so that it can assign a 313 * switchdev hardware domain to it. 314 */ 315 int br_switchdev_port_offload(struct net_bridge_port *p, 316 struct net_device *dev, const void *ctx, 317 struct notifier_block *atomic_nb, 318 struct notifier_block *blocking_nb, 319 bool tx_fwd_offload, 320 struct netlink_ext_ack *extack) 321 { 322 struct netdev_phys_item_id ppid; 323 int err; 324 325 err = dev_get_port_parent_id(dev, &ppid, false); 326 if (err) 327 return err; 328 329 err = nbp_switchdev_add(p, ppid, tx_fwd_offload, extack); 330 if (err) 331 return err; 332 333 err = nbp_switchdev_sync_objs(p, ctx, atomic_nb, blocking_nb, extack); 334 if (err) 335 goto out_switchdev_del; 336 337 return 0; 338 339 out_switchdev_del: 340 nbp_switchdev_del(p); 341 342 return err; 343 } 344 345 void br_switchdev_port_unoffload(struct net_bridge_port *p, const void *ctx, 346 struct notifier_block *atomic_nb, 347 struct notifier_block *blocking_nb) 348 { 349 nbp_switchdev_unsync_objs(p, ctx, atomic_nb, blocking_nb); 350 351 nbp_switchdev_del(p); 352 } 353