root/net/bridge/br_vlan_tunnel.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. br_vlan_tunid_cmp
  2. br_vlan_tunnel_lookup
  3. vlan_tunnel_info_del
  4. __vlan_tunnel_info_add
  5. nbp_vlan_tunnel_info_add
  6. nbp_vlan_tunnel_info_delete
  7. __vlan_tunnel_info_flush
  8. nbp_vlan_tunnel_info_flush
  9. vlan_tunnel_init
  10. vlan_tunnel_deinit
  11. br_handle_ingress_vlan_tunnel
  12. br_handle_egress_vlan_tunnel

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      Bridge per vlan tunnel port dst_metadata handling code
   4  *
   5  *      Authors:
   6  *      Roopa Prabhu            <roopa@cumulusnetworks.com>
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/netdevice.h>
  11 #include <linux/rtnetlink.h>
  12 #include <linux/slab.h>
  13 #include <net/switchdev.h>
  14 #include <net/dst_metadata.h>
  15 
  16 #include "br_private.h"
  17 #include "br_private_tunnel.h"
  18 
  19 static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg,
  20                                     const void *ptr)
  21 {
  22         const struct net_bridge_vlan *vle = ptr;
  23         __be64 tunid = *(__be64 *)arg->key;
  24 
  25         return vle->tinfo.tunnel_id != tunid;
  26 }
  27 
  28 static const struct rhashtable_params br_vlan_tunnel_rht_params = {
  29         .head_offset = offsetof(struct net_bridge_vlan, tnode),
  30         .key_offset = offsetof(struct net_bridge_vlan, tinfo.tunnel_id),
  31         .key_len = sizeof(__be64),
  32         .nelem_hint = 3,
  33         .obj_cmpfn = br_vlan_tunid_cmp,
  34         .automatic_shrinking = true,
  35 };
  36 
  37 static struct net_bridge_vlan *br_vlan_tunnel_lookup(struct rhashtable *tbl,
  38                                                      u64 tunnel_id)
  39 {
  40         return rhashtable_lookup_fast(tbl, &tunnel_id,
  41                                       br_vlan_tunnel_rht_params);
  42 }
  43 
  44 void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg,
  45                           struct net_bridge_vlan *vlan)
  46 {
  47         if (!vlan->tinfo.tunnel_dst)
  48                 return;
  49         rhashtable_remove_fast(&vg->tunnel_hash, &vlan->tnode,
  50                                br_vlan_tunnel_rht_params);
  51         vlan->tinfo.tunnel_id = 0;
  52         dst_release(&vlan->tinfo.tunnel_dst->dst);
  53         vlan->tinfo.tunnel_dst = NULL;
  54 }
  55 
  56 static int __vlan_tunnel_info_add(struct net_bridge_vlan_group *vg,
  57                                   struct net_bridge_vlan *vlan, u32 tun_id)
  58 {
  59         struct metadata_dst *metadata = NULL;
  60         __be64 key = key32_to_tunnel_id(cpu_to_be32(tun_id));
  61         int err;
  62 
  63         if (vlan->tinfo.tunnel_dst)
  64                 return -EEXIST;
  65 
  66         metadata = __ip_tun_set_dst(0, 0, 0, 0, 0, TUNNEL_KEY,
  67                                     key, 0);
  68         if (!metadata)
  69                 return -EINVAL;
  70 
  71         metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_BRIDGE;
  72         vlan->tinfo.tunnel_dst = metadata;
  73         vlan->tinfo.tunnel_id = key;
  74 
  75         err = rhashtable_lookup_insert_fast(&vg->tunnel_hash, &vlan->tnode,
  76                                             br_vlan_tunnel_rht_params);
  77         if (err)
  78                 goto out;
  79 
  80         return 0;
  81 out:
  82         dst_release(&vlan->tinfo.tunnel_dst->dst);
  83         vlan->tinfo.tunnel_dst = NULL;
  84         vlan->tinfo.tunnel_id = 0;
  85 
  86         return err;
  87 }
  88 
  89 /* Must be protected by RTNL.
  90  * Must be called with vid in range from 1 to 4094 inclusive.
  91  */
  92 int nbp_vlan_tunnel_info_add(struct net_bridge_port *port, u16 vid, u32 tun_id)
  93 {
  94         struct net_bridge_vlan_group *vg;
  95         struct net_bridge_vlan *vlan;
  96 
  97         ASSERT_RTNL();
  98 
  99         vg = nbp_vlan_group(port);
 100         vlan = br_vlan_find(vg, vid);
 101         if (!vlan)
 102                 return -EINVAL;
 103 
 104         return __vlan_tunnel_info_add(vg, vlan, tun_id);
 105 }
 106 
 107 /* Must be protected by RTNL.
 108  * Must be called with vid in range from 1 to 4094 inclusive.
 109  */
 110 int nbp_vlan_tunnel_info_delete(struct net_bridge_port *port, u16 vid)
 111 {
 112         struct net_bridge_vlan_group *vg;
 113         struct net_bridge_vlan *v;
 114 
 115         ASSERT_RTNL();
 116 
 117         vg = nbp_vlan_group(port);
 118         v = br_vlan_find(vg, vid);
 119         if (!v)
 120                 return -ENOENT;
 121 
 122         vlan_tunnel_info_del(vg, v);
 123 
 124         return 0;
 125 }
 126 
 127 static void __vlan_tunnel_info_flush(struct net_bridge_vlan_group *vg)
 128 {
 129         struct net_bridge_vlan *vlan, *tmp;
 130 
 131         list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist)
 132                 vlan_tunnel_info_del(vg, vlan);
 133 }
 134 
 135 void nbp_vlan_tunnel_info_flush(struct net_bridge_port *port)
 136 {
 137         struct net_bridge_vlan_group *vg;
 138 
 139         ASSERT_RTNL();
 140 
 141         vg = nbp_vlan_group(port);
 142         __vlan_tunnel_info_flush(vg);
 143 }
 144 
 145 int vlan_tunnel_init(struct net_bridge_vlan_group *vg)
 146 {
 147         return rhashtable_init(&vg->tunnel_hash, &br_vlan_tunnel_rht_params);
 148 }
 149 
 150 void vlan_tunnel_deinit(struct net_bridge_vlan_group *vg)
 151 {
 152         rhashtable_destroy(&vg->tunnel_hash);
 153 }
 154 
 155 int br_handle_ingress_vlan_tunnel(struct sk_buff *skb,
 156                                   struct net_bridge_port *p,
 157                                   struct net_bridge_vlan_group *vg)
 158 {
 159         struct ip_tunnel_info *tinfo = skb_tunnel_info(skb);
 160         struct net_bridge_vlan *vlan;
 161 
 162         if (!vg || !tinfo)
 163                 return 0;
 164 
 165         /* if already tagged, ignore */
 166         if (skb_vlan_tagged(skb))
 167                 return 0;
 168 
 169         /* lookup vid, given tunnel id */
 170         vlan = br_vlan_tunnel_lookup(&vg->tunnel_hash, tinfo->key.tun_id);
 171         if (!vlan)
 172                 return 0;
 173 
 174         skb_dst_drop(skb);
 175 
 176         __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid);
 177 
 178         return 0;
 179 }
 180 
 181 int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
 182                                  struct net_bridge_vlan *vlan)
 183 {
 184         int err;
 185 
 186         if (!vlan || !vlan->tinfo.tunnel_id)
 187                 return 0;
 188 
 189         if (unlikely(!skb_vlan_tag_present(skb)))
 190                 return 0;
 191 
 192         skb_dst_drop(skb);
 193         err = skb_vlan_pop(skb);
 194         if (err)
 195                 return err;
 196 
 197         skb_dst_set(skb, dst_clone(&vlan->tinfo.tunnel_dst->dst));
 198 
 199         return 0;
 200 }

/* [<][>][^][v][top][bottom][index][help] */