From e68e498ff35412daba861c9d6d8ebad8f22a6465 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 4 Jul 2018 20:14:08 +0200 Subject: [PATCH] kernel: replace bridge port isolate hack with upstream patch backport on 4.14 Signed-off-by: Felix Fietkau (backported from 21ee8ce9b52f8ae4a6babf4032f71e2d4d56392b) (rebased patches) Signed-off-by: Jo-Philipp Wich --- ...ridge-add-support-for-port-isolation.patch | 145 ++++++++++++++++++ .../640-bridge-only-accept-EAP-locally.patch | 7 +- .../hack-4.14/641-bridge_port_isolate.patch | 76 --------- ...ge_allow_receiption_on_disabled_port.patch | 4 +- 4 files changed, 150 insertions(+), 82 deletions(-) create mode 100644 target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch delete mode 100644 target/linux/generic/hack-4.14/641-bridge_port_isolate.patch diff --git a/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch b/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch new file mode 100644 index 0000000000..6237177a45 --- /dev/null +++ b/target/linux/generic/backport-4.14/090-net-bridge-add-support-for-port-isolation.patch @@ -0,0 +1,145 @@ +From: Nikolay Aleksandrov +Date: Thu, 24 May 2018 11:56:48 +0300 +Subject: [PATCH] net: bridge: add support for port isolation + +This patch adds support for a new port flag - BR_ISOLATED. If it is set +then isolated ports cannot communicate between each other, but they can +still communicate with non-isolated ports. The same can be achieved via +ACLs but they can't scale with large number of ports and also the +complexity of the rules grows. This feature can be used to achieve +isolated vlan functionality (similar to pvlan) as well, though currently +it will be port-wide (for all vlans on the port). The new test in +should_deliver uses data that is already cache hot and the new boolean +is used to avoid an additional source port test in should_deliver. + +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Toshiaki Makita +Signed-off-by: David S. Miller +--- + +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -326,6 +326,8 @@ enum { + IFLA_BRPORT_MCAST_TO_UCAST, + IFLA_BRPORT_VLAN_TUNNEL, + IFLA_BRPORT_BCAST_FLOOD, ++ IFLA_BRPORT_NEIGH_SUPPRESS, ++ IFLA_BRPORT_ISOLATED, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -30,7 +30,8 @@ static inline int should_deliver(const s + vg = nbp_vlan_group_rcu(p); + return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && + br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING && +- nbp_switchdev_allowed_egress(p, skb); ++ nbp_switchdev_allowed_egress(p, skb) && ++ !br_skb_isolated(p, skb); + } + + int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -170,6 +170,7 @@ int br_handle_frame_finish(struct net *n + goto drop; + + BR_INPUT_SKB_CB(skb)->brdev = br->dev; ++ BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED); + + if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) + br_do_proxy_arp(skb, br, vid, p); +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -138,6 +138,7 @@ static inline size_t br_port_info_size(v + + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */ + + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */ + + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ ++ + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ +@@ -208,7 +209,8 @@ static int br_port_fill_attrs(struct sk_ + p->topology_change_ack) || + nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) || + nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags & +- BR_VLAN_TUNNEL))) ++ BR_VLAN_TUNNEL)) || ++ nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) + return -EMSGSIZE; + + timerval = br_timer_value(&p->message_age_timer); +@@ -637,6 +639,7 @@ static const struct nla_policy br_port_p + [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 }, + [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 }, + [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 }, ++ [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, + }; + + /* Change the state of the port and notify spanning tree */ +@@ -773,6 +776,11 @@ static int br_setport(struct net_bridge_ + return err; + } + #endif ++ ++ err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); ++ if (err) ++ return err; ++ + br_port_flags_change(p, old_flags ^ p->flags); + return 0; + } +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -407,6 +407,7 @@ struct br_input_skb_cb { + #endif + + bool proxyarp_replied; ++ bool src_port_isolated; + + #ifdef CONFIG_BRIDGE_VLAN_FILTERING + bool vlan_filtered; +@@ -554,6 +555,14 @@ int br_forward_finish(struct net *net, s + void br_flood(struct net_bridge *br, struct sk_buff *skb, + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig); + ++/* return true if both source port and dest port are isolated */ ++static inline bool br_skb_isolated(const struct net_bridge_port *to, ++ const struct sk_buff *skb) ++{ ++ return BR_INPUT_SKB_CB(skb)->src_port_isolated && ++ (to->flags & BR_ISOLATED); ++} ++ + /* br_if.c */ + void br_port_carrier_check(struct net_bridge_port *p); + int br_add_bridge(struct net *net, const char *name); +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -174,6 +174,7 @@ BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); + BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); + BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD); + BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); ++BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -223,6 +224,7 @@ static const struct brport_attribute *br + &brport_attr_proxyarp_wifi, + &brport_attr_multicast_flood, + &brport_attr_broadcast_flood, ++ &brport_attr_isolated, + NULL + }; + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -49,6 +49,7 @@ struct br_ip_list { + #define BR_MULTICAST_TO_UNICAST BIT(12) + #define BR_VLAN_TUNNEL BIT(13) + #define BR_BCAST_FLOOD BIT(14) ++#define BR_ISOLATED BIT(16) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + diff --git a/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch b/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch index 83c9cf739f..0dbb8ee3c0 100644 --- a/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch +++ b/target/linux/generic/hack-4.14/640-bridge-only-accept-EAP-locally.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -166,11 +166,14 @@ int br_handle_frame_finish(struct net *n +@@ -166,10 +166,14 @@ int br_handle_frame_finish(struct net *n } } @@ -26,7 +26,6 @@ Signed-off-by: Felix Fietkau goto drop; - BR_INPUT_SKB_CB(skb)->brdev = br->dev; -- - if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) - br_do_proxy_arp(skb, br, vid, p); + BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED); + if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) diff --git a/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch b/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch deleted file mode 100644 index 43e71ee2ff..0000000000 --- a/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch +++ /dev/null @@ -1,76 +0,0 @@ -From e988390850731aa1697ed09d47b0932fac1af175 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Fri, 7 Jul 2017 17:20:03 +0200 -Subject: bridge: port isolate - -Isolating individual bridge ports - -Signed-off-by: Felix Fietkau ---- - include/linux/if_bridge.h | 1 + - net/bridge/br_forward.c | 5 +++++ - net/bridge/br_input.c | 3 +++ - net/bridge/br_sysfs_if.c | 2 ++ - 4 files changed, 11 insertions(+) - ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -49,6 +49,7 @@ struct br_ip_list { - #define BR_MULTICAST_TO_UNICAST BIT(12) - #define BR_VLAN_TUNNEL BIT(13) - #define BR_BCAST_FLOOD BIT(14) -+#define BR_ISOLATE_MODE BIT(15) - - #define BR_DEFAULT_AGEING_TIME (300 * HZ) - ---- a/net/bridge/br_forward.c -+++ b/net/bridge/br_forward.c -@@ -141,6 +141,9 @@ static int deliver_clone(const struct ne - void br_forward(const struct net_bridge_port *to, - struct sk_buff *skb, bool local_rcv, bool local_orig) - { -+ if (to->flags & BR_ISOLATE_MODE && !local_orig) -+ to = NULL; -+ - if (to && should_deliver(to, skb)) { - if (local_rcv) - deliver_clone(to, skb, local_orig); -@@ -183,6 +186,8 @@ void br_flood(struct net_bridge *br, str - struct net_bridge_port *p; - - list_for_each_entry_rcu(p, &br->port_list, list) { -+ if (!local_orig && (p->flags & BR_ISOLATE_MODE)) -+ continue; - /* Do not flood unicast traffic to ports that turn it off, nor - * other traffic if flood off, except for traffic we originate - */ ---- a/net/bridge/br_input.c -+++ b/net/bridge/br_input.c -@@ -177,6 +177,9 @@ int br_handle_frame_finish(struct net *n - if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP)) - br_do_proxy_arp(skb, br, vid, p); - -+ if (p->flags & BR_ISOLATE_MODE) -+ return br_pass_frame_up(skb); -+ - switch (pkt_type) { - case BR_PKT_MULTICAST: - mdst = br_mdb_get(br, skb, vid); ---- a/net/bridge/br_sysfs_if.c -+++ b/net/bridge/br_sysfs_if.c -@@ -174,6 +174,7 @@ BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); - BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); - BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD); - BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); -+BRPORT_ATTR_FLAG(isolated, BR_ISOLATE_MODE); - - #ifdef CONFIG_BRIDGE_IGMP_SNOOPING - static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) -@@ -223,6 +224,7 @@ static const struct brport_attribute *br - &brport_attr_proxyarp_wifi, - &brport_attr_multicast_flood, - &brport_attr_broadcast_flood, -+ &brport_attr_isolated, - NULL - }; - diff --git a/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch index 03267310a0..9fcffdee06 100644 --- a/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch +++ b/target/linux/generic/pending-4.14/150-bridge_allow_receiption_on_disabled_port.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -238,7 +238,8 @@ static int br_handle_local_finish(struct +@@ -239,7 +239,8 @@ static int br_handle_local_finish(struct { struct net_bridge_port *p = br_port_get_rcu(skb->dev); @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau BR_INPUT_SKB_CB(skb)->brdev = p->br->dev; br_pass_frame_up(skb); -@@ -326,6 +327,15 @@ rx_handler_result_t br_handle_frame(stru +@@ -327,6 +328,15 @@ rx_handler_result_t br_handle_frame(stru forward: switch (p->state) { -- 2.30.2