1 /* 2 * lwtunnel Infrastructure for light weight tunnels like mpls 3 * 4 * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 * 11 */ 12 13 #include <linux/capability.h> 14 #include <linux/module.h> 15 #include <linux/types.h> 16 #include <linux/kernel.h> 17 #include <linux/slab.h> 18 #include <linux/uaccess.h> 19 #include <linux/skbuff.h> 20 #include <linux/netdevice.h> 21 #include <linux/lwtunnel.h> 22 #include <linux/in.h> 23 #include <linux/init.h> 24 #include <linux/err.h> 25 26 #include <net/lwtunnel.h> 27 #include <net/rtnetlink.h> 28 #include <net/ip6_fib.h> 29 30 #ifdef CONFIG_MODULES 31 32 static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type) 33 { 34 /* Only lwt encaps implemented without using an interface for 35 * the encap need to return a string here. 36 */ 37 switch (encap_type) { 38 case LWTUNNEL_ENCAP_MPLS: 39 return "MPLS"; 40 case LWTUNNEL_ENCAP_ILA: 41 return "ILA"; 42 case LWTUNNEL_ENCAP_SEG6: 43 return "SEG6"; 44 case LWTUNNEL_ENCAP_BPF: 45 return "BPF"; 46 case LWTUNNEL_ENCAP_IP6: 47 case LWTUNNEL_ENCAP_IP: 48 case LWTUNNEL_ENCAP_NONE: 49 case __LWTUNNEL_ENCAP_MAX: 50 /* should not have got here */ 51 WARN_ON(1); 52 break; 53 } 54 return NULL; 55 } 56 57 #endif /* CONFIG_MODULES */ 58 59 struct lwtunnel_state *lwtunnel_state_alloc(int encap_len) 60 { 61 struct lwtunnel_state *lws; 62 63 lws = kzalloc(sizeof(*lws) + encap_len, GFP_ATOMIC); 64 65 return lws; 66 } 67 EXPORT_SYMBOL(lwtunnel_state_alloc); 68 69 static const struct lwtunnel_encap_ops __rcu * 70 lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly; 71 72 int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops, 73 unsigned int num) 74 { 75 if (num > LWTUNNEL_ENCAP_MAX) 76 return -ERANGE; 77 78 return !cmpxchg((const struct lwtunnel_encap_ops **) 79 &lwtun_encaps[num], 80 NULL, ops) ? 0 : -1; 81 } 82 EXPORT_SYMBOL(lwtunnel_encap_add_ops); 83 84 int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops, 85 unsigned int encap_type) 86 { 87 int ret; 88 89 if (encap_type == LWTUNNEL_ENCAP_NONE || 90 encap_type > LWTUNNEL_ENCAP_MAX) 91 return -ERANGE; 92 93 ret = (cmpxchg((const struct lwtunnel_encap_ops **) 94 &lwtun_encaps[encap_type], 95 ops, NULL) == ops) ? 0 : -1; 96 97 synchronize_net(); 98 99 return ret; 100 } 101 EXPORT_SYMBOL(lwtunnel_encap_del_ops); 102 103 int lwtunnel_build_state(struct net_device *dev, u16 encap_type, 104 struct nlattr *encap, unsigned int family, 105 const void *cfg, struct lwtunnel_state **lws) 106 { 107 const struct lwtunnel_encap_ops *ops; 108 int ret = -EINVAL; 109 110 if (encap_type == LWTUNNEL_ENCAP_NONE || 111 encap_type > LWTUNNEL_ENCAP_MAX) 112 return ret; 113 114 ret = -EOPNOTSUPP; 115 rcu_read_lock(); 116 ops = rcu_dereference(lwtun_encaps[encap_type]); 117 #ifdef CONFIG_MODULES 118 if (!ops) { 119 const char *encap_type_str = lwtunnel_encap_str(encap_type); 120 121 if (encap_type_str) { 122 rcu_read_unlock(); 123 request_module("rtnl-lwt-%s", encap_type_str); 124 rcu_read_lock(); 125 ops = rcu_dereference(lwtun_encaps[encap_type]); 126 } 127 } 128 #endif 129 if (likely(ops && ops->build_state)) 130 ret = ops->build_state(dev, encap, family, cfg, lws); 131 rcu_read_unlock(); 132 133 return ret; 134 } 135 EXPORT_SYMBOL(lwtunnel_build_state); 136 137 void lwtstate_free(struct lwtunnel_state *lws) 138 { 139 const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type]; 140 141 if (ops->destroy_state) { 142 ops->destroy_state(lws); 143 kfree_rcu(lws, rcu); 144 } else { 145 kfree(lws); 146 } 147 } 148 EXPORT_SYMBOL(lwtstate_free); 149 150 int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate) 151 { 152 const struct lwtunnel_encap_ops *ops; 153 struct nlattr *nest; 154 int ret = -EINVAL; 155 156 if (!lwtstate) 157 return 0; 158 159 if (lwtstate->type == LWTUNNEL_ENCAP_NONE || 160 lwtstate->type > LWTUNNEL_ENCAP_MAX) 161 return 0; 162 163 ret = -EOPNOTSUPP; 164 nest = nla_nest_start(skb, RTA_ENCAP); 165 rcu_read_lock(); 166 ops = rcu_dereference(lwtun_encaps[lwtstate->type]); 167 if (likely(ops && ops->fill_encap)) 168 ret = ops->fill_encap(skb, lwtstate); 169 rcu_read_unlock(); 170 171 if (ret) 172 goto nla_put_failure; 173 nla_nest_end(skb, nest); 174 ret = nla_put_u16(skb, RTA_ENCAP_TYPE, lwtstate->type); 175 if (ret) 176 goto nla_put_failure; 177 178 return 0; 179 180 nla_put_failure: 181 nla_nest_cancel(skb, nest); 182 183 return (ret == -EOPNOTSUPP ? 0 : ret); 184 } 185 EXPORT_SYMBOL(lwtunnel_fill_encap); 186 187 int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate) 188 { 189 const struct lwtunnel_encap_ops *ops; 190 int ret = 0; 191 192 if (!lwtstate) 193 return 0; 194 195 if (lwtstate->type == LWTUNNEL_ENCAP_NONE || 196 lwtstate->type > LWTUNNEL_ENCAP_MAX) 197 return 0; 198 199 rcu_read_lock(); 200 ops = rcu_dereference(lwtun_encaps[lwtstate->type]); 201 if (likely(ops && ops->get_encap_size)) 202 ret = nla_total_size(ops->get_encap_size(lwtstate)); 203 rcu_read_unlock(); 204 205 return ret; 206 } 207 EXPORT_SYMBOL(lwtunnel_get_encap_size); 208 209 int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b) 210 { 211 const struct lwtunnel_encap_ops *ops; 212 int ret = 0; 213 214 if (!a && !b) 215 return 0; 216 217 if (!a || !b) 218 return 1; 219 220 if (a->type != b->type) 221 return 1; 222 223 if (a->type == LWTUNNEL_ENCAP_NONE || 224 a->type > LWTUNNEL_ENCAP_MAX) 225 return 0; 226 227 rcu_read_lock(); 228 ops = rcu_dereference(lwtun_encaps[a->type]); 229 if (likely(ops && ops->cmp_encap)) 230 ret = ops->cmp_encap(a, b); 231 rcu_read_unlock(); 232 233 return ret; 234 } 235 EXPORT_SYMBOL(lwtunnel_cmp_encap); 236 237 int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb) 238 { 239 struct dst_entry *dst = skb_dst(skb); 240 const struct lwtunnel_encap_ops *ops; 241 struct lwtunnel_state *lwtstate; 242 int ret = -EINVAL; 243 244 if (!dst) 245 goto drop; 246 lwtstate = dst->lwtstate; 247 248 if (lwtstate->type == LWTUNNEL_ENCAP_NONE || 249 lwtstate->type > LWTUNNEL_ENCAP_MAX) 250 return 0; 251 252 ret = -EOPNOTSUPP; 253 rcu_read_lock(); 254 ops = rcu_dereference(lwtun_encaps[lwtstate->type]); 255 if (likely(ops && ops->output)) 256 ret = ops->output(net, sk, skb); 257 rcu_read_unlock(); 258 259 if (ret == -EOPNOTSUPP) 260 goto drop; 261 262 return ret; 263 264 drop: 265 kfree_skb(skb); 266 267 return ret; 268 } 269 EXPORT_SYMBOL(lwtunnel_output); 270 271 int lwtunnel_xmit(struct sk_buff *skb) 272 { 273 struct dst_entry *dst = skb_dst(skb); 274 const struct lwtunnel_encap_ops *ops; 275 struct lwtunnel_state *lwtstate; 276 int ret = -EINVAL; 277 278 if (!dst) 279 goto drop; 280 281 lwtstate = dst->lwtstate; 282 283 if (lwtstate->type == LWTUNNEL_ENCAP_NONE || 284 lwtstate->type > LWTUNNEL_ENCAP_MAX) 285 return 0; 286 287 ret = -EOPNOTSUPP; 288 rcu_read_lock(); 289 ops = rcu_dereference(lwtun_encaps[lwtstate->type]); 290 if (likely(ops && ops->xmit)) 291 ret = ops->xmit(skb); 292 rcu_read_unlock(); 293 294 if (ret == -EOPNOTSUPP) 295 goto drop; 296 297 return ret; 298 299 drop: 300 kfree_skb(skb); 301 302 return ret; 303 } 304 EXPORT_SYMBOL(lwtunnel_xmit); 305 306 int lwtunnel_input(struct sk_buff *skb) 307 { 308 struct dst_entry *dst = skb_dst(skb); 309 const struct lwtunnel_encap_ops *ops; 310 struct lwtunnel_state *lwtstate; 311 int ret = -EINVAL; 312 313 if (!dst) 314 goto drop; 315 lwtstate = dst->lwtstate; 316 317 if (lwtstate->type == LWTUNNEL_ENCAP_NONE || 318 lwtstate->type > LWTUNNEL_ENCAP_MAX) 319 return 0; 320 321 ret = -EOPNOTSUPP; 322 rcu_read_lock(); 323 ops = rcu_dereference(lwtun_encaps[lwtstate->type]); 324 if (likely(ops && ops->input)) 325 ret = ops->input(skb); 326 rcu_read_unlock(); 327 328 if (ret == -EOPNOTSUPP) 329 goto drop; 330 331 return ret; 332 333 drop: 334 kfree_skb(skb); 335 336 return ret; 337 } 338 EXPORT_SYMBOL(lwtunnel_input); 339