From patchwork Wed Feb 1 06:59:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 722363 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vCvCW1h4vz9rxw for ; Wed, 1 Feb 2017 18:00:23 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="L5IgsmBR"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751405AbdBAHAQ (ORCPT ); Wed, 1 Feb 2017 02:00:16 -0500 Received: from mail-pg0-f47.google.com ([74.125.83.47]:34851 "EHLO mail-pg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751080AbdBAHAL (ORCPT ); Wed, 1 Feb 2017 02:00:11 -0500 Received: by mail-pg0-f47.google.com with SMTP id 194so106795961pgd.2 for ; Tue, 31 Jan 2017 23:00:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nAsYfrfJNuw8bLmDa2SYxZVDJuoquaqs0UYsUuB5kaM=; b=L5IgsmBRhejMy1a8/HP8kHhpR+4A1RUlH9V2Ke9pMpWky+GaEJg8HIuhyRSTsOAKdb PdmcPMbhda/fhTG2TYGcgfUmNdokx+nBmxqTZrcf3DS/gvJP6IDCsf3V1nTIh6oG6EzW U1nkCCgWy3otu3Wdj52zVJcy7ORqh8ZEg0iaI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nAsYfrfJNuw8bLmDa2SYxZVDJuoquaqs0UYsUuB5kaM=; b=bH0i8Hykkw7Y2dS7cY3uLLnxvM2PrxRGHb8YQcFbup4GveirdOJLaLn6ZDvEpV0Jge oHd1pKE3zC1uSD/XpmCs4CQgoCjn4BZmmgEj3rppqmfvKa6tNDCaPyKrx23+/iCNwfW1 uAYDAyN1E6HWwed5Hvdng9kjTezjmOBwG2vB7ePjwRe6GwgOaz6gYd4x3NmtFdzCkxkM 1yPq3Q31PrIk2NA6ARSBAd+PBD0owHZfEqsgUPnPPoGjH8JuHV6t2wuDkTCm+cat2/Fg EAqq4q/EPRWF/eZn0h6gTgw+BqVc0X4qEYid7hBTCgv6Ps5v9Hq6oyJozDIm91Z/hXrt IQ7A== X-Gm-Message-State: AIkVDXI9ZOsAj0z/YzFkyAlsmBkg7j2H2Y/yDzLddmXPd1hDhV4d378Lwi3suXoQN0JzmSuI X-Received: by 10.84.232.67 with SMTP id f3mr2094825pln.55.1485932405915; Tue, 31 Jan 2017 23:00:05 -0800 (PST) Received: from hydra-01.mvlab.cumulusnetworks.com ([216.129.126.126]) by smtp.googlemail.com with ESMTPSA id f3sm46275999pfd.10.2017.01.31.23.00.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 31 Jan 2017 23:00:05 -0800 (PST) From: Roopa Prabhu X-Google-Original-From: Roopa Prabhu To: netdev@vger.kernel.org Cc: davem@davemloft.net, stephen@networkplumber.org, nikolay@cumulusnetworks.com, tgraf@suug.ch, hannes@stressinduktion.org, jbenc@redhat.com, pshelar@ovn.org, dsa@cumulusnetworks.com, hadi@mojatatu.com Subject: [PATCH net-next v2 5/5] bridge: vlan dst_metadata hooks in ingress and egress paths Date: Tue, 31 Jan 2017 22:59:55 -0800 Message-Id: <1485932395-58422-6-git-send-email-roopa@cumulusnetworks.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1485932395-58422-1-git-send-email-roopa@cumulusnetworks.com> References: <1485932395-58422-1-git-send-email-roopa@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu - ingress hook: - if port is a tunnel port, use tunnel info in attached dst_metadata to map it to a local vlan - egress hook: - if port is a tunnel port, use tunnel info attached to vlan to set dst_metadata on the skb CC: Nikolay Aleksandrov Signed-off-by: Roopa Prabhu --- net/bridge/br_forward.c | 2 +- net/bridge/br_input.c | 8 +++++- net/bridge/br_private.h | 2 ++ net/bridge/br_private_tunnel.h | 11 ++++++++ net/bridge/br_vlan.c | 7 ++++++ net/bridge/br_vlan_tunnel.c | 54 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index a0f9d00..e5d4821 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -80,7 +80,7 @@ static void __br_forward(const struct net_bridge_port *to, int br_hook; vg = nbp_vlan_group_rcu(to); - skb = br_handle_vlan(to->br, vg, skb); + skb = br_handle_vlan(to->br, to, vg, skb); if (!skb) return; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 855b72f..fba38d8 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -21,6 +21,7 @@ #include #include #include "br_private.h" +#include "br_private_tunnel.h" /* Hook for brouter */ br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; @@ -57,7 +58,7 @@ static int br_pass_frame_up(struct sk_buff *skb) indev = skb->dev; skb->dev = brdev; - skb = br_handle_vlan(br, vg, skb); + skb = br_handle_vlan(br, NULL, vg, skb); if (!skb) return NET_RX_DROP; /* update the multicast stats if the packet is IGMP/MLD */ @@ -261,6 +262,11 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) return RX_HANDLER_CONSUMED; p = br_port_get_rcu(skb->dev); + if (p->flags & BR_VLAN_TUNNEL) { + if (br_handle_ingress_vlan_tunnel(skb, p, + nbp_vlan_group_rcu(p))) + goto drop; + } if (unlikely(is_link_local_ether_addr(dest))) { u16 fwd_mask = p->br->group_fwd_mask_required; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 61de90f..40177df 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -775,6 +775,7 @@ bool br_allowed_egress(struct net_bridge_vlan_group *vg, const struct sk_buff *skb); bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid); struct sk_buff *br_handle_vlan(struct net_bridge *br, + const struct net_bridge_port *port, struct net_bridge_vlan_group *vg, struct sk_buff *skb); int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags); @@ -874,6 +875,7 @@ static inline bool br_should_learn(struct net_bridge_port *p, } static inline struct sk_buff *br_handle_vlan(struct net_bridge *br, + const struct net_bridge_port *port, struct net_bridge_vlan_group *vg, struct sk_buff *skb) { diff --git a/net/bridge/br_private_tunnel.h b/net/bridge/br_private_tunnel.h index 1c8d0d5..4a447a3 100644 --- a/net/bridge/br_private_tunnel.h +++ b/net/bridge/br_private_tunnel.h @@ -40,6 +40,11 @@ int br_fill_vlan_tunnel_info(struct sk_buff *skb, void nbp_vlan_tunnel_info_flush(struct net_bridge_port *port); void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg, struct net_bridge_vlan *vlan); +int br_handle_ingress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_port *p, + struct net_bridge_vlan_group *vg); +int br_handle_egress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_vlan *vlan); #else static inline int vlan_tunnel_init(struct net_bridge_vlan_group *vg) { @@ -67,6 +72,12 @@ static inline void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg, { } +static inline int br_handle_ingress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_port *p, + struct net_bridge_vlan_group *vg) +{ + return 0; +} #endif #endif diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 64002e3..62e68c0 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -341,6 +341,7 @@ static void __vlan_flush(struct net_bridge_vlan_group *vg) } struct sk_buff *br_handle_vlan(struct net_bridge *br, + const struct net_bridge_port *p, struct net_bridge_vlan_group *vg, struct sk_buff *skb) { @@ -381,6 +382,12 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) skb->vlan_tci = 0; + + if (p && (p->flags & BR_VLAN_TUNNEL) && + br_handle_egress_vlan_tunnel(skb, v)) { + kfree_skb(skb); + return NULL; + } out: return skb; } diff --git a/net/bridge/br_vlan_tunnel.c b/net/bridge/br_vlan_tunnel.c index b3fd29d..b2b79a0 100644 --- a/net/bridge/br_vlan_tunnel.c +++ b/net/bridge/br_vlan_tunnel.c @@ -39,6 +39,13 @@ static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg, .automatic_shrinking = true, }; +static struct net_bridge_vlan *br_vlan_tunnel_lookup(struct rhashtable *tbl, + u64 tunnel_id) +{ + return rhashtable_lookup_fast(tbl, &tunnel_id, + br_vlan_tunnel_rht_params); +} + void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg, struct net_bridge_vlan *vlan) { @@ -147,3 +154,50 @@ void vlan_tunnel_deinit(struct net_bridge_vlan_group *vg) { rhashtable_destroy(&vg->tunnel_hash); } + +int br_handle_ingress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_port *p, + struct net_bridge_vlan_group *vg) +{ + struct ip_tunnel_info *tinfo = skb_tunnel_info(skb); + struct net_bridge_vlan *vlan; + + if (!vg || !tinfo) + return 0; + + /* if already tagged, ignore */ + if (skb_vlan_tagged(skb)) + return 0; + + /* lookup vid, given tunnel id */ + vlan = br_vlan_tunnel_lookup(&vg->tunnel_hash, tinfo->key.tun_id); + if (!vlan) + return 0; + + skb_dst_drop(skb); + + __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid); + + return 0; +} + +int br_handle_egress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_vlan *vlan) +{ + int err; + + if (!vlan || !vlan->tinfo.tunnel_id) + return 0; + + if (unlikely(!skb_vlan_tag_present(skb))) + return 0; + + skb_dst_drop(skb); + err = skb_vlan_pop(skb); + if (err) + return err; + + skb_dst_set(skb, dst_clone(&vlan->tinfo.tunnel_dst->dst)); + + return 0; +}