diff options
Diffstat (limited to 'net/bridge')
| -rw-r--r-- | net/bridge/br_fdb.c | 15 | ||||
| -rw-r--r-- | net/bridge/br_forward.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 59 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 16 | ||||
| -rw-r--r-- | net/bridge/br_mdb.c | 174 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 99 | ||||
| -rw-r--r-- | net/bridge/br_netfilter_hooks.c | 68 | ||||
| -rw-r--r-- | net/bridge/br_netlink.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 10 | ||||
| -rw-r--r-- | net/bridge/br_stp.c | 27 | ||||
| -rw-r--r-- | net/bridge/br_stp_if.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_stp_timer.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_vlan.c | 11 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtables.c | 10 | ||||
| -rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 24 |
15 files changed, 375 insertions, 143 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 82e3e9705017..dcea4f4c62b3 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -723,6 +723,8 @@ int br_fdb_dump(struct sk_buff *skb, | |||
| 723 | struct net_bridge_fdb_entry *f; | 723 | struct net_bridge_fdb_entry *f; |
| 724 | 724 | ||
| 725 | hlist_for_each_entry_rcu(f, &br->hash[i], hlist) { | 725 | hlist_for_each_entry_rcu(f, &br->hash[i], hlist) { |
| 726 | int err; | ||
| 727 | |||
| 726 | if (idx < cb->args[0]) | 728 | if (idx < cb->args[0]) |
| 727 | goto skip; | 729 | goto skip; |
| 728 | 730 | ||
| @@ -741,12 +743,15 @@ int br_fdb_dump(struct sk_buff *skb, | |||
| 741 | if (!filter_dev && f->dst) | 743 | if (!filter_dev && f->dst) |
| 742 | goto skip; | 744 | goto skip; |
| 743 | 745 | ||
| 744 | if (fdb_fill_info(skb, br, f, | 746 | err = fdb_fill_info(skb, br, f, |
| 745 | NETLINK_CB(cb->skb).portid, | 747 | NETLINK_CB(cb->skb).portid, |
| 746 | cb->nlh->nlmsg_seq, | 748 | cb->nlh->nlmsg_seq, |
| 747 | RTM_NEWNEIGH, | 749 | RTM_NEWNEIGH, |
| 748 | NLM_F_MULTI) < 0) | 750 | NLM_F_MULTI); |
| 751 | if (err < 0) { | ||
| 752 | cb->args[1] = err; | ||
| 749 | break; | 753 | break; |
| 754 | } | ||
| 750 | skip: | 755 | skip: |
| 751 | ++idx; | 756 | ++idx; |
| 752 | } | 757 | } |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index fcdb86dd5a23..f47759f05b6d 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -44,7 +44,6 @@ int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb | |||
| 44 | 44 | ||
| 45 | skb_push(skb, ETH_HLEN); | 45 | skb_push(skb, ETH_HLEN); |
| 46 | br_drop_fake_rtable(skb); | 46 | br_drop_fake_rtable(skb); |
| 47 | skb_sender_cpu_clear(skb); | ||
| 48 | 47 | ||
| 49 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 48 | if (skb->ip_summed == CHECKSUM_PARTIAL && |
| 50 | (skb->protocol == htons(ETH_P_8021Q) || | 49 | (skb->protocol == htons(ETH_P_8021Q) || |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index c367b3e1b5ac..8217aecf025b 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -36,10 +36,10 @@ | |||
| 36 | */ | 36 | */ |
| 37 | static int port_cost(struct net_device *dev) | 37 | static int port_cost(struct net_device *dev) |
| 38 | { | 38 | { |
| 39 | struct ethtool_cmd ecmd; | 39 | struct ethtool_link_ksettings ecmd; |
| 40 | 40 | ||
| 41 | if (!__ethtool_get_settings(dev, &ecmd)) { | 41 | if (!__ethtool_get_link_ksettings(dev, &ecmd)) { |
| 42 | switch (ethtool_cmd_speed(&ecmd)) { | 42 | switch (ecmd.base.speed) { |
| 43 | case SPEED_10000: | 43 | case SPEED_10000: |
| 44 | return 2; | 44 | return 2; |
| 45 | case SPEED_1000: | 45 | case SPEED_1000: |
| @@ -223,6 +223,31 @@ static void destroy_nbp_rcu(struct rcu_head *head) | |||
| 223 | destroy_nbp(p); | 223 | destroy_nbp(p); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | static unsigned get_max_headroom(struct net_bridge *br) | ||
| 227 | { | ||
| 228 | unsigned max_headroom = 0; | ||
| 229 | struct net_bridge_port *p; | ||
| 230 | |||
| 231 | list_for_each_entry(p, &br->port_list, list) { | ||
| 232 | unsigned dev_headroom = netdev_get_fwd_headroom(p->dev); | ||
| 233 | |||
| 234 | if (dev_headroom > max_headroom) | ||
| 235 | max_headroom = dev_headroom; | ||
| 236 | } | ||
| 237 | |||
| 238 | return max_headroom; | ||
| 239 | } | ||
| 240 | |||
| 241 | static void update_headroom(struct net_bridge *br, int new_hr) | ||
| 242 | { | ||
| 243 | struct net_bridge_port *p; | ||
| 244 | |||
| 245 | list_for_each_entry(p, &br->port_list, list) | ||
| 246 | netdev_set_rx_headroom(p->dev, new_hr); | ||
| 247 | |||
| 248 | br->dev->needed_headroom = new_hr; | ||
| 249 | } | ||
| 250 | |||
| 226 | /* Delete port(interface) from bridge is done in two steps. | 251 | /* Delete port(interface) from bridge is done in two steps. |
| 227 | * via RCU. First step, marks device as down. That deletes | 252 | * via RCU. First step, marks device as down. That deletes |
| 228 | * all the timers and stops new packets from flowing through. | 253 | * all the timers and stops new packets from flowing through. |
| @@ -248,6 +273,9 @@ static void del_nbp(struct net_bridge_port *p) | |||
| 248 | br_ifinfo_notify(RTM_DELLINK, p); | 273 | br_ifinfo_notify(RTM_DELLINK, p); |
| 249 | 274 | ||
| 250 | list_del_rcu(&p->list); | 275 | list_del_rcu(&p->list); |
| 276 | if (netdev_get_fwd_headroom(dev) == br->dev->needed_headroom) | ||
| 277 | update_headroom(br, get_max_headroom(br)); | ||
| 278 | netdev_reset_rx_headroom(dev); | ||
| 251 | 279 | ||
| 252 | nbp_vlan_flush(p); | 280 | nbp_vlan_flush(p); |
| 253 | br_fdb_delete_by_port(br, p, 0, 1); | 281 | br_fdb_delete_by_port(br, p, 0, 1); |
| @@ -409,6 +437,20 @@ int br_min_mtu(const struct net_bridge *br) | |||
| 409 | return mtu; | 437 | return mtu; |
| 410 | } | 438 | } |
| 411 | 439 | ||
| 440 | static void br_set_gso_limits(struct net_bridge *br) | ||
| 441 | { | ||
| 442 | unsigned int gso_max_size = GSO_MAX_SIZE; | ||
| 443 | u16 gso_max_segs = GSO_MAX_SEGS; | ||
| 444 | const struct net_bridge_port *p; | ||
| 445 | |||
| 446 | list_for_each_entry(p, &br->port_list, list) { | ||
| 447 | gso_max_size = min(gso_max_size, p->dev->gso_max_size); | ||
| 448 | gso_max_segs = min(gso_max_segs, p->dev->gso_max_segs); | ||
| 449 | } | ||
| 450 | br->dev->gso_max_size = gso_max_size; | ||
| 451 | br->dev->gso_max_segs = gso_max_segs; | ||
| 452 | } | ||
| 453 | |||
| 412 | /* | 454 | /* |
| 413 | * Recomputes features using slave's features | 455 | * Recomputes features using slave's features |
| 414 | */ | 456 | */ |
| @@ -438,6 +480,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 438 | { | 480 | { |
| 439 | struct net_bridge_port *p; | 481 | struct net_bridge_port *p; |
| 440 | int err = 0; | 482 | int err = 0; |
| 483 | unsigned br_hr, dev_hr; | ||
| 441 | bool changed_addr; | 484 | bool changed_addr; |
| 442 | 485 | ||
| 443 | /* Don't allow bridging non-ethernet like devices, or DSA-enabled | 486 | /* Don't allow bridging non-ethernet like devices, or DSA-enabled |
| @@ -505,8 +548,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 505 | 548 | ||
| 506 | netdev_update_features(br->dev); | 549 | netdev_update_features(br->dev); |
| 507 | 550 | ||
| 508 | if (br->dev->needed_headroom < dev->needed_headroom) | 551 | br_hr = br->dev->needed_headroom; |
| 509 | br->dev->needed_headroom = dev->needed_headroom; | 552 | dev_hr = netdev_get_fwd_headroom(dev); |
| 553 | if (br_hr < dev_hr) | ||
| 554 | update_headroom(br, dev_hr); | ||
| 555 | else | ||
| 556 | netdev_set_rx_headroom(dev, br_hr); | ||
| 510 | 557 | ||
| 511 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) | 558 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) |
| 512 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | 559 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); |
| @@ -531,6 +578,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 531 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); | 578 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); |
| 532 | 579 | ||
| 533 | dev_set_mtu(br->dev, br_min_mtu(br)); | 580 | dev_set_mtu(br->dev, br_min_mtu(br)); |
| 581 | br_set_gso_limits(br); | ||
| 534 | 582 | ||
| 535 | kobject_uevent(&p->kobj, KOBJ_ADD); | 583 | kobject_uevent(&p->kobj, KOBJ_ADD); |
| 536 | 584 | ||
| @@ -577,6 +625,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
| 577 | del_nbp(p); | 625 | del_nbp(p); |
| 578 | 626 | ||
| 579 | dev_set_mtu(br->dev, br_min_mtu(br)); | 627 | dev_set_mtu(br->dev, br_min_mtu(br)); |
| 628 | br_set_gso_limits(br); | ||
| 580 | 629 | ||
| 581 | spin_lock_bh(&br->lock); | 630 | spin_lock_bh(&br->lock); |
| 582 | changed_addr = br_stp_recalculate_bridge_id(br); | 631 | changed_addr = br_stp_recalculate_bridge_id(br); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f7fba74108a9..160797722228 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -222,7 +222,10 @@ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_bu | |||
| 222 | /* check if vlan is allowed, to avoid spoofing */ | 222 | /* check if vlan is allowed, to avoid spoofing */ |
| 223 | if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) | 223 | if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) |
| 224 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); | 224 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); |
| 225 | return 0; /* process further */ | 225 | |
| 226 | BR_INPUT_SKB_CB(skb)->brdev = p->br->dev; | ||
| 227 | br_pass_frame_up(skb); | ||
| 228 | return 0; | ||
| 226 | } | 229 | } |
| 227 | 230 | ||
| 228 | /* | 231 | /* |
| @@ -284,14 +287,9 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) | |||
| 284 | } | 287 | } |
| 285 | 288 | ||
| 286 | /* Deliver packet to local host only */ | 289 | /* Deliver packet to local host only */ |
| 287 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, | 290 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, dev_net(skb->dev), |
| 288 | dev_net(skb->dev), NULL, skb, skb->dev, NULL, | 291 | NULL, skb, skb->dev, NULL, br_handle_local_finish); |
| 289 | br_handle_local_finish)) { | 292 | return RX_HANDLER_CONSUMED; |
| 290 | return RX_HANDLER_CONSUMED; /* consumed by filter */ | ||
| 291 | } else { | ||
| 292 | *pskb = skb; | ||
| 293 | return RX_HANDLER_PASS; /* continue processing */ | ||
| 294 | } | ||
| 295 | } | 293 | } |
| 296 | 294 | ||
| 297 | forward: | 295 | forward: |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 74c278e00225..7dbc80d01eb0 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
| @@ -20,7 +20,7 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 20 | { | 20 | { |
| 21 | struct net_bridge *br = netdev_priv(dev); | 21 | struct net_bridge *br = netdev_priv(dev); |
| 22 | struct net_bridge_port *p; | 22 | struct net_bridge_port *p; |
| 23 | struct nlattr *nest; | 23 | struct nlattr *nest, *port_nest; |
| 24 | 24 | ||
| 25 | if (!br->multicast_router || hlist_empty(&br->router_list)) | 25 | if (!br->multicast_router || hlist_empty(&br->router_list)) |
| 26 | return 0; | 26 | return 0; |
| @@ -30,8 +30,20 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 30 | return -EMSGSIZE; | 30 | return -EMSGSIZE; |
| 31 | 31 | ||
| 32 | hlist_for_each_entry_rcu(p, &br->router_list, rlist) { | 32 | hlist_for_each_entry_rcu(p, &br->router_list, rlist) { |
| 33 | if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex)) | 33 | if (!p) |
| 34 | continue; | ||
| 35 | port_nest = nla_nest_start(skb, MDBA_ROUTER_PORT); | ||
| 36 | if (!port_nest) | ||
| 37 | goto fail; | ||
| 38 | if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) || | ||
| 39 | nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER, | ||
| 40 | br_timer_value(&p->multicast_router_timer)) || | ||
| 41 | nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE, | ||
| 42 | p->multicast_router)) { | ||
| 43 | nla_nest_cancel(skb, port_nest); | ||
| 34 | goto fail; | 44 | goto fail; |
| 45 | } | ||
| 46 | nla_nest_end(skb, port_nest); | ||
| 35 | } | 47 | } |
| 36 | 48 | ||
| 37 | nla_nest_end(skb, nest); | 49 | nla_nest_end(skb, nest); |
| @@ -41,6 +53,27 @@ fail: | |||
| 41 | return -EMSGSIZE; | 53 | return -EMSGSIZE; |
| 42 | } | 54 | } |
| 43 | 55 | ||
| 56 | static void __mdb_entry_fill_flags(struct br_mdb_entry *e, unsigned char flags) | ||
| 57 | { | ||
| 58 | e->state = flags & MDB_PG_FLAGS_PERMANENT; | ||
| 59 | e->flags = 0; | ||
| 60 | if (flags & MDB_PG_FLAGS_OFFLOAD) | ||
| 61 | e->flags |= MDB_FLAGS_OFFLOAD; | ||
| 62 | } | ||
| 63 | |||
| 64 | static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) | ||
| 65 | { | ||
| 66 | memset(ip, 0, sizeof(struct br_ip)); | ||
| 67 | ip->vid = entry->vid; | ||
| 68 | ip->proto = entry->addr.proto; | ||
| 69 | if (ip->proto == htons(ETH_P_IP)) | ||
| 70 | ip->u.ip4 = entry->addr.u.ip4; | ||
| 71 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 72 | else | ||
| 73 | ip->u.ip6 = entry->addr.u.ip6; | ||
| 74 | #endif | ||
| 75 | } | ||
| 76 | |||
| 44 | static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | 77 | static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, |
| 45 | struct net_device *dev) | 78 | struct net_device *dev) |
| 46 | { | 79 | { |
| @@ -80,26 +113,41 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 80 | for (pp = &mp->ports; | 113 | for (pp = &mp->ports; |
| 81 | (p = rcu_dereference(*pp)) != NULL; | 114 | (p = rcu_dereference(*pp)) != NULL; |
| 82 | pp = &p->next) { | 115 | pp = &p->next) { |
| 116 | struct nlattr *nest_ent; | ||
| 117 | struct br_mdb_entry e; | ||
| 118 | |||
| 83 | port = p->port; | 119 | port = p->port; |
| 84 | if (port) { | 120 | if (!port) |
| 85 | struct br_mdb_entry e; | 121 | continue; |
| 86 | memset(&e, 0, sizeof(e)); | 122 | |
| 87 | e.ifindex = port->dev->ifindex; | 123 | memset(&e, 0, sizeof(e)); |
| 88 | e.state = p->state; | 124 | e.ifindex = port->dev->ifindex; |
| 89 | e.vid = p->addr.vid; | 125 | e.vid = p->addr.vid; |
| 90 | if (p->addr.proto == htons(ETH_P_IP)) | 126 | __mdb_entry_fill_flags(&e, p->flags); |
| 91 | e.addr.u.ip4 = p->addr.u.ip4; | 127 | if (p->addr.proto == htons(ETH_P_IP)) |
| 128 | e.addr.u.ip4 = p->addr.u.ip4; | ||
| 92 | #if IS_ENABLED(CONFIG_IPV6) | 129 | #if IS_ENABLED(CONFIG_IPV6) |
| 93 | if (p->addr.proto == htons(ETH_P_IPV6)) | 130 | if (p->addr.proto == htons(ETH_P_IPV6)) |
| 94 | e.addr.u.ip6 = p->addr.u.ip6; | 131 | e.addr.u.ip6 = p->addr.u.ip6; |
| 95 | #endif | 132 | #endif |
| 96 | e.addr.proto = p->addr.proto; | 133 | e.addr.proto = p->addr.proto; |
| 97 | if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) { | 134 | nest_ent = nla_nest_start(skb, |
| 98 | nla_nest_cancel(skb, nest2); | 135 | MDBA_MDB_ENTRY_INFO); |
| 99 | err = -EMSGSIZE; | 136 | if (!nest_ent) { |
| 100 | goto out; | 137 | nla_nest_cancel(skb, nest2); |
| 101 | } | 138 | err = -EMSGSIZE; |
| 139 | goto out; | ||
| 102 | } | 140 | } |
| 141 | if (nla_put_nohdr(skb, sizeof(e), &e) || | ||
| 142 | nla_put_u32(skb, | ||
| 143 | MDBA_MDB_EATTR_TIMER, | ||
| 144 | br_timer_value(&p->timer))) { | ||
| 145 | nla_nest_cancel(skb, nest_ent); | ||
| 146 | nla_nest_cancel(skb, nest2); | ||
| 147 | err = -EMSGSIZE; | ||
| 148 | goto out; | ||
| 149 | } | ||
| 150 | nla_nest_end(skb, nest_ent); | ||
| 103 | } | 151 | } |
| 104 | nla_nest_end(skb, nest2); | 152 | nla_nest_end(skb, nest2); |
| 105 | skip: | 153 | skip: |
| @@ -208,9 +256,45 @@ static inline size_t rtnl_mdb_nlmsg_size(void) | |||
| 208 | + nla_total_size(sizeof(struct br_mdb_entry)); | 256 | + nla_total_size(sizeof(struct br_mdb_entry)); |
| 209 | } | 257 | } |
| 210 | 258 | ||
| 211 | static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | 259 | struct br_mdb_complete_info { |
| 212 | int type) | 260 | struct net_bridge_port *port; |
| 261 | struct br_ip ip; | ||
| 262 | }; | ||
| 263 | |||
| 264 | static void br_mdb_complete(struct net_device *dev, int err, void *priv) | ||
| 265 | { | ||
| 266 | struct br_mdb_complete_info *data = priv; | ||
| 267 | struct net_bridge_port_group __rcu **pp; | ||
| 268 | struct net_bridge_port_group *p; | ||
| 269 | struct net_bridge_mdb_htable *mdb; | ||
| 270 | struct net_bridge_mdb_entry *mp; | ||
| 271 | struct net_bridge_port *port = data->port; | ||
| 272 | struct net_bridge *br = port->br; | ||
| 273 | |||
| 274 | if (err) | ||
| 275 | goto err; | ||
| 276 | |||
| 277 | spin_lock_bh(&br->multicast_lock); | ||
| 278 | mdb = mlock_dereference(br->mdb, br); | ||
| 279 | mp = br_mdb_ip_get(mdb, &data->ip); | ||
| 280 | if (!mp) | ||
| 281 | goto out; | ||
| 282 | for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; | ||
| 283 | pp = &p->next) { | ||
| 284 | if (p->port != port) | ||
| 285 | continue; | ||
| 286 | p->flags |= MDB_PG_FLAGS_OFFLOAD; | ||
| 287 | } | ||
| 288 | out: | ||
| 289 | spin_unlock_bh(&br->multicast_lock); | ||
| 290 | err: | ||
| 291 | kfree(priv); | ||
| 292 | } | ||
| 293 | |||
| 294 | static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, | ||
| 295 | struct br_mdb_entry *entry, int type) | ||
| 213 | { | 296 | { |
| 297 | struct br_mdb_complete_info *complete_info; | ||
| 214 | struct switchdev_obj_port_mdb mdb = { | 298 | struct switchdev_obj_port_mdb mdb = { |
| 215 | .obj = { | 299 | .obj = { |
| 216 | .id = SWITCHDEV_OBJ_ID_PORT_MDB, | 300 | .id = SWITCHDEV_OBJ_ID_PORT_MDB, |
| @@ -232,10 +316,18 @@ static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | |||
| 232 | #endif | 316 | #endif |
| 233 | 317 | ||
| 234 | mdb.obj.orig_dev = port_dev; | 318 | mdb.obj.orig_dev = port_dev; |
| 235 | if (port_dev && type == RTM_NEWMDB) | 319 | if (port_dev && type == RTM_NEWMDB) { |
| 236 | switchdev_port_obj_add(port_dev, &mdb.obj); | 320 | complete_info = kmalloc(sizeof(*complete_info), GFP_ATOMIC); |
| 237 | else if (port_dev && type == RTM_DELMDB) | 321 | if (complete_info) { |
| 322 | complete_info->port = p; | ||
| 323 | __mdb_entry_to_br_ip(entry, &complete_info->ip); | ||
| 324 | mdb.obj.complete_priv = complete_info; | ||
| 325 | mdb.obj.complete = br_mdb_complete; | ||
| 326 | switchdev_port_obj_add(port_dev, &mdb.obj); | ||
| 327 | } | ||
| 328 | } else if (port_dev && type == RTM_DELMDB) { | ||
| 238 | switchdev_port_obj_del(port_dev, &mdb.obj); | 329 | switchdev_port_obj_del(port_dev, &mdb.obj); |
| 330 | } | ||
| 239 | 331 | ||
| 240 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); | 332 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); |
| 241 | if (!skb) | 333 | if (!skb) |
| @@ -254,7 +346,7 @@ errout: | |||
| 254 | } | 346 | } |
| 255 | 347 | ||
| 256 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | 348 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
| 257 | struct br_ip *group, int type, u8 state) | 349 | struct br_ip *group, int type, u8 flags) |
| 258 | { | 350 | { |
| 259 | struct br_mdb_entry entry; | 351 | struct br_mdb_entry entry; |
| 260 | 352 | ||
| @@ -265,9 +357,9 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | |||
| 265 | #if IS_ENABLED(CONFIG_IPV6) | 357 | #if IS_ENABLED(CONFIG_IPV6) |
| 266 | entry.addr.u.ip6 = group->u.ip6; | 358 | entry.addr.u.ip6 = group->u.ip6; |
| 267 | #endif | 359 | #endif |
| 268 | entry.state = state; | ||
| 269 | entry.vid = group->vid; | 360 | entry.vid = group->vid; |
| 270 | __br_mdb_notify(dev, &entry, type); | 361 | __mdb_entry_fill_flags(&entry, flags); |
| 362 | __br_mdb_notify(dev, port, &entry, type); | ||
| 271 | } | 363 | } |
| 272 | 364 | ||
| 273 | static int nlmsg_populate_rtr_fill(struct sk_buff *skb, | 365 | static int nlmsg_populate_rtr_fill(struct sk_buff *skb, |
| @@ -468,15 +560,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, | |||
| 468 | if (!p || p->br != br || p->state == BR_STATE_DISABLED) | 560 | if (!p || p->br != br || p->state == BR_STATE_DISABLED) |
| 469 | return -EINVAL; | 561 | return -EINVAL; |
| 470 | 562 | ||
| 471 | memset(&ip, 0, sizeof(ip)); | 563 | __mdb_entry_to_br_ip(entry, &ip); |
| 472 | ip.vid = entry->vid; | ||
| 473 | ip.proto = entry->addr.proto; | ||
| 474 | if (ip.proto == htons(ETH_P_IP)) | ||
| 475 | ip.u.ip4 = entry->addr.u.ip4; | ||
| 476 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 477 | else | ||
| 478 | ip.u.ip6 = entry->addr.u.ip6; | ||
| 479 | #endif | ||
| 480 | 564 | ||
| 481 | spin_lock_bh(&br->multicast_lock); | 565 | spin_lock_bh(&br->multicast_lock); |
| 482 | ret = br_mdb_add_group(br, p, &ip, entry->state); | 566 | ret = br_mdb_add_group(br, p, &ip, entry->state); |
| @@ -519,12 +603,12 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 519 | err = __br_mdb_add(net, br, entry); | 603 | err = __br_mdb_add(net, br, entry); |
| 520 | if (err) | 604 | if (err) |
| 521 | break; | 605 | break; |
| 522 | __br_mdb_notify(dev, entry, RTM_NEWMDB); | 606 | __br_mdb_notify(dev, p, entry, RTM_NEWMDB); |
| 523 | } | 607 | } |
| 524 | } else { | 608 | } else { |
| 525 | err = __br_mdb_add(net, br, entry); | 609 | err = __br_mdb_add(net, br, entry); |
| 526 | if (!err) | 610 | if (!err) |
| 527 | __br_mdb_notify(dev, entry, RTM_NEWMDB); | 611 | __br_mdb_notify(dev, p, entry, RTM_NEWMDB); |
| 528 | } | 612 | } |
| 529 | 613 | ||
| 530 | return err; | 614 | return err; |
| @@ -542,15 +626,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | |||
| 542 | if (!netif_running(br->dev) || br->multicast_disabled) | 626 | if (!netif_running(br->dev) || br->multicast_disabled) |
| 543 | return -EINVAL; | 627 | return -EINVAL; |
| 544 | 628 | ||
| 545 | memset(&ip, 0, sizeof(ip)); | 629 | __mdb_entry_to_br_ip(entry, &ip); |
| 546 | ip.vid = entry->vid; | ||
| 547 | ip.proto = entry->addr.proto; | ||
| 548 | if (ip.proto == htons(ETH_P_IP)) | ||
| 549 | ip.u.ip4 = entry->addr.u.ip4; | ||
| 550 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 551 | else | ||
| 552 | ip.u.ip6 = entry->addr.u.ip6; | ||
| 553 | #endif | ||
| 554 | 630 | ||
| 555 | spin_lock_bh(&br->multicast_lock); | 631 | spin_lock_bh(&br->multicast_lock); |
| 556 | mdb = mlock_dereference(br->mdb, br); | 632 | mdb = mlock_dereference(br->mdb, br); |
| @@ -568,7 +644,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | |||
| 568 | if (p->port->state == BR_STATE_DISABLED) | 644 | if (p->port->state == BR_STATE_DISABLED) |
| 569 | goto unlock; | 645 | goto unlock; |
| 570 | 646 | ||
| 571 | entry->state = p->state; | 647 | __mdb_entry_fill_flags(entry, p->flags); |
| 572 | rcu_assign_pointer(*pp, p->next); | 648 | rcu_assign_pointer(*pp, p->next); |
| 573 | hlist_del_init(&p->mglist); | 649 | hlist_del_init(&p->mglist); |
| 574 | del_timer(&p->timer); | 650 | del_timer(&p->timer); |
| @@ -620,12 +696,12 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 620 | entry->vid = v->vid; | 696 | entry->vid = v->vid; |
| 621 | err = __br_mdb_del(br, entry); | 697 | err = __br_mdb_del(br, entry); |
| 622 | if (!err) | 698 | if (!err) |
| 623 | __br_mdb_notify(dev, entry, RTM_DELMDB); | 699 | __br_mdb_notify(dev, p, entry, RTM_DELMDB); |
| 624 | } | 700 | } |
| 625 | } else { | 701 | } else { |
| 626 | err = __br_mdb_del(br, entry); | 702 | err = __br_mdb_del(br, entry); |
| 627 | if (!err) | 703 | if (!err) |
| 628 | __br_mdb_notify(dev, entry, RTM_DELMDB); | 704 | __br_mdb_notify(dev, p, entry, RTM_DELMDB); |
| 629 | } | 705 | } |
| 630 | 706 | ||
| 631 | return err; | 707 | return err; |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 03661d97463c..191ea66e4d92 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -284,7 +284,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
| 284 | hlist_del_init(&p->mglist); | 284 | hlist_del_init(&p->mglist); |
| 285 | del_timer(&p->timer); | 285 | del_timer(&p->timer); |
| 286 | br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, | 286 | br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, |
| 287 | p->state); | 287 | p->flags); |
| 288 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 288 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
| 289 | 289 | ||
| 290 | if (!mp->ports && !mp->mglist && | 290 | if (!mp->ports && !mp->mglist && |
| @@ -304,7 +304,7 @@ static void br_multicast_port_group_expired(unsigned long data) | |||
| 304 | 304 | ||
| 305 | spin_lock(&br->multicast_lock); | 305 | spin_lock(&br->multicast_lock); |
| 306 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || | 306 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || |
| 307 | hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT) | 307 | hlist_unhashed(&pg->mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT) |
| 308 | goto out; | 308 | goto out; |
| 309 | 309 | ||
| 310 | br_multicast_del_pg(br, pg); | 310 | br_multicast_del_pg(br, pg); |
| @@ -649,7 +649,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( | |||
| 649 | struct net_bridge_port *port, | 649 | struct net_bridge_port *port, |
| 650 | struct br_ip *group, | 650 | struct br_ip *group, |
| 651 | struct net_bridge_port_group __rcu *next, | 651 | struct net_bridge_port_group __rcu *next, |
| 652 | unsigned char state) | 652 | unsigned char flags) |
| 653 | { | 653 | { |
| 654 | struct net_bridge_port_group *p; | 654 | struct net_bridge_port_group *p; |
| 655 | 655 | ||
| @@ -659,7 +659,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( | |||
| 659 | 659 | ||
| 660 | p->addr = *group; | 660 | p->addr = *group; |
| 661 | p->port = port; | 661 | p->port = port; |
| 662 | p->state = state; | 662 | p->flags = flags; |
| 663 | rcu_assign_pointer(p->next, next); | 663 | rcu_assign_pointer(p->next, next); |
| 664 | hlist_add_head(&p->mglist, &port->mglist); | 664 | hlist_add_head(&p->mglist, &port->mglist); |
| 665 | setup_timer(&p->timer, br_multicast_port_group_expired, | 665 | setup_timer(&p->timer, br_multicast_port_group_expired, |
| @@ -702,11 +702,11 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 702 | break; | 702 | break; |
| 703 | } | 703 | } |
| 704 | 704 | ||
| 705 | p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY); | 705 | p = br_multicast_new_port_group(port, group, *pp, 0); |
| 706 | if (unlikely(!p)) | 706 | if (unlikely(!p)) |
| 707 | goto err; | 707 | goto err; |
| 708 | rcu_assign_pointer(*pp, p); | 708 | rcu_assign_pointer(*pp, p); |
| 709 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB, MDB_TEMPORARY); | 709 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0); |
| 710 | 710 | ||
| 711 | found: | 711 | found: |
| 712 | mod_timer(&p->timer, now + br->multicast_membership_interval); | 712 | mod_timer(&p->timer, now + br->multicast_membership_interval); |
| @@ -760,13 +760,17 @@ static void br_multicast_router_expired(unsigned long data) | |||
| 760 | struct net_bridge *br = port->br; | 760 | struct net_bridge *br = port->br; |
| 761 | 761 | ||
| 762 | spin_lock(&br->multicast_lock); | 762 | spin_lock(&br->multicast_lock); |
| 763 | if (port->multicast_router != 1 || | 763 | if (port->multicast_router == MDB_RTR_TYPE_DISABLED || |
| 764 | port->multicast_router == MDB_RTR_TYPE_PERM || | ||
| 764 | timer_pending(&port->multicast_router_timer) || | 765 | timer_pending(&port->multicast_router_timer) || |
| 765 | hlist_unhashed(&port->rlist)) | 766 | hlist_unhashed(&port->rlist)) |
| 766 | goto out; | 767 | goto out; |
| 767 | 768 | ||
| 768 | hlist_del_init_rcu(&port->rlist); | 769 | hlist_del_init_rcu(&port->rlist); |
| 769 | br_rtr_notify(br->dev, port, RTM_DELMDB); | 770 | br_rtr_notify(br->dev, port, RTM_DELMDB); |
| 771 | /* Don't allow timer refresh if the router expired */ | ||
| 772 | if (port->multicast_router == MDB_RTR_TYPE_TEMP) | ||
| 773 | port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; | ||
| 770 | 774 | ||
| 771 | out: | 775 | out: |
| 772 | spin_unlock(&br->multicast_lock); | 776 | spin_unlock(&br->multicast_lock); |
| @@ -913,7 +917,7 @@ static void br_ip6_multicast_port_query_expired(unsigned long data) | |||
| 913 | 917 | ||
| 914 | void br_multicast_add_port(struct net_bridge_port *port) | 918 | void br_multicast_add_port(struct net_bridge_port *port) |
| 915 | { | 919 | { |
| 916 | port->multicast_router = 1; | 920 | port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 917 | 921 | ||
| 918 | setup_timer(&port->multicast_router_timer, br_multicast_router_expired, | 922 | setup_timer(&port->multicast_router_timer, br_multicast_router_expired, |
| 919 | (unsigned long)port); | 923 | (unsigned long)port); |
| @@ -960,7 +964,8 @@ void br_multicast_enable_port(struct net_bridge_port *port) | |||
| 960 | #if IS_ENABLED(CONFIG_IPV6) | 964 | #if IS_ENABLED(CONFIG_IPV6) |
| 961 | br_multicast_enable(&port->ip6_own_query); | 965 | br_multicast_enable(&port->ip6_own_query); |
| 962 | #endif | 966 | #endif |
| 963 | if (port->multicast_router == 2 && hlist_unhashed(&port->rlist)) | 967 | if (port->multicast_router == MDB_RTR_TYPE_PERM && |
| 968 | hlist_unhashed(&port->rlist)) | ||
| 964 | br_multicast_add_router(br, port); | 969 | br_multicast_add_router(br, port); |
| 965 | 970 | ||
| 966 | out: | 971 | out: |
| @@ -975,12 +980,15 @@ void br_multicast_disable_port(struct net_bridge_port *port) | |||
| 975 | 980 | ||
| 976 | spin_lock(&br->multicast_lock); | 981 | spin_lock(&br->multicast_lock); |
| 977 | hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) | 982 | hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) |
| 978 | if (pg->state == MDB_TEMPORARY) | 983 | if (!(pg->flags & MDB_PG_FLAGS_PERMANENT)) |
| 979 | br_multicast_del_pg(br, pg); | 984 | br_multicast_del_pg(br, pg); |
| 980 | 985 | ||
| 981 | if (!hlist_unhashed(&port->rlist)) { | 986 | if (!hlist_unhashed(&port->rlist)) { |
| 982 | hlist_del_init_rcu(&port->rlist); | 987 | hlist_del_init_rcu(&port->rlist); |
| 983 | br_rtr_notify(br->dev, port, RTM_DELMDB); | 988 | br_rtr_notify(br->dev, port, RTM_DELMDB); |
| 989 | /* Don't allow timer refresh if disabling */ | ||
| 990 | if (port->multicast_router == MDB_RTR_TYPE_TEMP) | ||
| 991 | port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; | ||
| 984 | } | 992 | } |
| 985 | del_timer(&port->multicast_router_timer); | 993 | del_timer(&port->multicast_router_timer); |
| 986 | del_timer(&port->ip4_own_query.timer); | 994 | del_timer(&port->ip4_own_query.timer); |
| @@ -1228,13 +1236,14 @@ static void br_multicast_mark_router(struct net_bridge *br, | |||
| 1228 | unsigned long now = jiffies; | 1236 | unsigned long now = jiffies; |
| 1229 | 1237 | ||
| 1230 | if (!port) { | 1238 | if (!port) { |
| 1231 | if (br->multicast_router == 1) | 1239 | if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) |
| 1232 | mod_timer(&br->multicast_router_timer, | 1240 | mod_timer(&br->multicast_router_timer, |
| 1233 | now + br->multicast_querier_interval); | 1241 | now + br->multicast_querier_interval); |
| 1234 | return; | 1242 | return; |
| 1235 | } | 1243 | } |
| 1236 | 1244 | ||
| 1237 | if (port->multicast_router != 1) | 1245 | if (port->multicast_router == MDB_RTR_TYPE_DISABLED || |
| 1246 | port->multicast_router == MDB_RTR_TYPE_PERM) | ||
| 1238 | return; | 1247 | return; |
| 1239 | 1248 | ||
| 1240 | br_multicast_add_router(br, port); | 1249 | br_multicast_add_router(br, port); |
| @@ -1454,7 +1463,7 @@ br_multicast_leave_group(struct net_bridge *br, | |||
| 1454 | del_timer(&p->timer); | 1463 | del_timer(&p->timer); |
| 1455 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 1464 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
| 1456 | br_mdb_notify(br->dev, port, group, RTM_DELMDB, | 1465 | br_mdb_notify(br->dev, port, group, RTM_DELMDB, |
| 1457 | p->state); | 1466 | p->flags); |
| 1458 | 1467 | ||
| 1459 | if (!mp->ports && !mp->mglist && | 1468 | if (!mp->ports && !mp->mglist && |
| 1460 | netif_running(br->dev)) | 1469 | netif_running(br->dev)) |
| @@ -1715,7 +1724,7 @@ void br_multicast_init(struct net_bridge *br) | |||
| 1715 | br->hash_elasticity = 4; | 1724 | br->hash_elasticity = 4; |
| 1716 | br->hash_max = 512; | 1725 | br->hash_max = 512; |
| 1717 | 1726 | ||
| 1718 | br->multicast_router = 1; | 1727 | br->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 1719 | br->multicast_querier = 0; | 1728 | br->multicast_querier = 0; |
| 1720 | br->multicast_query_use_ifaddr = 0; | 1729 | br->multicast_query_use_ifaddr = 0; |
| 1721 | br->multicast_last_member_count = 2; | 1730 | br->multicast_last_member_count = 2; |
| @@ -1825,11 +1834,11 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) | |||
| 1825 | spin_lock_bh(&br->multicast_lock); | 1834 | spin_lock_bh(&br->multicast_lock); |
| 1826 | 1835 | ||
| 1827 | switch (val) { | 1836 | switch (val) { |
| 1828 | case 0: | 1837 | case MDB_RTR_TYPE_DISABLED: |
| 1829 | case 2: | 1838 | case MDB_RTR_TYPE_PERM: |
| 1830 | del_timer(&br->multicast_router_timer); | 1839 | del_timer(&br->multicast_router_timer); |
| 1831 | /* fall through */ | 1840 | /* fall through */ |
| 1832 | case 1: | 1841 | case MDB_RTR_TYPE_TEMP_QUERY: |
| 1833 | br->multicast_router = val; | 1842 | br->multicast_router = val; |
| 1834 | err = 0; | 1843 | err = 0; |
| 1835 | break; | 1844 | break; |
| @@ -1840,37 +1849,53 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) | |||
| 1840 | return err; | 1849 | return err; |
| 1841 | } | 1850 | } |
| 1842 | 1851 | ||
| 1852 | static void __del_port_router(struct net_bridge_port *p) | ||
| 1853 | { | ||
| 1854 | if (hlist_unhashed(&p->rlist)) | ||
| 1855 | return; | ||
| 1856 | hlist_del_init_rcu(&p->rlist); | ||
| 1857 | br_rtr_notify(p->br->dev, p, RTM_DELMDB); | ||
| 1858 | } | ||
| 1859 | |||
| 1843 | int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) | 1860 | int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) |
| 1844 | { | 1861 | { |
| 1845 | struct net_bridge *br = p->br; | 1862 | struct net_bridge *br = p->br; |
| 1863 | unsigned long now = jiffies; | ||
| 1846 | int err = -EINVAL; | 1864 | int err = -EINVAL; |
| 1847 | 1865 | ||
| 1848 | spin_lock(&br->multicast_lock); | 1866 | spin_lock(&br->multicast_lock); |
| 1849 | 1867 | if (p->multicast_router == val) { | |
| 1850 | switch (val) { | 1868 | /* Refresh the temp router port timer */ |
| 1851 | case 0: | 1869 | if (p->multicast_router == MDB_RTR_TYPE_TEMP) |
| 1852 | case 1: | 1870 | mod_timer(&p->multicast_router_timer, |
| 1853 | case 2: | 1871 | now + br->multicast_querier_interval); |
| 1854 | p->multicast_router = val; | ||
| 1855 | err = 0; | 1872 | err = 0; |
| 1856 | 1873 | goto unlock; | |
| 1857 | if (val < 2 && !hlist_unhashed(&p->rlist)) { | 1874 | } |
| 1858 | hlist_del_init_rcu(&p->rlist); | 1875 | switch (val) { |
| 1859 | br_rtr_notify(br->dev, p, RTM_DELMDB); | 1876 | case MDB_RTR_TYPE_DISABLED: |
| 1860 | } | 1877 | p->multicast_router = MDB_RTR_TYPE_DISABLED; |
| 1861 | 1878 | __del_port_router(p); | |
| 1862 | if (val == 1) | 1879 | del_timer(&p->multicast_router_timer); |
| 1863 | break; | 1880 | break; |
| 1864 | 1881 | case MDB_RTR_TYPE_TEMP_QUERY: | |
| 1882 | p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; | ||
| 1883 | __del_port_router(p); | ||
| 1884 | break; | ||
| 1885 | case MDB_RTR_TYPE_PERM: | ||
| 1886 | p->multicast_router = MDB_RTR_TYPE_PERM; | ||
| 1865 | del_timer(&p->multicast_router_timer); | 1887 | del_timer(&p->multicast_router_timer); |
| 1866 | |||
| 1867 | if (val == 0) | ||
| 1868 | break; | ||
| 1869 | |||
| 1870 | br_multicast_add_router(br, p); | 1888 | br_multicast_add_router(br, p); |
| 1871 | break; | 1889 | break; |
| 1890 | case MDB_RTR_TYPE_TEMP: | ||
| 1891 | p->multicast_router = MDB_RTR_TYPE_TEMP; | ||
| 1892 | br_multicast_mark_router(br, p); | ||
| 1893 | break; | ||
| 1894 | default: | ||
| 1895 | goto unlock; | ||
| 1872 | } | 1896 | } |
| 1873 | 1897 | err = 0; | |
| 1898 | unlock: | ||
| 1874 | spin_unlock(&br->multicast_lock); | 1899 | spin_unlock(&br->multicast_lock); |
| 1875 | 1900 | ||
| 1876 | return err; | 1901 | return err; |
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 7ddbe7ec81d6..44114a94c576 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <net/addrconf.h> | 37 | #include <net/addrconf.h> |
| 38 | #include <net/route.h> | 38 | #include <net/route.h> |
| 39 | #include <net/netfilter/br_netfilter.h> | 39 | #include <net/netfilter/br_netfilter.h> |
| 40 | #include <net/netns/generic.h> | ||
| 40 | 41 | ||
| 41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| 42 | #include "br_private.h" | 43 | #include "br_private.h" |
| @@ -44,6 +45,12 @@ | |||
| 44 | #include <linux/sysctl.h> | 45 | #include <linux/sysctl.h> |
| 45 | #endif | 46 | #endif |
| 46 | 47 | ||
| 48 | static int brnf_net_id __read_mostly; | ||
| 49 | |||
| 50 | struct brnf_net { | ||
| 51 | bool enabled; | ||
| 52 | }; | ||
| 53 | |||
| 47 | #ifdef CONFIG_SYSCTL | 54 | #ifdef CONFIG_SYSCTL |
| 48 | static struct ctl_table_header *brnf_sysctl_header; | 55 | static struct ctl_table_header *brnf_sysctl_header; |
| 49 | static int brnf_call_iptables __read_mostly = 1; | 56 | static int brnf_call_iptables __read_mostly = 1; |
| @@ -938,6 +945,53 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { | |||
| 938 | }, | 945 | }, |
| 939 | }; | 946 | }; |
| 940 | 947 | ||
| 948 | static int brnf_device_event(struct notifier_block *unused, unsigned long event, | ||
| 949 | void *ptr) | ||
| 950 | { | ||
| 951 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
| 952 | struct brnf_net *brnet; | ||
| 953 | struct net *net; | ||
| 954 | int ret; | ||
| 955 | |||
| 956 | if (event != NETDEV_REGISTER || !(dev->priv_flags & IFF_EBRIDGE)) | ||
| 957 | return NOTIFY_DONE; | ||
| 958 | |||
| 959 | ASSERT_RTNL(); | ||
| 960 | |||
| 961 | net = dev_net(dev); | ||
| 962 | brnet = net_generic(net, brnf_net_id); | ||
| 963 | if (brnet->enabled) | ||
| 964 | return NOTIFY_OK; | ||
| 965 | |||
| 966 | ret = nf_register_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops)); | ||
| 967 | if (ret) | ||
| 968 | return NOTIFY_BAD; | ||
| 969 | |||
| 970 | brnet->enabled = true; | ||
| 971 | return NOTIFY_OK; | ||
| 972 | } | ||
| 973 | |||
| 974 | static void __net_exit brnf_exit_net(struct net *net) | ||
| 975 | { | ||
| 976 | struct brnf_net *brnet = net_generic(net, brnf_net_id); | ||
| 977 | |||
| 978 | if (!brnet->enabled) | ||
| 979 | return; | ||
| 980 | |||
| 981 | nf_unregister_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops)); | ||
| 982 | brnet->enabled = false; | ||
| 983 | } | ||
| 984 | |||
| 985 | static struct pernet_operations brnf_net_ops __read_mostly = { | ||
| 986 | .exit = brnf_exit_net, | ||
| 987 | .id = &brnf_net_id, | ||
| 988 | .size = sizeof(struct brnf_net), | ||
| 989 | }; | ||
| 990 | |||
| 991 | static struct notifier_block brnf_notifier __read_mostly = { | ||
| 992 | .notifier_call = brnf_device_event, | ||
| 993 | }; | ||
| 994 | |||
| 941 | #ifdef CONFIG_SYSCTL | 995 | #ifdef CONFIG_SYSCTL |
| 942 | static | 996 | static |
| 943 | int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, | 997 | int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, |
| @@ -1003,16 +1057,23 @@ static int __init br_netfilter_init(void) | |||
| 1003 | { | 1057 | { |
| 1004 | int ret; | 1058 | int ret; |
| 1005 | 1059 | ||
| 1006 | ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | 1060 | ret = register_pernet_subsys(&brnf_net_ops); |
| 1007 | if (ret < 0) | 1061 | if (ret < 0) |
| 1008 | return ret; | 1062 | return ret; |
| 1009 | 1063 | ||
| 1064 | ret = register_netdevice_notifier(&brnf_notifier); | ||
| 1065 | if (ret < 0) { | ||
| 1066 | unregister_pernet_subsys(&brnf_net_ops); | ||
| 1067 | return ret; | ||
| 1068 | } | ||
| 1069 | |||
| 1010 | #ifdef CONFIG_SYSCTL | 1070 | #ifdef CONFIG_SYSCTL |
| 1011 | brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); | 1071 | brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); |
| 1012 | if (brnf_sysctl_header == NULL) { | 1072 | if (brnf_sysctl_header == NULL) { |
| 1013 | printk(KERN_WARNING | 1073 | printk(KERN_WARNING |
| 1014 | "br_netfilter: can't register to sysctl.\n"); | 1074 | "br_netfilter: can't register to sysctl.\n"); |
| 1015 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | 1075 | unregister_netdevice_notifier(&brnf_notifier); |
| 1076 | unregister_pernet_subsys(&brnf_net_ops); | ||
| 1016 | return -ENOMEM; | 1077 | return -ENOMEM; |
| 1017 | } | 1078 | } |
| 1018 | #endif | 1079 | #endif |
| @@ -1024,7 +1085,8 @@ static int __init br_netfilter_init(void) | |||
| 1024 | static void __exit br_netfilter_fini(void) | 1085 | static void __exit br_netfilter_fini(void) |
| 1025 | { | 1086 | { |
| 1026 | RCU_INIT_POINTER(nf_br_ops, NULL); | 1087 | RCU_INIT_POINTER(nf_br_ops, NULL); |
| 1027 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | 1088 | unregister_netdevice_notifier(&brnf_notifier); |
| 1089 | unregister_pernet_subsys(&brnf_net_ops); | ||
| 1028 | #ifdef CONFIG_SYSCTL | 1090 | #ifdef CONFIG_SYSCTL |
| 1029 | unregister_net_sysctl_table(brnf_sysctl_header); | 1091 | unregister_net_sysctl_table(brnf_sysctl_header); |
| 1030 | #endif | 1092 | #endif |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 40197ff8918a..e9c635eae24d 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
| @@ -598,7 +598,6 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state) | |||
| 598 | return -ENETDOWN; | 598 | return -ENETDOWN; |
| 599 | 599 | ||
| 600 | br_set_state(p, state); | 600 | br_set_state(p, state); |
| 601 | br_log_state(p); | ||
| 602 | br_port_state_selection(p->br); | 601 | br_port_state_selection(p->br); |
| 603 | return 0; | 602 | return 0; |
| 604 | } | 603 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 216018c76018..d9da857182ef 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -150,6 +150,9 @@ struct net_bridge_fdb_entry | |||
| 150 | struct rcu_head rcu; | 150 | struct rcu_head rcu; |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | #define MDB_PG_FLAGS_PERMANENT BIT(0) | ||
| 154 | #define MDB_PG_FLAGS_OFFLOAD BIT(1) | ||
| 155 | |||
| 153 | struct net_bridge_port_group { | 156 | struct net_bridge_port_group { |
| 154 | struct net_bridge_port *port; | 157 | struct net_bridge_port *port; |
| 155 | struct net_bridge_port_group __rcu *next; | 158 | struct net_bridge_port_group __rcu *next; |
| @@ -157,7 +160,7 @@ struct net_bridge_port_group { | |||
| 157 | struct rcu_head rcu; | 160 | struct rcu_head rcu; |
| 158 | struct timer_list timer; | 161 | struct timer_list timer; |
| 159 | struct br_ip addr; | 162 | struct br_ip addr; |
| 160 | unsigned char state; | 163 | unsigned char flags; |
| 161 | }; | 164 | }; |
| 162 | 165 | ||
| 163 | struct net_bridge_mdb_entry | 166 | struct net_bridge_mdb_entry |
| @@ -554,11 +557,11 @@ void br_multicast_free_pg(struct rcu_head *head); | |||
| 554 | struct net_bridge_port_group * | 557 | struct net_bridge_port_group * |
| 555 | br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, | 558 | br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, |
| 556 | struct net_bridge_port_group __rcu *next, | 559 | struct net_bridge_port_group __rcu *next, |
| 557 | unsigned char state); | 560 | unsigned char flags); |
| 558 | void br_mdb_init(void); | 561 | void br_mdb_init(void); |
| 559 | void br_mdb_uninit(void); | 562 | void br_mdb_uninit(void); |
| 560 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | 563 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
| 561 | struct br_ip *group, int type, u8 state); | 564 | struct br_ip *group, int type, u8 flags); |
| 562 | void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, | 565 | void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, |
| 563 | int type); | 566 | int type); |
| 564 | 567 | ||
| @@ -897,7 +900,6 @@ static inline void br_nf_core_fini(void) {} | |||
| 897 | #endif | 900 | #endif |
| 898 | 901 | ||
| 899 | /* br_stp.c */ | 902 | /* br_stp.c */ |
| 900 | void br_log_state(const struct net_bridge_port *p); | ||
| 901 | void br_set_state(struct net_bridge_port *p, unsigned int state); | 903 | void br_set_state(struct net_bridge_port *p, unsigned int state); |
| 902 | struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no); | 904 | struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no); |
| 903 | void br_init_port(struct net_bridge_port *p); | 905 | void br_init_port(struct net_bridge_port *p); |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index b3cca126b103..9cb7044d0801 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
| @@ -30,13 +30,6 @@ static const char *const br_port_state_names[] = { | |||
| 30 | [BR_STATE_BLOCKING] = "blocking", | 30 | [BR_STATE_BLOCKING] = "blocking", |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | void br_log_state(const struct net_bridge_port *p) | ||
| 34 | { | ||
| 35 | br_info(p->br, "port %u(%s) entered %s state\n", | ||
| 36 | (unsigned int) p->port_no, p->dev->name, | ||
| 37 | br_port_state_names[p->state]); | ||
| 38 | } | ||
| 39 | |||
| 40 | void br_set_state(struct net_bridge_port *p, unsigned int state) | 33 | void br_set_state(struct net_bridge_port *p, unsigned int state) |
| 41 | { | 34 | { |
| 42 | struct switchdev_attr attr = { | 35 | struct switchdev_attr attr = { |
| @@ -52,6 +45,10 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) | |||
| 52 | if (err && err != -EOPNOTSUPP) | 45 | if (err && err != -EOPNOTSUPP) |
| 53 | br_warn(p->br, "error setting offload STP state on port %u(%s)\n", | 46 | br_warn(p->br, "error setting offload STP state on port %u(%s)\n", |
| 54 | (unsigned int) p->port_no, p->dev->name); | 47 | (unsigned int) p->port_no, p->dev->name); |
| 48 | else | ||
| 49 | br_info(p->br, "port %u(%s) entered %s state\n", | ||
| 50 | (unsigned int) p->port_no, p->dev->name, | ||
| 51 | br_port_state_names[p->state]); | ||
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | /* called under bridge lock */ | 54 | /* called under bridge lock */ |
| @@ -126,7 +123,6 @@ static void br_root_port_block(const struct net_bridge *br, | |||
| 126 | (unsigned int) p->port_no, p->dev->name); | 123 | (unsigned int) p->port_no, p->dev->name); |
| 127 | 124 | ||
| 128 | br_set_state(p, BR_STATE_LISTENING); | 125 | br_set_state(p, BR_STATE_LISTENING); |
| 129 | br_log_state(p); | ||
| 130 | br_ifinfo_notify(RTM_NEWLINK, p); | 126 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 131 | 127 | ||
| 132 | if (br->forward_delay > 0) | 128 | if (br->forward_delay > 0) |
| @@ -407,7 +403,6 @@ static void br_make_blocking(struct net_bridge_port *p) | |||
| 407 | br_topology_change_detection(p->br); | 403 | br_topology_change_detection(p->br); |
| 408 | 404 | ||
| 409 | br_set_state(p, BR_STATE_BLOCKING); | 405 | br_set_state(p, BR_STATE_BLOCKING); |
| 410 | br_log_state(p); | ||
| 411 | br_ifinfo_notify(RTM_NEWLINK, p); | 406 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 412 | 407 | ||
| 413 | del_timer(&p->forward_delay_timer); | 408 | del_timer(&p->forward_delay_timer); |
| @@ -431,7 +426,6 @@ static void br_make_forwarding(struct net_bridge_port *p) | |||
| 431 | else | 426 | else |
| 432 | br_set_state(p, BR_STATE_LEARNING); | 427 | br_set_state(p, BR_STATE_LEARNING); |
| 433 | 428 | ||
| 434 | br_log_state(p); | ||
| 435 | br_ifinfo_notify(RTM_NEWLINK, p); | 429 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 436 | 430 | ||
| 437 | if (br->forward_delay != 0) | 431 | if (br->forward_delay != 0) |
| @@ -568,6 +562,14 @@ int br_set_max_age(struct net_bridge *br, unsigned long val) | |||
| 568 | 562 | ||
| 569 | } | 563 | } |
| 570 | 564 | ||
| 565 | /* Set time interval that dynamic forwarding entries live | ||
| 566 | * For pure software bridge, allow values outside the 802.1 | ||
| 567 | * standard specification for special cases: | ||
| 568 | * 0 - entry never ages (all permanant) | ||
| 569 | * 1 - entry disappears (no persistance) | ||
| 570 | * | ||
| 571 | * Offloaded switch entries maybe more restrictive | ||
| 572 | */ | ||
| 571 | int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) | 573 | int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) |
| 572 | { | 574 | { |
| 573 | struct switchdev_attr attr = { | 575 | struct switchdev_attr attr = { |
| @@ -579,11 +581,8 @@ int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) | |||
| 579 | unsigned long t = clock_t_to_jiffies(ageing_time); | 581 | unsigned long t = clock_t_to_jiffies(ageing_time); |
| 580 | int err; | 582 | int err; |
| 581 | 583 | ||
| 582 | if (t < BR_MIN_AGEING_TIME || t > BR_MAX_AGEING_TIME) | ||
| 583 | return -ERANGE; | ||
| 584 | |||
| 585 | err = switchdev_port_attr_set(br->dev, &attr); | 584 | err = switchdev_port_attr_set(br->dev, &attr); |
| 586 | if (err) | 585 | if (err && err != -EOPNOTSUPP) |
| 587 | return err; | 586 | return err; |
| 588 | 587 | ||
| 589 | br->ageing_time = t; | 588 | br->ageing_time = t; |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index a31ac6ad76a2..984d46263007 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
| @@ -102,7 +102,6 @@ void br_stp_enable_port(struct net_bridge_port *p) | |||
| 102 | { | 102 | { |
| 103 | br_init_port(p); | 103 | br_init_port(p); |
| 104 | br_port_state_selection(p->br); | 104 | br_port_state_selection(p->br); |
| 105 | br_log_state(p); | ||
| 106 | br_ifinfo_notify(RTM_NEWLINK, p); | 105 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 107 | } | 106 | } |
| 108 | 107 | ||
| @@ -118,7 +117,6 @@ void br_stp_disable_port(struct net_bridge_port *p) | |||
| 118 | p->topology_change_ack = 0; | 117 | p->topology_change_ack = 0; |
| 119 | p->config_pending = 0; | 118 | p->config_pending = 0; |
| 120 | 119 | ||
| 121 | br_log_state(p); | ||
| 122 | br_ifinfo_notify(RTM_NEWLINK, p); | 120 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 123 | 121 | ||
| 124 | del_timer(&p->message_age_timer); | 122 | del_timer(&p->message_age_timer); |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 5f0f5af0ec35..da058b85aa22 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
| @@ -98,7 +98,6 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
| 98 | br_topology_change_detection(br); | 98 | br_topology_change_detection(br); |
| 99 | netif_carrier_on(br->dev); | 99 | netif_carrier_on(br->dev); |
| 100 | } | 100 | } |
| 101 | br_log_state(p); | ||
| 102 | rcu_read_lock(); | 101 | rcu_read_lock(); |
| 103 | br_ifinfo_notify(RTM_NEWLINK, p); | 102 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 104 | rcu_read_unlock(); | 103 | rcu_read_unlock(); |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 85e43af4af7a..9309bb4f2a5b 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -955,6 +955,13 @@ err_rhtbl: | |||
| 955 | */ | 955 | */ |
| 956 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) | 956 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) |
| 957 | { | 957 | { |
| 958 | struct switchdev_obj_port_vlan v = { | ||
| 959 | .obj.orig_dev = port->dev, | ||
| 960 | .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, | ||
| 961 | .flags = flags, | ||
| 962 | .vid_begin = vid, | ||
| 963 | .vid_end = vid, | ||
| 964 | }; | ||
| 958 | struct net_bridge_vlan *vlan; | 965 | struct net_bridge_vlan *vlan; |
| 959 | int ret; | 966 | int ret; |
| 960 | 967 | ||
| @@ -962,6 +969,10 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) | |||
| 962 | 969 | ||
| 963 | vlan = br_vlan_find(nbp_vlan_group(port), vid); | 970 | vlan = br_vlan_find(nbp_vlan_group(port), vid); |
| 964 | if (vlan) { | 971 | if (vlan) { |
| 972 | /* Pass the flags to the hardware bridge */ | ||
| 973 | ret = switchdev_port_obj_add(port->dev, &v.obj); | ||
| 974 | if (ret && ret != -EOPNOTSUPP) | ||
| 975 | return ret; | ||
| 965 | __vlan_add_flags(vlan, flags); | 976 | __vlan_add_flags(vlan, flags); |
| 966 | return 0; | 977 | return 0; |
| 967 | } | 978 | } |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 67b2e27999aa..5a61f35412a0 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -370,7 +370,11 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, | |||
| 370 | left - sizeof(struct ebt_entry_match) < m->match_size) | 370 | left - sizeof(struct ebt_entry_match) < m->match_size) |
| 371 | return -EINVAL; | 371 | return -EINVAL; |
| 372 | 372 | ||
| 373 | match = xt_request_find_match(NFPROTO_BRIDGE, m->u.name, 0); | 373 | match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); |
| 374 | if (IS_ERR(match) || match->family != NFPROTO_BRIDGE) { | ||
| 375 | request_module("ebt_%s", m->u.name); | ||
| 376 | match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); | ||
| 377 | } | ||
| 374 | if (IS_ERR(match)) | 378 | if (IS_ERR(match)) |
| 375 | return PTR_ERR(match); | 379 | return PTR_ERR(match); |
| 376 | m->u.match = match; | 380 | m->u.match = match; |
| @@ -1521,6 +1525,8 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1521 | if (copy_from_user(&tmp, user, sizeof(tmp))) | 1525 | if (copy_from_user(&tmp, user, sizeof(tmp))) |
| 1522 | return -EFAULT; | 1526 | return -EFAULT; |
| 1523 | 1527 | ||
| 1528 | tmp.name[sizeof(tmp.name) - 1] = '\0'; | ||
| 1529 | |||
| 1524 | t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); | 1530 | t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); |
| 1525 | if (!t) | 1531 | if (!t) |
| 1526 | return ret; | 1532 | return ret; |
| @@ -2332,6 +2338,8 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd, | |||
| 2332 | if (copy_from_user(&tmp, user, sizeof(tmp))) | 2338 | if (copy_from_user(&tmp, user, sizeof(tmp))) |
| 2333 | return -EFAULT; | 2339 | return -EFAULT; |
| 2334 | 2340 | ||
| 2341 | tmp.name[sizeof(tmp.name) - 1] = '\0'; | ||
| 2342 | |||
| 2335 | t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); | 2343 | t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); |
| 2336 | if (!t) | 2344 | if (!t) |
| 2337 | return ret; | 2345 | return ret; |
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index fdba3d9fbff3..77f7e7a9ebe1 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
| @@ -40,7 +40,8 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | |||
| 40 | /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT) | 40 | /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT) |
| 41 | * or the bridge port (NF_BRIDGE PREROUTING). | 41 | * or the bridge port (NF_BRIDGE PREROUTING). |
| 42 | */ | 42 | */ |
| 43 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, | 43 | static void nft_reject_br_send_v4_tcp_reset(struct net *net, |
| 44 | struct sk_buff *oldskb, | ||
| 44 | const struct net_device *dev, | 45 | const struct net_device *dev, |
| 45 | int hook) | 46 | int hook) |
| 46 | { | 47 | { |
| @@ -63,9 +64,9 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, | |||
| 63 | 64 | ||
| 64 | skb_reserve(nskb, LL_MAX_HEADER); | 65 | skb_reserve(nskb, LL_MAX_HEADER); |
| 65 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, | 66 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, |
| 66 | sysctl_ip_default_ttl); | 67 | net->ipv4.sysctl_ip_default_ttl); |
| 67 | nf_reject_ip_tcphdr_put(nskb, oldskb, oth); | 68 | nf_reject_ip_tcphdr_put(nskb, oldskb, oth); |
| 68 | niph->ttl = sysctl_ip_default_ttl; | 69 | niph->ttl = net->ipv4.sysctl_ip_default_ttl; |
| 69 | niph->tot_len = htons(nskb->len); | 70 | niph->tot_len = htons(nskb->len); |
| 70 | ip_send_check(niph); | 71 | ip_send_check(niph); |
| 71 | 72 | ||
| @@ -74,7 +75,8 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, | |||
| 74 | br_deliver(br_port_get_rcu(dev), nskb); | 75 | br_deliver(br_port_get_rcu(dev), nskb); |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, | 78 | static void nft_reject_br_send_v4_unreach(struct net *net, |
| 79 | struct sk_buff *oldskb, | ||
| 78 | const struct net_device *dev, | 80 | const struct net_device *dev, |
| 79 | int hook, u8 code) | 81 | int hook, u8 code) |
| 80 | { | 82 | { |
| @@ -119,7 +121,7 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, | |||
| 119 | 121 | ||
| 120 | skb_reserve(nskb, LL_MAX_HEADER); | 122 | skb_reserve(nskb, LL_MAX_HEADER); |
| 121 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, | 123 | niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, |
| 122 | sysctl_ip_default_ttl); | 124 | net->ipv4.sysctl_ip_default_ttl); |
| 123 | 125 | ||
| 124 | skb_reset_transport_header(nskb); | 126 | skb_reset_transport_header(nskb); |
| 125 | icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); | 127 | icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); |
| @@ -271,17 +273,17 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
| 271 | case htons(ETH_P_IP): | 273 | case htons(ETH_P_IP): |
| 272 | switch (priv->type) { | 274 | switch (priv->type) { |
| 273 | case NFT_REJECT_ICMP_UNREACH: | 275 | case NFT_REJECT_ICMP_UNREACH: |
| 274 | nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, | 276 | nft_reject_br_send_v4_unreach(pkt->net, pkt->skb, |
| 275 | pkt->hook, | 277 | pkt->in, pkt->hook, |
| 276 | priv->icmp_code); | 278 | priv->icmp_code); |
| 277 | break; | 279 | break; |
| 278 | case NFT_REJECT_TCP_RST: | 280 | case NFT_REJECT_TCP_RST: |
| 279 | nft_reject_br_send_v4_tcp_reset(pkt->skb, pkt->in, | 281 | nft_reject_br_send_v4_tcp_reset(pkt->net, pkt->skb, |
| 280 | pkt->hook); | 282 | pkt->in, pkt->hook); |
| 281 | break; | 283 | break; |
| 282 | case NFT_REJECT_ICMPX_UNREACH: | 284 | case NFT_REJECT_ICMPX_UNREACH: |
| 283 | nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, | 285 | nft_reject_br_send_v4_unreach(pkt->net, pkt->skb, |
| 284 | pkt->hook, | 286 | pkt->in, pkt->hook, |
| 285 | nft_reject_icmp_code(priv->icmp_code)); | 287 | nft_reject_icmp_code(priv->icmp_code)); |
| 286 | break; | 288 | break; |
| 287 | } | 289 | } |
