Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: bridge: extend the process of special frames

This patch extends the processing of frames in the bridge. Currently MRP
frames needs special processing and the current implementation doesn't
allow a nice way to process different frame types. Therefore try to
improve this by adding a list that contains frame types that need
special processing. This list is iterated for each input frame and if
there is a match based on frame type then these functions will be called
and decide what to do with the frame. It can process the frame then the
bridge doesn't need to do anything or don't process so then the bridge
will do normal forwarding.

Signed-off-by: Henrik Bjoernlund <henrik.bjoernlund@microchip.com>
Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Henrik Bjoernlund and committed by
Jakub Kicinski
90c628dd ae8a6e6e

+60 -12
+1
net/bridge/br_device.c
··· 454 454 spin_lock_init(&br->lock); 455 455 INIT_LIST_HEAD(&br->port_list); 456 456 INIT_HLIST_HEAD(&br->fdb_list); 457 + INIT_HLIST_HEAD(&br->frame_type_list); 457 458 #if IS_ENABLED(CONFIG_BRIDGE_MRP) 458 459 INIT_LIST_HEAD(&br->mrp_list); 459 460 #endif
+32 -1
net/bridge/br_input.c
··· 254 254 return RX_HANDLER_CONSUMED; 255 255 } 256 256 257 + /* Return 0 if the frame was not processed otherwise 1 258 + * note: already called with rcu_read_lock 259 + */ 260 + static int br_process_frame_type(struct net_bridge_port *p, 261 + struct sk_buff *skb) 262 + { 263 + struct br_frame_type *tmp; 264 + 265 + hlist_for_each_entry_rcu(tmp, &p->br->frame_type_list, list) 266 + if (unlikely(tmp->type == skb->protocol)) 267 + return tmp->frame_handler(p, skb); 268 + 269 + return 0; 270 + } 271 + 257 272 /* 258 273 * Return NULL if skb is handled 259 274 * note: already called with rcu_read_lock ··· 358 343 } 359 344 } 360 345 361 - if (unlikely(br_mrp_process(p, skb))) 346 + if (unlikely(br_process_frame_type(p, skb))) 362 347 return RX_HANDLER_PASS; 363 348 364 349 forward: ··· 394 379 return br_handle_frame_dummy; 395 380 396 381 return br_handle_frame; 382 + } 383 + 384 + void br_add_frame(struct net_bridge *br, struct br_frame_type *ft) 385 + { 386 + hlist_add_head_rcu(&ft->list, &br->frame_type_list); 387 + } 388 + 389 + void br_del_frame(struct net_bridge *br, struct br_frame_type *ft) 390 + { 391 + struct br_frame_type *tmp; 392 + 393 + hlist_for_each_entry(tmp, &br->frame_type_list, list) 394 + if (ft == tmp) { 395 + hlist_del_rcu(&ft->list); 396 + return; 397 + } 397 398 }
+15 -4
net/bridge/br_mrp.c
··· 6 6 static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 }; 7 7 static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 }; 8 8 9 + static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb); 10 + 11 + static struct br_frame_type mrp_frame_type __read_mostly = { 12 + .type = cpu_to_be16(ETH_P_MRP), 13 + .frame_handler = br_mrp_process, 14 + }; 15 + 9 16 static bool br_mrp_is_ring_port(struct net_bridge_port *p_port, 10 17 struct net_bridge_port *s_port, 11 18 struct net_bridge_port *port) ··· 452 445 453 446 list_del_rcu(&mrp->list); 454 447 kfree_rcu(mrp, rcu); 448 + 449 + if (list_empty(&br->mrp_list)) 450 + br_del_frame(br, &mrp_frame_type); 455 451 } 456 452 457 453 /* Adds a new MRP instance. ··· 502 492 p->flags |= BR_MRP_AWARE; 503 493 spin_unlock_bh(&br->lock); 504 494 rcu_assign_pointer(mrp->s_port, p); 495 + 496 + if (list_empty(&br->mrp_list)) 497 + br_add_frame(br, &mrp_frame_type); 505 498 506 499 INIT_DELAYED_WORK(&mrp->test_work, br_mrp_test_work_expired); 507 500 INIT_DELAYED_WORK(&mrp->in_test_work, br_mrp_in_test_work_expired); ··· 1185 1172 * normal forwarding. 1186 1173 * note: already called with rcu_read_lock 1187 1174 */ 1188 - int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) 1175 + static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) 1189 1176 { 1190 1177 /* If there is no MRP instance do normal forwarding */ 1191 1178 if (likely(!(p->flags & BR_MRP_AWARE))) 1192 1179 goto out; 1193 1180 1194 - if (unlikely(skb->protocol == htons(ETH_P_MRP))) 1195 - return br_mrp_rcv(p, skb, p->dev); 1196 - 1181 + return br_mrp_rcv(p, skb, p->dev); 1197 1182 out: 1198 1183 return 0; 1199 1184 }
+12 -7
net/bridge/br_private.h
··· 383 383 struct net_bridge { 384 384 spinlock_t lock; 385 385 spinlock_t hash_lock; 386 - struct list_head port_list; 386 + struct hlist_head frame_type_list; 387 387 struct net_device *dev; 388 388 struct pcpu_sw_netstats __percpu *stats; 389 389 unsigned long options; ··· 395 395 #endif 396 396 397 397 struct rhashtable fdb_hash_tbl; 398 + struct list_head port_list; 398 399 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 399 400 union { 400 401 struct rtable fake_rtable; ··· 755 754 /* br_input.c */ 756 755 int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); 757 756 rx_handler_func_t *br_get_rx_handler(const struct net_device *dev); 757 + 758 + struct br_frame_type { 759 + __be16 type; 760 + int (*frame_handler)(struct net_bridge_port *port, 761 + struct sk_buff *skb); 762 + struct hlist_node list; 763 + }; 764 + 765 + void br_add_frame(struct net_bridge *br, struct br_frame_type *ft); 766 + void br_del_frame(struct net_bridge *br, struct br_frame_type *ft); 758 767 759 768 static inline bool br_rx_handler_check_rcu(const struct net_device *dev) 760 769 { ··· 1428 1417 #if IS_ENABLED(CONFIG_BRIDGE_MRP) 1429 1418 int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, 1430 1419 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack); 1431 - int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb); 1432 1420 bool br_mrp_enabled(struct net_bridge *br); 1433 1421 void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p); 1434 1422 int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br); ··· 1437 1427 struct netlink_ext_ack *extack) 1438 1428 { 1439 1429 return -EOPNOTSUPP; 1440 - } 1441 - 1442 - static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) 1443 - { 1444 - return 0; 1445 1430 } 1446 1431 1447 1432 static inline bool br_mrp_enabled(struct net_bridge *br)