| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Linux ethernet bridge |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Authors: |
|---|
| 5 | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify it under the terms of the GNU General Public License |
|---|
| 9 | | - * as published by the Free Software Foundation; either version |
|---|
| 10 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #ifndef _BR_PRIVATE_H |
|---|
| .. | .. |
|---|
| 31 | 27 | #define BR_PORT_BITS 10 |
|---|
| 32 | 28 | #define BR_MAX_PORTS (1<<BR_PORT_BITS) |
|---|
| 33 | 29 | |
|---|
| 30 | +#define BR_MULTICAST_DEFAULT_HASH_MAX 4096 |
|---|
| 31 | + |
|---|
| 34 | 32 | #define BR_VERSION "2.3" |
|---|
| 35 | 33 | |
|---|
| 36 | 34 | /* Control of forwarding link local multicast */ |
|---|
| .. | .. |
|---|
| 50 | 48 | /* Path to usermode spanning tree program */ |
|---|
| 51 | 49 | #define BR_STP_PROG "/sbin/bridge-stp" |
|---|
| 52 | 50 | |
|---|
| 51 | +#define BR_FDB_NOTIFY_SETTABLE_BITS (FDB_NOTIFY_BIT | FDB_NOTIFY_INACTIVE_BIT) |
|---|
| 52 | + |
|---|
| 53 | 53 | typedef struct bridge_id bridge_id; |
|---|
| 54 | 54 | typedef struct mac_addr mac_addr; |
|---|
| 55 | 55 | typedef __u16 port_id; |
|---|
| 56 | 56 | |
|---|
| 57 | | -struct bridge_id |
|---|
| 58 | | -{ |
|---|
| 57 | +struct bridge_id { |
|---|
| 59 | 58 | unsigned char prio[2]; |
|---|
| 60 | 59 | unsigned char addr[ETH_ALEN]; |
|---|
| 61 | 60 | }; |
|---|
| 62 | 61 | |
|---|
| 63 | | -struct mac_addr |
|---|
| 64 | | -{ |
|---|
| 62 | +struct mac_addr { |
|---|
| 65 | 63 | unsigned char addr[ETH_ALEN]; |
|---|
| 66 | 64 | }; |
|---|
| 67 | 65 | |
|---|
| .. | .. |
|---|
| 104 | 102 | struct metadata_dst __rcu *tunnel_dst; |
|---|
| 105 | 103 | }; |
|---|
| 106 | 104 | |
|---|
| 105 | +/* private vlan flags */ |
|---|
| 106 | +enum { |
|---|
| 107 | + BR_VLFLAG_PER_PORT_STATS = BIT(0), |
|---|
| 108 | + BR_VLFLAG_ADDED_BY_SWITCHDEV = BIT(1), |
|---|
| 109 | +}; |
|---|
| 110 | + |
|---|
| 107 | 111 | /** |
|---|
| 108 | 112 | * struct net_bridge_vlan - per-vlan entry |
|---|
| 109 | 113 | * |
|---|
| 110 | 114 | * @vnode: rhashtable member |
|---|
| 111 | 115 | * @vid: VLAN id |
|---|
| 112 | 116 | * @flags: bridge vlan flags |
|---|
| 117 | + * @priv_flags: private (in-kernel) bridge vlan flags |
|---|
| 118 | + * @state: STP state (e.g. blocking, learning, forwarding) |
|---|
| 113 | 119 | * @stats: per-cpu VLAN statistics |
|---|
| 114 | 120 | * @br: if MASTER flag set, this points to a bridge struct |
|---|
| 115 | 121 | * @port: if MASTER flag unset, this points to a port struct |
|---|
| .. | .. |
|---|
| 129 | 135 | struct rhash_head tnode; |
|---|
| 130 | 136 | u16 vid; |
|---|
| 131 | 137 | u16 flags; |
|---|
| 138 | + u16 priv_flags; |
|---|
| 139 | + u8 state; |
|---|
| 132 | 140 | struct br_vlan_stats __percpu *stats; |
|---|
| 133 | 141 | union { |
|---|
| 134 | 142 | struct net_bridge *br; |
|---|
| .. | .. |
|---|
| 153 | 161 | * @vlan_list: sorted VLAN entry list |
|---|
| 154 | 162 | * @num_vlans: number of total VLAN entries |
|---|
| 155 | 163 | * @pvid: PVID VLAN id |
|---|
| 164 | + * @pvid_state: PVID's STP state (e.g. forwarding, learning, blocking) |
|---|
| 156 | 165 | * |
|---|
| 157 | 166 | * IMPORTANT: Be careful when checking if there're VLAN entries using list |
|---|
| 158 | 167 | * primitives because the bridge can have entries in its list which |
|---|
| .. | .. |
|---|
| 166 | 175 | struct list_head vlan_list; |
|---|
| 167 | 176 | u16 num_vlans; |
|---|
| 168 | 177 | u16 pvid; |
|---|
| 178 | + u8 pvid_state; |
|---|
| 179 | +}; |
|---|
| 180 | + |
|---|
| 181 | +/* bridge fdb flags */ |
|---|
| 182 | +enum { |
|---|
| 183 | + BR_FDB_LOCAL, |
|---|
| 184 | + BR_FDB_STATIC, |
|---|
| 185 | + BR_FDB_STICKY, |
|---|
| 186 | + BR_FDB_ADDED_BY_USER, |
|---|
| 187 | + BR_FDB_ADDED_BY_EXT_LEARN, |
|---|
| 188 | + BR_FDB_OFFLOADED, |
|---|
| 189 | + BR_FDB_NOTIFY, |
|---|
| 190 | + BR_FDB_NOTIFY_INACTIVE |
|---|
| 169 | 191 | }; |
|---|
| 170 | 192 | |
|---|
| 171 | 193 | struct net_bridge_fdb_key { |
|---|
| .. | .. |
|---|
| 179 | 201 | |
|---|
| 180 | 202 | struct net_bridge_fdb_key key; |
|---|
| 181 | 203 | struct hlist_node fdb_node; |
|---|
| 182 | | - unsigned char is_local:1, |
|---|
| 183 | | - is_static:1, |
|---|
| 184 | | - added_by_user:1, |
|---|
| 185 | | - added_by_external_learn:1, |
|---|
| 186 | | - offloaded:1; |
|---|
| 204 | + unsigned long flags; |
|---|
| 187 | 205 | |
|---|
| 188 | 206 | /* write-heavy members should not affect lookups */ |
|---|
| 189 | 207 | unsigned long updated ____cacheline_aligned_in_smp; |
|---|
| .. | .. |
|---|
| 194 | 212 | |
|---|
| 195 | 213 | #define MDB_PG_FLAGS_PERMANENT BIT(0) |
|---|
| 196 | 214 | #define MDB_PG_FLAGS_OFFLOAD BIT(1) |
|---|
| 215 | +#define MDB_PG_FLAGS_FAST_LEAVE BIT(2) |
|---|
| 216 | +#define MDB_PG_FLAGS_STAR_EXCL BIT(3) |
|---|
| 217 | +#define MDB_PG_FLAGS_BLOCKED BIT(4) |
|---|
| 218 | + |
|---|
| 219 | +#define PG_SRC_ENT_LIMIT 32 |
|---|
| 220 | + |
|---|
| 221 | +#define BR_SGRP_F_DELETE BIT(0) |
|---|
| 222 | +#define BR_SGRP_F_SEND BIT(1) |
|---|
| 223 | +#define BR_SGRP_F_INSTALLED BIT(2) |
|---|
| 224 | + |
|---|
| 225 | +struct net_bridge_mcast_gc { |
|---|
| 226 | + struct hlist_node gc_node; |
|---|
| 227 | + void (*destroy)(struct net_bridge_mcast_gc *gc); |
|---|
| 228 | +}; |
|---|
| 229 | + |
|---|
| 230 | +struct net_bridge_group_src { |
|---|
| 231 | + struct hlist_node node; |
|---|
| 232 | + |
|---|
| 233 | + struct br_ip addr; |
|---|
| 234 | + struct net_bridge_port_group *pg; |
|---|
| 235 | + u8 flags; |
|---|
| 236 | + u8 src_query_rexmit_cnt; |
|---|
| 237 | + struct timer_list timer; |
|---|
| 238 | + |
|---|
| 239 | + struct net_bridge *br; |
|---|
| 240 | + struct net_bridge_mcast_gc mcast_gc; |
|---|
| 241 | + struct rcu_head rcu; |
|---|
| 242 | +}; |
|---|
| 243 | + |
|---|
| 244 | +struct net_bridge_port_group_sg_key { |
|---|
| 245 | + struct net_bridge_port *port; |
|---|
| 246 | + struct br_ip addr; |
|---|
| 247 | +}; |
|---|
| 197 | 248 | |
|---|
| 198 | 249 | struct net_bridge_port_group { |
|---|
| 199 | | - struct net_bridge_port *port; |
|---|
| 200 | 250 | struct net_bridge_port_group __rcu *next; |
|---|
| 201 | | - struct hlist_node mglist; |
|---|
| 202 | | - struct rcu_head rcu; |
|---|
| 203 | | - struct timer_list timer; |
|---|
| 204 | | - struct br_ip addr; |
|---|
| 251 | + struct net_bridge_port_group_sg_key key; |
|---|
| 205 | 252 | unsigned char eth_addr[ETH_ALEN] __aligned(2); |
|---|
| 206 | 253 | unsigned char flags; |
|---|
| 254 | + unsigned char filter_mode; |
|---|
| 255 | + unsigned char grp_query_rexmit_cnt; |
|---|
| 256 | + unsigned char rt_protocol; |
|---|
| 257 | + |
|---|
| 258 | + struct hlist_head src_list; |
|---|
| 259 | + unsigned int src_ents; |
|---|
| 260 | + struct timer_list timer; |
|---|
| 261 | + struct timer_list rexmit_timer; |
|---|
| 262 | + struct hlist_node mglist; |
|---|
| 263 | + |
|---|
| 264 | + struct rhash_head rhnode; |
|---|
| 265 | + struct net_bridge_mcast_gc mcast_gc; |
|---|
| 266 | + struct rcu_head rcu; |
|---|
| 207 | 267 | }; |
|---|
| 208 | 268 | |
|---|
| 209 | | -struct net_bridge_mdb_entry |
|---|
| 210 | | -{ |
|---|
| 211 | | - struct hlist_node hlist[2]; |
|---|
| 269 | +struct net_bridge_mdb_entry { |
|---|
| 270 | + struct rhash_head rhnode; |
|---|
| 212 | 271 | struct net_bridge *br; |
|---|
| 213 | 272 | struct net_bridge_port_group __rcu *ports; |
|---|
| 214 | | - struct rcu_head rcu; |
|---|
| 215 | | - struct timer_list timer; |
|---|
| 216 | 273 | struct br_ip addr; |
|---|
| 217 | 274 | bool host_joined; |
|---|
| 218 | | -}; |
|---|
| 219 | 275 | |
|---|
| 220 | | -struct net_bridge_mdb_htable |
|---|
| 221 | | -{ |
|---|
| 222 | | - struct hlist_head *mhash; |
|---|
| 276 | + struct timer_list timer; |
|---|
| 277 | + struct hlist_node mdb_node; |
|---|
| 278 | + |
|---|
| 279 | + struct net_bridge_mcast_gc mcast_gc; |
|---|
| 223 | 280 | struct rcu_head rcu; |
|---|
| 224 | | - struct net_bridge_mdb_htable *old; |
|---|
| 225 | | - u32 size; |
|---|
| 226 | | - u32 max; |
|---|
| 227 | | - u32 secret; |
|---|
| 228 | | - u32 ver; |
|---|
| 229 | 281 | }; |
|---|
| 230 | 282 | |
|---|
| 231 | 283 | struct net_bridge_port { |
|---|
| .. | .. |
|---|
| 283 | 335 | #endif |
|---|
| 284 | 336 | u16 group_fwd_mask; |
|---|
| 285 | 337 | u16 backup_redirected_cnt; |
|---|
| 338 | + |
|---|
| 339 | + struct bridge_stp_xstats stp_xstats; |
|---|
| 286 | 340 | }; |
|---|
| 287 | 341 | |
|---|
| 288 | 342 | #define kobj_to_brport(obj) container_of(obj, struct net_bridge_port, kobj) |
|---|
| 289 | 343 | |
|---|
| 290 | 344 | #define br_auto_port(p) ((p)->flags & BR_AUTO_MASK) |
|---|
| 291 | 345 | #define br_promisc_port(p) ((p)->flags & BR_PROMISC) |
|---|
| 292 | | - |
|---|
| 293 | | -#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT) |
|---|
| 294 | 346 | |
|---|
| 295 | 347 | static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) |
|---|
| 296 | 348 | { |
|---|
| .. | .. |
|---|
| 299 | 351 | |
|---|
| 300 | 352 | static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *dev) |
|---|
| 301 | 353 | { |
|---|
| 302 | | - return br_port_exists(dev) ? |
|---|
| 354 | + return netif_is_bridge_port(dev) ? |
|---|
| 303 | 355 | rtnl_dereference(dev->rx_handler_data) : NULL; |
|---|
| 304 | 356 | } |
|---|
| 305 | 357 | |
|---|
| 306 | 358 | static inline struct net_bridge_port *br_port_get_rtnl_rcu(const struct net_device *dev) |
|---|
| 307 | 359 | { |
|---|
| 308 | | - return br_port_exists(dev) ? |
|---|
| 360 | + return netif_is_bridge_port(dev) ? |
|---|
| 309 | 361 | rcu_dereference_rtnl(dev->rx_handler_data) : NULL; |
|---|
| 310 | 362 | } |
|---|
| 363 | + |
|---|
| 364 | +enum net_bridge_opts { |
|---|
| 365 | + BROPT_VLAN_ENABLED, |
|---|
| 366 | + BROPT_VLAN_STATS_ENABLED, |
|---|
| 367 | + BROPT_NF_CALL_IPTABLES, |
|---|
| 368 | + BROPT_NF_CALL_IP6TABLES, |
|---|
| 369 | + BROPT_NF_CALL_ARPTABLES, |
|---|
| 370 | + BROPT_GROUP_ADDR_SET, |
|---|
| 371 | + BROPT_MULTICAST_ENABLED, |
|---|
| 372 | + BROPT_MULTICAST_QUERIER, |
|---|
| 373 | + BROPT_MULTICAST_QUERY_USE_IFADDR, |
|---|
| 374 | + BROPT_MULTICAST_STATS_ENABLED, |
|---|
| 375 | + BROPT_HAS_IPV6_ADDR, |
|---|
| 376 | + BROPT_NEIGH_SUPPRESS_ENABLED, |
|---|
| 377 | + BROPT_MTU_SET_BY_USER, |
|---|
| 378 | + BROPT_VLAN_STATS_PER_PORT, |
|---|
| 379 | + BROPT_NO_LL_LEARN, |
|---|
| 380 | + BROPT_VLAN_BRIDGE_BINDING, |
|---|
| 381 | +}; |
|---|
| 311 | 382 | |
|---|
| 312 | 383 | struct net_bridge { |
|---|
| 313 | 384 | spinlock_t lock; |
|---|
| .. | .. |
|---|
| 315 | 386 | struct list_head port_list; |
|---|
| 316 | 387 | struct net_device *dev; |
|---|
| 317 | 388 | struct pcpu_sw_netstats __percpu *stats; |
|---|
| 389 | + unsigned long options; |
|---|
| 318 | 390 | /* These fields are accessed on each packet */ |
|---|
| 319 | 391 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING |
|---|
| 320 | | - u8 vlan_enabled; |
|---|
| 321 | | - u8 vlan_stats_enabled; |
|---|
| 322 | 392 | __be16 vlan_proto; |
|---|
| 323 | 393 | u16 default_pvid; |
|---|
| 324 | 394 | struct net_bridge_vlan_group __rcu *vlgrp; |
|---|
| .. | .. |
|---|
| 330 | 400 | struct rtable fake_rtable; |
|---|
| 331 | 401 | struct rt6_info fake_rt6_info; |
|---|
| 332 | 402 | }; |
|---|
| 333 | | - bool nf_call_iptables; |
|---|
| 334 | | - bool nf_call_ip6tables; |
|---|
| 335 | | - bool nf_call_arptables; |
|---|
| 336 | 403 | #endif |
|---|
| 337 | 404 | u16 group_fwd_mask; |
|---|
| 338 | 405 | u16 group_fwd_mask_required; |
|---|
| .. | .. |
|---|
| 340 | 407 | /* STP */ |
|---|
| 341 | 408 | bridge_id designated_root; |
|---|
| 342 | 409 | bridge_id bridge_id; |
|---|
| 343 | | - u32 root_path_cost; |
|---|
| 344 | 410 | unsigned char topology_change; |
|---|
| 345 | 411 | unsigned char topology_change_detected; |
|---|
| 346 | 412 | u16 root_port; |
|---|
| .. | .. |
|---|
| 352 | 418 | unsigned long bridge_hello_time; |
|---|
| 353 | 419 | unsigned long bridge_forward_delay; |
|---|
| 354 | 420 | unsigned long bridge_ageing_time; |
|---|
| 421 | + u32 root_path_cost; |
|---|
| 355 | 422 | |
|---|
| 356 | 423 | u8 group_addr[ETH_ALEN]; |
|---|
| 357 | | - bool group_addr_set; |
|---|
| 358 | 424 | |
|---|
| 359 | 425 | enum { |
|---|
| 360 | 426 | BR_NO_STP, /* no spanning tree */ |
|---|
| .. | .. |
|---|
| 363 | 429 | } stp_enabled; |
|---|
| 364 | 430 | |
|---|
| 365 | 431 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
|---|
| 366 | | - unsigned char multicast_router; |
|---|
| 367 | 432 | |
|---|
| 368 | | - u8 multicast_disabled:1; |
|---|
| 369 | | - u8 multicast_querier:1; |
|---|
| 370 | | - u8 multicast_query_use_ifaddr:1; |
|---|
| 371 | | - u8 has_ipv6_addr:1; |
|---|
| 372 | | - u8 multicast_stats_enabled:1; |
|---|
| 373 | | - |
|---|
| 374 | | - u32 hash_elasticity; |
|---|
| 375 | 433 | u32 hash_max; |
|---|
| 376 | 434 | |
|---|
| 377 | 435 | u32 multicast_last_member_count; |
|---|
| 378 | 436 | u32 multicast_startup_query_count; |
|---|
| 379 | 437 | |
|---|
| 380 | 438 | u8 multicast_igmp_version; |
|---|
| 381 | | - |
|---|
| 439 | + u8 multicast_router; |
|---|
| 440 | +#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 441 | + u8 multicast_mld_version; |
|---|
| 442 | +#endif |
|---|
| 443 | + spinlock_t multicast_lock; |
|---|
| 382 | 444 | unsigned long multicast_last_member_interval; |
|---|
| 383 | 445 | unsigned long multicast_membership_interval; |
|---|
| 384 | 446 | unsigned long multicast_querier_interval; |
|---|
| .. | .. |
|---|
| 386 | 448 | unsigned long multicast_query_response_interval; |
|---|
| 387 | 449 | unsigned long multicast_startup_query_interval; |
|---|
| 388 | 450 | |
|---|
| 389 | | - spinlock_t multicast_lock; |
|---|
| 390 | | - struct net_bridge_mdb_htable __rcu *mdb; |
|---|
| 451 | + struct rhashtable mdb_hash_tbl; |
|---|
| 452 | + struct rhashtable sg_port_tbl; |
|---|
| 453 | + |
|---|
| 454 | + struct hlist_head mcast_gc_list; |
|---|
| 455 | + struct hlist_head mdb_list; |
|---|
| 391 | 456 | struct hlist_head router_list; |
|---|
| 392 | 457 | |
|---|
| 393 | 458 | struct timer_list multicast_router_timer; |
|---|
| .. | .. |
|---|
| 399 | 464 | struct bridge_mcast_other_query ip6_other_query; |
|---|
| 400 | 465 | struct bridge_mcast_own_query ip6_own_query; |
|---|
| 401 | 466 | struct bridge_mcast_querier ip6_querier; |
|---|
| 402 | | - u8 multicast_mld_version; |
|---|
| 403 | 467 | #endif /* IS_ENABLED(CONFIG_IPV6) */ |
|---|
| 468 | + struct work_struct mcast_gc_work; |
|---|
| 404 | 469 | #endif |
|---|
| 405 | 470 | |
|---|
| 406 | 471 | struct timer_list hello_timer; |
|---|
| .. | .. |
|---|
| 413 | 478 | #ifdef CONFIG_NET_SWITCHDEV |
|---|
| 414 | 479 | int offload_fwd_mark; |
|---|
| 415 | 480 | #endif |
|---|
| 416 | | - bool neigh_suppress_enabled; |
|---|
| 417 | | - bool mtu_set_by_user; |
|---|
| 418 | 481 | struct hlist_head fdb_list; |
|---|
| 482 | + |
|---|
| 483 | +#if IS_ENABLED(CONFIG_BRIDGE_MRP) |
|---|
| 484 | + struct list_head mrp_list; |
|---|
| 485 | +#endif |
|---|
| 419 | 486 | }; |
|---|
| 420 | 487 | |
|---|
| 421 | 488 | struct br_input_skb_cb { |
|---|
| 422 | 489 | struct net_device *brdev; |
|---|
| 423 | 490 | |
|---|
| 491 | + u16 frag_max_size; |
|---|
| 424 | 492 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
|---|
| 425 | | - int igmp; |
|---|
| 426 | | - int mrouters_only; |
|---|
| 493 | + u8 igmp; |
|---|
| 494 | + u8 mrouters_only:1; |
|---|
| 427 | 495 | #endif |
|---|
| 428 | | - |
|---|
| 429 | | - bool proxyarp_replied; |
|---|
| 430 | | - bool src_port_isolated; |
|---|
| 431 | | - |
|---|
| 496 | + u8 proxyarp_replied:1; |
|---|
| 497 | + u8 src_port_isolated:1; |
|---|
| 432 | 498 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING |
|---|
| 433 | | - bool vlan_filtered; |
|---|
| 499 | + u8 vlan_filtered:1; |
|---|
| 500 | +#endif |
|---|
| 501 | +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE |
|---|
| 502 | + u8 br_netfilter_broute:1; |
|---|
| 434 | 503 | #endif |
|---|
| 435 | 504 | |
|---|
| 436 | 505 | #ifdef CONFIG_NET_SWITCHDEV |
|---|
| .. | .. |
|---|
| 492 | 561 | return true; |
|---|
| 493 | 562 | } |
|---|
| 494 | 563 | |
|---|
| 564 | +static inline bool nbp_state_should_learn(const struct net_bridge_port *p) |
|---|
| 565 | +{ |
|---|
| 566 | + return p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING; |
|---|
| 567 | +} |
|---|
| 568 | + |
|---|
| 569 | +static inline bool br_vlan_valid_id(u16 vid, struct netlink_ext_ack *extack) |
|---|
| 570 | +{ |
|---|
| 571 | + bool ret = vid > 0 && vid < VLAN_VID_MASK; |
|---|
| 572 | + |
|---|
| 573 | + if (!ret) |
|---|
| 574 | + NL_SET_ERR_MSG_MOD(extack, "Vlan id is invalid"); |
|---|
| 575 | + |
|---|
| 576 | + return ret; |
|---|
| 577 | +} |
|---|
| 578 | + |
|---|
| 579 | +static inline bool br_vlan_valid_range(const struct bridge_vlan_info *cur, |
|---|
| 580 | + const struct bridge_vlan_info *last, |
|---|
| 581 | + struct netlink_ext_ack *extack) |
|---|
| 582 | +{ |
|---|
| 583 | + /* pvid flag is not allowed in ranges */ |
|---|
| 584 | + if (cur->flags & BRIDGE_VLAN_INFO_PVID) { |
|---|
| 585 | + NL_SET_ERR_MSG_MOD(extack, "Pvid isn't allowed in a range"); |
|---|
| 586 | + return false; |
|---|
| 587 | + } |
|---|
| 588 | + |
|---|
| 589 | + /* when cur is the range end, check if: |
|---|
| 590 | + * - it has range start flag |
|---|
| 591 | + * - range ids are invalid (end is equal to or before start) |
|---|
| 592 | + */ |
|---|
| 593 | + if (last) { |
|---|
| 594 | + if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { |
|---|
| 595 | + NL_SET_ERR_MSG_MOD(extack, "Found a new vlan range start while processing one"); |
|---|
| 596 | + return false; |
|---|
| 597 | + } else if (!(cur->flags & BRIDGE_VLAN_INFO_RANGE_END)) { |
|---|
| 598 | + NL_SET_ERR_MSG_MOD(extack, "Vlan range end flag is missing"); |
|---|
| 599 | + return false; |
|---|
| 600 | + } else if (cur->vid <= last->vid) { |
|---|
| 601 | + NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id"); |
|---|
| 602 | + return false; |
|---|
| 603 | + } |
|---|
| 604 | + } |
|---|
| 605 | + |
|---|
| 606 | + /* check for required range flags */ |
|---|
| 607 | + if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | |
|---|
| 608 | + BRIDGE_VLAN_INFO_RANGE_END))) { |
|---|
| 609 | + NL_SET_ERR_MSG_MOD(extack, "Both vlan range flags are missing"); |
|---|
| 610 | + return false; |
|---|
| 611 | + } |
|---|
| 612 | + |
|---|
| 613 | + return true; |
|---|
| 614 | +} |
|---|
| 615 | + |
|---|
| 616 | +static inline int br_afspec_cmd_to_rtm(int cmd) |
|---|
| 617 | +{ |
|---|
| 618 | + switch (cmd) { |
|---|
| 619 | + case RTM_SETLINK: |
|---|
| 620 | + return RTM_NEWVLAN; |
|---|
| 621 | + case RTM_DELLINK: |
|---|
| 622 | + return RTM_DELVLAN; |
|---|
| 623 | + } |
|---|
| 624 | + |
|---|
| 625 | + return 0; |
|---|
| 626 | +} |
|---|
| 627 | + |
|---|
| 628 | +static inline int br_opt_get(const struct net_bridge *br, |
|---|
| 629 | + enum net_bridge_opts opt) |
|---|
| 630 | +{ |
|---|
| 631 | + return test_bit(opt, &br->options); |
|---|
| 632 | +} |
|---|
| 633 | + |
|---|
| 634 | +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on, |
|---|
| 635 | + struct netlink_ext_ack *extack); |
|---|
| 636 | +int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt); |
|---|
| 637 | +int br_boolopt_multi_toggle(struct net_bridge *br, |
|---|
| 638 | + struct br_boolopt_multi *bm, |
|---|
| 639 | + struct netlink_ext_ack *extack); |
|---|
| 640 | +void br_boolopt_multi_get(const struct net_bridge *br, |
|---|
| 641 | + struct br_boolopt_multi *bm); |
|---|
| 642 | +void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on); |
|---|
| 643 | + |
|---|
| 495 | 644 | /* br_device.c */ |
|---|
| 496 | 645 | void br_dev_setup(struct net_device *dev); |
|---|
| 497 | 646 | void br_dev_delete(struct net_device *dev, struct list_head *list); |
|---|
| .. | .. |
|---|
| 500 | 649 | static inline void br_netpoll_send_skb(const struct net_bridge_port *p, |
|---|
| 501 | 650 | struct sk_buff *skb) |
|---|
| 502 | 651 | { |
|---|
| 503 | | - struct netpoll *np = p->np; |
|---|
| 504 | | - |
|---|
| 505 | | - if (np) |
|---|
| 506 | | - netpoll_send_skb(np, skb); |
|---|
| 652 | + netpoll_send_skb(p->np, skb); |
|---|
| 507 | 653 | } |
|---|
| 508 | 654 | |
|---|
| 509 | 655 | int br_netpoll_enable(struct net_bridge_port *p); |
|---|
| .. | .. |
|---|
| 547 | 693 | int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
|---|
| 548 | 694 | const unsigned char *addr, u16 vid); |
|---|
| 549 | 695 | void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, |
|---|
| 550 | | - const unsigned char *addr, u16 vid, bool added_by_user); |
|---|
| 696 | + const unsigned char *addr, u16 vid, unsigned long flags); |
|---|
| 551 | 697 | |
|---|
| 552 | 698 | int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], |
|---|
| 553 | 699 | struct net_device *dev, const unsigned char *addr, u16 vid); |
|---|
| 554 | 700 | int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, |
|---|
| 555 | | - const unsigned char *addr, u16 vid, u16 nlh_flags); |
|---|
| 701 | + const unsigned char *addr, u16 vid, u16 nlh_flags, |
|---|
| 702 | + struct netlink_ext_ack *extack); |
|---|
| 556 | 703 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, |
|---|
| 557 | 704 | struct net_device *dev, struct net_device *fdev, int *idx); |
|---|
| 705 | +int br_fdb_get(struct sk_buff *skb, struct nlattr *tb[], struct net_device *dev, |
|---|
| 706 | + const unsigned char *addr, u16 vid, u32 portid, u32 seq, |
|---|
| 707 | + struct netlink_ext_ack *extack); |
|---|
| 558 | 708 | int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); |
|---|
| 559 | 709 | void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); |
|---|
| 560 | 710 | int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, |
|---|
| .. | .. |
|---|
| 564 | 714 | const unsigned char *addr, u16 vid, |
|---|
| 565 | 715 | bool swdev_notify); |
|---|
| 566 | 716 | void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p, |
|---|
| 567 | | - const unsigned char *addr, u16 vid); |
|---|
| 717 | + const unsigned char *addr, u16 vid, bool offloaded); |
|---|
| 568 | 718 | |
|---|
| 569 | 719 | /* br_forward.c */ |
|---|
| 570 | 720 | enum br_pkt_type { |
|---|
| .. | .. |
|---|
| 603 | 753 | |
|---|
| 604 | 754 | /* br_input.c */ |
|---|
| 605 | 755 | int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); |
|---|
| 606 | | -rx_handler_result_t br_handle_frame(struct sk_buff **pskb); |
|---|
| 756 | +rx_handler_func_t *br_get_rx_handler(const struct net_device *dev); |
|---|
| 607 | 757 | |
|---|
| 608 | 758 | static inline bool br_rx_handler_check_rcu(const struct net_device *dev) |
|---|
| 609 | 759 | { |
|---|
| 610 | | - return rcu_dereference(dev->rx_handler) == br_handle_frame; |
|---|
| 760 | + return rcu_dereference(dev->rx_handler) == br_get_rx_handler(dev); |
|---|
| 611 | 761 | } |
|---|
| 612 | 762 | |
|---|
| 613 | 763 | static inline bool br_rx_handler_check_rtnl(const struct net_device *dev) |
|---|
| 614 | 764 | { |
|---|
| 615 | | - return rcu_dereference_rtnl(dev->rx_handler) == br_handle_frame; |
|---|
| 765 | + return rcu_dereference_rtnl(dev->rx_handler) == br_get_rx_handler(dev); |
|---|
| 616 | 766 | } |
|---|
| 617 | 767 | |
|---|
| 618 | 768 | static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev) |
|---|
| .. | .. |
|---|
| 633 | 783 | |
|---|
| 634 | 784 | /* br_multicast.c */ |
|---|
| 635 | 785 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
|---|
| 636 | | -extern unsigned int br_mdb_rehash_seq; |
|---|
| 637 | 786 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, |
|---|
| 638 | 787 | struct sk_buff *skb, u16 vid); |
|---|
| 639 | 788 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, |
|---|
| .. | .. |
|---|
| 643 | 792 | void br_multicast_enable_port(struct net_bridge_port *port); |
|---|
| 644 | 793 | void br_multicast_disable_port(struct net_bridge_port *port); |
|---|
| 645 | 794 | void br_multicast_init(struct net_bridge *br); |
|---|
| 795 | +void br_multicast_join_snoopers(struct net_bridge *br); |
|---|
| 796 | +void br_multicast_leave_snoopers(struct net_bridge *br); |
|---|
| 646 | 797 | void br_multicast_open(struct net_bridge *br); |
|---|
| 647 | 798 | void br_multicast_stop(struct net_bridge *br); |
|---|
| 648 | 799 | void br_multicast_dev_del(struct net_bridge *br); |
|---|
| .. | .. |
|---|
| 658 | 809 | int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val); |
|---|
| 659 | 810 | #endif |
|---|
| 660 | 811 | struct net_bridge_mdb_entry * |
|---|
| 661 | | -br_mdb_ip_get(struct net_bridge_mdb_htable *mdb, struct br_ip *dst); |
|---|
| 812 | +br_mdb_ip_get(struct net_bridge *br, struct br_ip *dst); |
|---|
| 662 | 813 | struct net_bridge_mdb_entry * |
|---|
| 663 | | -br_multicast_new_group(struct net_bridge *br, struct net_bridge_port *port, |
|---|
| 664 | | - struct br_ip *group); |
|---|
| 665 | | -void br_multicast_free_pg(struct rcu_head *head); |
|---|
| 814 | +br_multicast_new_group(struct net_bridge *br, struct br_ip *group); |
|---|
| 666 | 815 | struct net_bridge_port_group * |
|---|
| 667 | 816 | br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, |
|---|
| 668 | 817 | struct net_bridge_port_group __rcu *next, |
|---|
| 669 | | - unsigned char flags, const unsigned char *src); |
|---|
| 670 | | -void br_mdb_init(void); |
|---|
| 671 | | -void br_mdb_uninit(void); |
|---|
| 672 | | -void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
|---|
| 673 | | - struct br_ip *group, int type, u8 flags); |
|---|
| 818 | + unsigned char flags, const unsigned char *src, |
|---|
| 819 | + u8 filter_mode, u8 rt_protocol); |
|---|
| 820 | +int br_mdb_hash_init(struct net_bridge *br); |
|---|
| 821 | +void br_mdb_hash_fini(struct net_bridge *br); |
|---|
| 822 | +void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, |
|---|
| 823 | + struct net_bridge_port_group *pg, int type); |
|---|
| 674 | 824 | void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, |
|---|
| 675 | 825 | int type); |
|---|
| 826 | +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, |
|---|
| 827 | + struct net_bridge_port_group *pg, |
|---|
| 828 | + struct net_bridge_port_group __rcu **pp); |
|---|
| 676 | 829 | void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, |
|---|
| 677 | 830 | const struct sk_buff *skb, u8 type, u8 dir); |
|---|
| 678 | 831 | int br_multicast_init_stats(struct net_bridge *br); |
|---|
| .. | .. |
|---|
| 680 | 833 | void br_multicast_get_stats(const struct net_bridge *br, |
|---|
| 681 | 834 | const struct net_bridge_port *p, |
|---|
| 682 | 835 | struct br_mcast_stats *dest); |
|---|
| 836 | +void br_mdb_init(void); |
|---|
| 837 | +void br_mdb_uninit(void); |
|---|
| 838 | +void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify); |
|---|
| 839 | +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify); |
|---|
| 840 | +void br_multicast_star_g_handle_mode(struct net_bridge_port_group *pg, |
|---|
| 841 | + u8 filter_mode); |
|---|
| 842 | +void br_multicast_sg_add_exclude_ports(struct net_bridge_mdb_entry *star_mp, |
|---|
| 843 | + struct net_bridge_port_group *sg); |
|---|
| 683 | 844 | |
|---|
| 684 | 845 | #define mlock_dereference(X, br) \ |
|---|
| 685 | 846 | rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) |
|---|
| .. | .. |
|---|
| 698 | 859 | { |
|---|
| 699 | 860 | bool own_querier_enabled; |
|---|
| 700 | 861 | |
|---|
| 701 | | - if (br->multicast_querier) { |
|---|
| 702 | | - if (is_ipv6 && !br->has_ipv6_addr) |
|---|
| 862 | + if (br_opt_get(br, BROPT_MULTICAST_QUERIER)) { |
|---|
| 863 | + if (is_ipv6 && !br_opt_get(br, BROPT_HAS_IPV6_ADDR)) |
|---|
| 703 | 864 | own_querier_enabled = false; |
|---|
| 704 | 865 | else |
|---|
| 705 | 866 | own_querier_enabled = true; |
|---|
| .. | .. |
|---|
| 728 | 889 | } |
|---|
| 729 | 890 | } |
|---|
| 730 | 891 | |
|---|
| 892 | +static inline bool br_multicast_is_star_g(const struct br_ip *ip) |
|---|
| 893 | +{ |
|---|
| 894 | + switch (ip->proto) { |
|---|
| 895 | + case htons(ETH_P_IP): |
|---|
| 896 | + return ipv4_is_zeronet(ip->src.ip4); |
|---|
| 897 | +#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 898 | + case htons(ETH_P_IPV6): |
|---|
| 899 | + return ipv6_addr_any(&ip->src.ip6); |
|---|
| 900 | +#endif |
|---|
| 901 | + default: |
|---|
| 902 | + return false; |
|---|
| 903 | + } |
|---|
| 904 | +} |
|---|
| 905 | + |
|---|
| 906 | +static inline bool br_multicast_should_handle_mode(const struct net_bridge *br, |
|---|
| 907 | + __be16 proto) |
|---|
| 908 | +{ |
|---|
| 909 | + switch (proto) { |
|---|
| 910 | + case htons(ETH_P_IP): |
|---|
| 911 | + return !!(br->multicast_igmp_version == 3); |
|---|
| 912 | +#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 913 | + case htons(ETH_P_IPV6): |
|---|
| 914 | + return !!(br->multicast_mld_version == 2); |
|---|
| 915 | +#endif |
|---|
| 916 | + default: |
|---|
| 917 | + return false; |
|---|
| 918 | + } |
|---|
| 919 | +} |
|---|
| 920 | + |
|---|
| 731 | 921 | static inline int br_multicast_igmp_type(const struct sk_buff *skb) |
|---|
| 732 | 922 | { |
|---|
| 733 | 923 | return BR_INPUT_SKB_CB(skb)->igmp; |
|---|
| 924 | +} |
|---|
| 925 | + |
|---|
| 926 | +static inline unsigned long br_multicast_lmqt(const struct net_bridge *br) |
|---|
| 927 | +{ |
|---|
| 928 | + return br->multicast_last_member_interval * |
|---|
| 929 | + br->multicast_last_member_count; |
|---|
| 930 | +} |
|---|
| 931 | + |
|---|
| 932 | +static inline unsigned long br_multicast_gmi(const struct net_bridge *br) |
|---|
| 933 | +{ |
|---|
| 934 | + return br->multicast_membership_interval; |
|---|
| 734 | 935 | } |
|---|
| 735 | 936 | #else |
|---|
| 736 | 937 | static inline int br_multicast_rcv(struct net_bridge *br, |
|---|
| .. | .. |
|---|
| 765 | 966 | } |
|---|
| 766 | 967 | |
|---|
| 767 | 968 | static inline void br_multicast_init(struct net_bridge *br) |
|---|
| 969 | +{ |
|---|
| 970 | +} |
|---|
| 971 | + |
|---|
| 972 | +static inline void br_multicast_join_snoopers(struct net_bridge *br) |
|---|
| 973 | +{ |
|---|
| 974 | +} |
|---|
| 975 | + |
|---|
| 976 | +static inline void br_multicast_leave_snoopers(struct net_bridge *br) |
|---|
| 768 | 977 | { |
|---|
| 769 | 978 | } |
|---|
| 770 | 979 | |
|---|
| .. | .. |
|---|
| 805 | 1014 | { |
|---|
| 806 | 1015 | } |
|---|
| 807 | 1016 | |
|---|
| 1017 | +static inline int br_mdb_hash_init(struct net_bridge *br) |
|---|
| 1018 | +{ |
|---|
| 1019 | + return 0; |
|---|
| 1020 | +} |
|---|
| 1021 | + |
|---|
| 1022 | +static inline void br_mdb_hash_fini(struct net_bridge *br) |
|---|
| 1023 | +{ |
|---|
| 1024 | +} |
|---|
| 1025 | + |
|---|
| 808 | 1026 | static inline void br_multicast_count(struct net_bridge *br, |
|---|
| 809 | 1027 | const struct net_bridge_port *p, |
|---|
| 810 | 1028 | const struct sk_buff *skb, |
|---|
| .. | .. |
|---|
| 831 | 1049 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING |
|---|
| 832 | 1050 | bool br_allowed_ingress(const struct net_bridge *br, |
|---|
| 833 | 1051 | struct net_bridge_vlan_group *vg, struct sk_buff *skb, |
|---|
| 834 | | - u16 *vid); |
|---|
| 1052 | + u16 *vid, u8 *state); |
|---|
| 835 | 1053 | bool br_allowed_egress(struct net_bridge_vlan_group *vg, |
|---|
| 836 | 1054 | const struct sk_buff *skb); |
|---|
| 837 | 1055 | bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid); |
|---|
| .. | .. |
|---|
| 840 | 1058 | struct net_bridge_vlan_group *vg, |
|---|
| 841 | 1059 | struct sk_buff *skb); |
|---|
| 842 | 1060 | int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, |
|---|
| 843 | | - bool *changed); |
|---|
| 1061 | + bool *changed, struct netlink_ext_ack *extack); |
|---|
| 844 | 1062 | int br_vlan_delete(struct net_bridge *br, u16 vid); |
|---|
| 845 | 1063 | void br_vlan_flush(struct net_bridge *br); |
|---|
| 846 | 1064 | struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid); |
|---|
| .. | .. |
|---|
| 850 | 1068 | int __br_vlan_set_proto(struct net_bridge *br, __be16 proto); |
|---|
| 851 | 1069 | int br_vlan_set_proto(struct net_bridge *br, unsigned long val); |
|---|
| 852 | 1070 | int br_vlan_set_stats(struct net_bridge *br, unsigned long val); |
|---|
| 1071 | +int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val); |
|---|
| 853 | 1072 | int br_vlan_init(struct net_bridge *br); |
|---|
| 854 | 1073 | int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val); |
|---|
| 855 | | -int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid); |
|---|
| 1074 | +int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, |
|---|
| 1075 | + struct netlink_ext_ack *extack); |
|---|
| 856 | 1076 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, |
|---|
| 857 | | - bool *changed); |
|---|
| 1077 | + bool *changed, struct netlink_ext_ack *extack); |
|---|
| 858 | 1078 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); |
|---|
| 859 | 1079 | void nbp_vlan_flush(struct net_bridge_port *port); |
|---|
| 860 | | -int nbp_vlan_init(struct net_bridge_port *port); |
|---|
| 1080 | +int nbp_vlan_init(struct net_bridge_port *port, struct netlink_ext_ack *extack); |
|---|
| 861 | 1081 | int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask); |
|---|
| 862 | 1082 | void br_vlan_get_stats(const struct net_bridge_vlan *v, |
|---|
| 863 | 1083 | struct br_vlan_stats *stats); |
|---|
| 1084 | +void br_vlan_port_event(struct net_bridge_port *p, unsigned long event); |
|---|
| 1085 | +int br_vlan_bridge_event(struct net_device *dev, unsigned long event, |
|---|
| 1086 | + void *ptr); |
|---|
| 1087 | +void br_vlan_rtnl_init(void); |
|---|
| 1088 | +void br_vlan_rtnl_uninit(void); |
|---|
| 1089 | +void br_vlan_notify(const struct net_bridge *br, |
|---|
| 1090 | + const struct net_bridge_port *p, |
|---|
| 1091 | + u16 vid, u16 vid_range, |
|---|
| 1092 | + int cmd); |
|---|
| 1093 | +bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, |
|---|
| 1094 | + const struct net_bridge_vlan *range_end); |
|---|
| 864 | 1095 | |
|---|
| 865 | 1096 | static inline struct net_bridge_vlan_group *br_vlan_group( |
|---|
| 866 | 1097 | const struct net_bridge *br) |
|---|
| .. | .. |
|---|
| 894 | 1125 | int err = 0; |
|---|
| 895 | 1126 | |
|---|
| 896 | 1127 | if (skb_vlan_tag_present(skb)) { |
|---|
| 897 | | - *vid = skb_vlan_tag_get(skb) & VLAN_VID_MASK; |
|---|
| 1128 | + *vid = skb_vlan_tag_get_id(skb); |
|---|
| 898 | 1129 | } else { |
|---|
| 899 | 1130 | *vid = 0; |
|---|
| 900 | 1131 | err = -EINVAL; |
|---|
| .. | .. |
|---|
| 912 | 1143 | return vg->pvid; |
|---|
| 913 | 1144 | } |
|---|
| 914 | 1145 | |
|---|
| 1146 | +static inline u16 br_vlan_flags(const struct net_bridge_vlan *v, u16 pvid) |
|---|
| 1147 | +{ |
|---|
| 1148 | + return v->vid == pvid ? v->flags | BRIDGE_VLAN_INFO_PVID : v->flags; |
|---|
| 1149 | +} |
|---|
| 915 | 1150 | #else |
|---|
| 916 | 1151 | static inline bool br_allowed_ingress(const struct net_bridge *br, |
|---|
| 917 | 1152 | struct net_bridge_vlan_group *vg, |
|---|
| 918 | 1153 | struct sk_buff *skb, |
|---|
| 919 | | - u16 *vid) |
|---|
| 1154 | + u16 *vid, u8 *state) |
|---|
| 920 | 1155 | { |
|---|
| 921 | 1156 | return true; |
|---|
| 922 | 1157 | } |
|---|
| .. | .. |
|---|
| 942 | 1177 | } |
|---|
| 943 | 1178 | |
|---|
| 944 | 1179 | static inline int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, |
|---|
| 945 | | - bool *changed) |
|---|
| 1180 | + bool *changed, struct netlink_ext_ack *extack) |
|---|
| 946 | 1181 | { |
|---|
| 947 | 1182 | *changed = false; |
|---|
| 948 | 1183 | return -EOPNOTSUPP; |
|---|
| .. | .. |
|---|
| 967 | 1202 | } |
|---|
| 968 | 1203 | |
|---|
| 969 | 1204 | static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, |
|---|
| 970 | | - bool *changed) |
|---|
| 1205 | + bool *changed, struct netlink_ext_ack *extack) |
|---|
| 971 | 1206 | { |
|---|
| 972 | 1207 | *changed = false; |
|---|
| 973 | 1208 | return -EOPNOTSUPP; |
|---|
| .. | .. |
|---|
| 988 | 1223 | return NULL; |
|---|
| 989 | 1224 | } |
|---|
| 990 | 1225 | |
|---|
| 991 | | -static inline int nbp_vlan_init(struct net_bridge_port *port) |
|---|
| 1226 | +static inline int nbp_vlan_init(struct net_bridge_port *port, |
|---|
| 1227 | + struct netlink_ext_ack *extack) |
|---|
| 992 | 1228 | { |
|---|
| 993 | 1229 | return 0; |
|---|
| 994 | 1230 | } |
|---|
| .. | .. |
|---|
| 1043 | 1279 | struct br_vlan_stats *stats) |
|---|
| 1044 | 1280 | { |
|---|
| 1045 | 1281 | } |
|---|
| 1282 | + |
|---|
| 1283 | +static inline void br_vlan_port_event(struct net_bridge_port *p, |
|---|
| 1284 | + unsigned long event) |
|---|
| 1285 | +{ |
|---|
| 1286 | +} |
|---|
| 1287 | + |
|---|
| 1288 | +static inline int br_vlan_bridge_event(struct net_device *dev, |
|---|
| 1289 | + unsigned long event, void *ptr) |
|---|
| 1290 | +{ |
|---|
| 1291 | + return 0; |
|---|
| 1292 | +} |
|---|
| 1293 | + |
|---|
| 1294 | +static inline void br_vlan_rtnl_init(void) |
|---|
| 1295 | +{ |
|---|
| 1296 | +} |
|---|
| 1297 | + |
|---|
| 1298 | +static inline void br_vlan_rtnl_uninit(void) |
|---|
| 1299 | +{ |
|---|
| 1300 | +} |
|---|
| 1301 | + |
|---|
| 1302 | +static inline void br_vlan_notify(const struct net_bridge *br, |
|---|
| 1303 | + const struct net_bridge_port *p, |
|---|
| 1304 | + u16 vid, u16 vid_range, |
|---|
| 1305 | + int cmd) |
|---|
| 1306 | +{ |
|---|
| 1307 | +} |
|---|
| 1308 | + |
|---|
| 1309 | +static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, |
|---|
| 1310 | + const struct net_bridge_vlan *range_end) |
|---|
| 1311 | +{ |
|---|
| 1312 | + return true; |
|---|
| 1313 | +} |
|---|
| 1314 | +#endif |
|---|
| 1315 | + |
|---|
| 1316 | +/* br_vlan_options.c */ |
|---|
| 1317 | +#ifdef CONFIG_BRIDGE_VLAN_FILTERING |
|---|
| 1318 | +bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr, |
|---|
| 1319 | + const struct net_bridge_vlan *range_end); |
|---|
| 1320 | +bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v); |
|---|
| 1321 | +size_t br_vlan_opts_nl_size(void); |
|---|
| 1322 | +int br_vlan_process_options(const struct net_bridge *br, |
|---|
| 1323 | + const struct net_bridge_port *p, |
|---|
| 1324 | + struct net_bridge_vlan *range_start, |
|---|
| 1325 | + struct net_bridge_vlan *range_end, |
|---|
| 1326 | + struct nlattr **tb, |
|---|
| 1327 | + struct netlink_ext_ack *extack); |
|---|
| 1328 | + |
|---|
| 1329 | +/* vlan state manipulation helpers using *_ONCE to annotate lock-free access */ |
|---|
| 1330 | +static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v) |
|---|
| 1331 | +{ |
|---|
| 1332 | + return READ_ONCE(v->state); |
|---|
| 1333 | +} |
|---|
| 1334 | + |
|---|
| 1335 | +static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state) |
|---|
| 1336 | +{ |
|---|
| 1337 | + WRITE_ONCE(v->state, state); |
|---|
| 1338 | +} |
|---|
| 1339 | + |
|---|
| 1340 | +static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg) |
|---|
| 1341 | +{ |
|---|
| 1342 | + return READ_ONCE(vg->pvid_state); |
|---|
| 1343 | +} |
|---|
| 1344 | + |
|---|
| 1345 | +static inline void br_vlan_set_pvid_state(struct net_bridge_vlan_group *vg, |
|---|
| 1346 | + u8 state) |
|---|
| 1347 | +{ |
|---|
| 1348 | + WRITE_ONCE(vg->pvid_state, state); |
|---|
| 1349 | +} |
|---|
| 1350 | + |
|---|
| 1351 | +/* learn_allow is true at ingress and false at egress */ |
|---|
| 1352 | +static inline bool br_vlan_state_allowed(u8 state, bool learn_allow) |
|---|
| 1353 | +{ |
|---|
| 1354 | + switch (state) { |
|---|
| 1355 | + case BR_STATE_LEARNING: |
|---|
| 1356 | + return learn_allow; |
|---|
| 1357 | + case BR_STATE_FORWARDING: |
|---|
| 1358 | + return true; |
|---|
| 1359 | + default: |
|---|
| 1360 | + return false; |
|---|
| 1361 | + } |
|---|
| 1362 | +} |
|---|
| 1046 | 1363 | #endif |
|---|
| 1047 | 1364 | |
|---|
| 1048 | 1365 | struct nf_br_ops { |
|---|
| .. | .. |
|---|
| 1078 | 1395 | /* br_stp_if.c */ |
|---|
| 1079 | 1396 | void br_stp_enable_bridge(struct net_bridge *br); |
|---|
| 1080 | 1397 | void br_stp_disable_bridge(struct net_bridge *br); |
|---|
| 1081 | | -void br_stp_set_enabled(struct net_bridge *br, unsigned long val); |
|---|
| 1398 | +int br_stp_set_enabled(struct net_bridge *br, unsigned long val, |
|---|
| 1399 | + struct netlink_ext_ack *extack); |
|---|
| 1082 | 1400 | void br_stp_enable_port(struct net_bridge_port *p); |
|---|
| 1083 | 1401 | void br_stp_disable_port(struct net_bridge_port *p); |
|---|
| 1084 | 1402 | bool br_stp_recalculate_bridge_id(struct net_bridge *br); |
|---|
| .. | .. |
|---|
| 1103 | 1421 | extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); |
|---|
| 1104 | 1422 | #endif |
|---|
| 1105 | 1423 | |
|---|
| 1424 | +/* br_mrp.c */ |
|---|
| 1425 | +#if IS_ENABLED(CONFIG_BRIDGE_MRP) |
|---|
| 1426 | +int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, |
|---|
| 1427 | + struct nlattr *attr, int cmd, struct netlink_ext_ack *extack); |
|---|
| 1428 | +int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb); |
|---|
| 1429 | +bool br_mrp_enabled(struct net_bridge *br); |
|---|
| 1430 | +void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p); |
|---|
| 1431 | +int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br); |
|---|
| 1432 | +#else |
|---|
| 1433 | +static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, |
|---|
| 1434 | + struct nlattr *attr, int cmd, |
|---|
| 1435 | + struct netlink_ext_ack *extack) |
|---|
| 1436 | +{ |
|---|
| 1437 | + return -EOPNOTSUPP; |
|---|
| 1438 | +} |
|---|
| 1439 | + |
|---|
| 1440 | +static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) |
|---|
| 1441 | +{ |
|---|
| 1442 | + return 0; |
|---|
| 1443 | +} |
|---|
| 1444 | + |
|---|
| 1445 | +static inline bool br_mrp_enabled(struct net_bridge *br) |
|---|
| 1446 | +{ |
|---|
| 1447 | + return false; |
|---|
| 1448 | +} |
|---|
| 1449 | + |
|---|
| 1450 | +static inline void br_mrp_port_del(struct net_bridge *br, |
|---|
| 1451 | + struct net_bridge_port *p) |
|---|
| 1452 | +{ |
|---|
| 1453 | +} |
|---|
| 1454 | + |
|---|
| 1455 | +static inline int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br) |
|---|
| 1456 | +{ |
|---|
| 1457 | + return 0; |
|---|
| 1458 | +} |
|---|
| 1459 | + |
|---|
| 1460 | +#endif |
|---|
| 1461 | + |
|---|
| 1106 | 1462 | /* br_netlink.c */ |
|---|
| 1107 | 1463 | extern struct rtnl_link_ops br_link_ops; |
|---|
| 1108 | 1464 | int br_netlink_init(void); |
|---|
| 1109 | 1465 | void br_netlink_fini(void); |
|---|
| 1110 | 1466 | void br_ifinfo_notify(int event, const struct net_bridge *br, |
|---|
| 1111 | 1467 | const struct net_bridge_port *port); |
|---|
| 1112 | | -int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); |
|---|
| 1468 | +int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags, |
|---|
| 1469 | + struct netlink_ext_ack *extack); |
|---|
| 1113 | 1470 | int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); |
|---|
| 1114 | 1471 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, |
|---|
| 1115 | 1472 | u32 filter_mask, int nlflags); |
|---|
| 1473 | +int br_process_vlan_info(struct net_bridge *br, |
|---|
| 1474 | + struct net_bridge_port *p, int cmd, |
|---|
| 1475 | + struct bridge_vlan_info *vinfo_curr, |
|---|
| 1476 | + struct bridge_vlan_info **vinfo_last, |
|---|
| 1477 | + bool *changed, |
|---|
| 1478 | + struct netlink_ext_ack *extack); |
|---|
| 1116 | 1479 | |
|---|
| 1117 | 1480 | #ifdef CONFIG_SYSFS |
|---|
| 1118 | 1481 | /* br_sysfs_if.c */ |
|---|
| .. | .. |
|---|
| 1144 | 1507 | unsigned long mask); |
|---|
| 1145 | 1508 | void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, |
|---|
| 1146 | 1509 | int type); |
|---|
| 1147 | | -int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags); |
|---|
| 1510 | +int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, |
|---|
| 1511 | + struct netlink_ext_ack *extack); |
|---|
| 1148 | 1512 | int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid); |
|---|
| 1149 | 1513 | |
|---|
| 1150 | 1514 | static inline void br_switchdev_frame_unmark(struct sk_buff *skb) |
|---|
| .. | .. |
|---|
| 1176 | 1540 | } |
|---|
| 1177 | 1541 | |
|---|
| 1178 | 1542 | static inline int br_switchdev_port_vlan_add(struct net_device *dev, |
|---|
| 1179 | | - u16 vid, u16 flags) |
|---|
| 1543 | + u16 vid, u16 flags, |
|---|
| 1544 | + struct netlink_ext_ack *extack) |
|---|
| 1180 | 1545 | { |
|---|
| 1181 | 1546 | return -EOPNOTSUPP; |
|---|
| 1182 | 1547 | } |
|---|