0001
0002
0003
0004 #include <linux/if_arp.h>
0005 #include <linux/init.h>
0006 #include <linux/kernel.h>
0007 #include <linux/module.h>
0008 #include <linux/mpls.h>
0009 #include <linux/rtnetlink.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/tc_act/tc_mpls.h>
0012 #include <net/mpls.h>
0013 #include <net/netlink.h>
0014 #include <net/pkt_sched.h>
0015 #include <net/pkt_cls.h>
0016 #include <net/tc_act/tc_mpls.h>
0017
0018 static unsigned int mpls_net_id;
0019 static struct tc_action_ops act_mpls_ops;
0020
0021 #define ACT_MPLS_TTL_DEFAULT 255
0022
0023 static __be32 tcf_mpls_get_lse(struct mpls_shim_hdr *lse,
0024 struct tcf_mpls_params *p, bool set_bos)
0025 {
0026 u32 new_lse = 0;
0027
0028 if (lse)
0029 new_lse = be32_to_cpu(lse->label_stack_entry);
0030
0031 if (p->tcfm_label != ACT_MPLS_LABEL_NOT_SET) {
0032 new_lse &= ~MPLS_LS_LABEL_MASK;
0033 new_lse |= p->tcfm_label << MPLS_LS_LABEL_SHIFT;
0034 }
0035 if (p->tcfm_ttl) {
0036 new_lse &= ~MPLS_LS_TTL_MASK;
0037 new_lse |= p->tcfm_ttl << MPLS_LS_TTL_SHIFT;
0038 }
0039 if (p->tcfm_tc != ACT_MPLS_TC_NOT_SET) {
0040 new_lse &= ~MPLS_LS_TC_MASK;
0041 new_lse |= p->tcfm_tc << MPLS_LS_TC_SHIFT;
0042 }
0043 if (p->tcfm_bos != ACT_MPLS_BOS_NOT_SET) {
0044 new_lse &= ~MPLS_LS_S_MASK;
0045 new_lse |= p->tcfm_bos << MPLS_LS_S_SHIFT;
0046 } else if (set_bos) {
0047 new_lse |= 1 << MPLS_LS_S_SHIFT;
0048 }
0049
0050 return cpu_to_be32(new_lse);
0051 }
0052
0053 static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
0054 struct tcf_result *res)
0055 {
0056 struct tcf_mpls *m = to_mpls(a);
0057 struct tcf_mpls_params *p;
0058 __be32 new_lse;
0059 int ret, mac_len;
0060
0061 tcf_lastuse_update(&m->tcf_tm);
0062 bstats_update(this_cpu_ptr(m->common.cpu_bstats), skb);
0063
0064
0065
0066
0067 if (skb_at_tc_ingress(skb)) {
0068 skb_push_rcsum(skb, skb->mac_len);
0069 mac_len = skb->mac_len;
0070 } else {
0071 mac_len = skb_network_header(skb) - skb_mac_header(skb);
0072 }
0073
0074 ret = READ_ONCE(m->tcf_action);
0075
0076 p = rcu_dereference_bh(m->mpls_p);
0077
0078 switch (p->tcfm_action) {
0079 case TCA_MPLS_ACT_POP:
0080 if (skb_mpls_pop(skb, p->tcfm_proto, mac_len,
0081 skb->dev && skb->dev->type == ARPHRD_ETHER))
0082 goto drop;
0083 break;
0084 case TCA_MPLS_ACT_PUSH:
0085 new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb_protocol(skb, true)));
0086 if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len,
0087 skb->dev && skb->dev->type == ARPHRD_ETHER))
0088 goto drop;
0089 break;
0090 case TCA_MPLS_ACT_MAC_PUSH:
0091 if (skb_vlan_tag_present(skb)) {
0092 if (__vlan_insert_inner_tag(skb, skb->vlan_proto,
0093 skb_vlan_tag_get(skb),
0094 ETH_HLEN) < 0)
0095 goto drop;
0096
0097 skb->protocol = skb->vlan_proto;
0098 __vlan_hwaccel_clear_tag(skb);
0099 }
0100
0101 new_lse = tcf_mpls_get_lse(NULL, p, mac_len ||
0102 !eth_p_mpls(skb->protocol));
0103
0104 if (skb_mpls_push(skb, new_lse, p->tcfm_proto, 0, false))
0105 goto drop;
0106 break;
0107 case TCA_MPLS_ACT_MODIFY:
0108 if (!pskb_may_pull(skb,
0109 skb_network_offset(skb) + MPLS_HLEN))
0110 goto drop;
0111 new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false);
0112 if (skb_mpls_update_lse(skb, new_lse))
0113 goto drop;
0114 break;
0115 case TCA_MPLS_ACT_DEC_TTL:
0116 if (skb_mpls_dec_ttl(skb))
0117 goto drop;
0118 break;
0119 }
0120
0121 if (skb_at_tc_ingress(skb))
0122 skb_pull_rcsum(skb, skb->mac_len);
0123
0124 return ret;
0125
0126 drop:
0127 qstats_drop_inc(this_cpu_ptr(m->common.cpu_qstats));
0128 return TC_ACT_SHOT;
0129 }
0130
0131 static int valid_label(const struct nlattr *attr,
0132 struct netlink_ext_ack *extack)
0133 {
0134 const u32 *label = nla_data(attr);
0135
0136 if (*label & ~MPLS_LABEL_MASK || *label == MPLS_LABEL_IMPLNULL) {
0137 NL_SET_ERR_MSG_MOD(extack, "MPLS label out of range");
0138 return -EINVAL;
0139 }
0140
0141 return 0;
0142 }
0143
0144 static const struct nla_policy mpls_policy[TCA_MPLS_MAX + 1] = {
0145 [TCA_MPLS_PARMS] = NLA_POLICY_EXACT_LEN(sizeof(struct tc_mpls)),
0146 [TCA_MPLS_PROTO] = { .type = NLA_U16 },
0147 [TCA_MPLS_LABEL] = NLA_POLICY_VALIDATE_FN(NLA_U32, valid_label),
0148 [TCA_MPLS_TC] = NLA_POLICY_RANGE(NLA_U8, 0, 7),
0149 [TCA_MPLS_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
0150 [TCA_MPLS_BOS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
0151 };
0152
0153 static int tcf_mpls_init(struct net *net, struct nlattr *nla,
0154 struct nlattr *est, struct tc_action **a,
0155 struct tcf_proto *tp, u32 flags,
0156 struct netlink_ext_ack *extack)
0157 {
0158 struct tc_action_net *tn = net_generic(net, mpls_net_id);
0159 bool bind = flags & TCA_ACT_FLAGS_BIND;
0160 struct nlattr *tb[TCA_MPLS_MAX + 1];
0161 struct tcf_chain *goto_ch = NULL;
0162 struct tcf_mpls_params *p;
0163 struct tc_mpls *parm;
0164 bool exists = false;
0165 struct tcf_mpls *m;
0166 int ret = 0, err;
0167 u8 mpls_ttl = 0;
0168 u32 index;
0169
0170 if (!nla) {
0171 NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
0172 return -EINVAL;
0173 }
0174
0175 err = nla_parse_nested(tb, TCA_MPLS_MAX, nla, mpls_policy, extack);
0176 if (err < 0)
0177 return err;
0178
0179 if (!tb[TCA_MPLS_PARMS]) {
0180 NL_SET_ERR_MSG_MOD(extack, "No MPLS params");
0181 return -EINVAL;
0182 }
0183 parm = nla_data(tb[TCA_MPLS_PARMS]);
0184 index = parm->index;
0185
0186
0187 switch (parm->m_action) {
0188 case TCA_MPLS_ACT_POP:
0189 if (!tb[TCA_MPLS_PROTO]) {
0190 NL_SET_ERR_MSG_MOD(extack, "Protocol must be set for MPLS pop");
0191 return -EINVAL;
0192 }
0193 if (!eth_proto_is_802_3(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
0194 NL_SET_ERR_MSG_MOD(extack, "Invalid protocol type for MPLS pop");
0195 return -EINVAL;
0196 }
0197 if (tb[TCA_MPLS_LABEL] || tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] ||
0198 tb[TCA_MPLS_BOS]) {
0199 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC or BOS cannot be used with MPLS pop");
0200 return -EINVAL;
0201 }
0202 break;
0203 case TCA_MPLS_ACT_DEC_TTL:
0204 if (tb[TCA_MPLS_PROTO] || tb[TCA_MPLS_LABEL] ||
0205 tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || tb[TCA_MPLS_BOS]) {
0206 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC, BOS or protocol cannot be used with MPLS dec_ttl");
0207 return -EINVAL;
0208 }
0209 break;
0210 case TCA_MPLS_ACT_PUSH:
0211 case TCA_MPLS_ACT_MAC_PUSH:
0212 if (!tb[TCA_MPLS_LABEL]) {
0213 NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push");
0214 return -EINVAL;
0215 }
0216 if (tb[TCA_MPLS_PROTO] &&
0217 !eth_p_mpls(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
0218 NL_SET_ERR_MSG_MOD(extack, "Protocol must be an MPLS type for MPLS push");
0219 return -EPROTONOSUPPORT;
0220 }
0221
0222 if (!tb[TCA_MPLS_TTL]) {
0223 #if IS_ENABLED(CONFIG_MPLS)
0224 mpls_ttl = net->mpls.default_ttl ?
0225 net->mpls.default_ttl : ACT_MPLS_TTL_DEFAULT;
0226 #else
0227 mpls_ttl = ACT_MPLS_TTL_DEFAULT;
0228 #endif
0229 }
0230 break;
0231 case TCA_MPLS_ACT_MODIFY:
0232 if (tb[TCA_MPLS_PROTO]) {
0233 NL_SET_ERR_MSG_MOD(extack, "Protocol cannot be used with MPLS modify");
0234 return -EINVAL;
0235 }
0236 break;
0237 default:
0238 NL_SET_ERR_MSG_MOD(extack, "Unknown MPLS action");
0239 return -EINVAL;
0240 }
0241
0242 err = tcf_idr_check_alloc(tn, &index, a, bind);
0243 if (err < 0)
0244 return err;
0245 exists = err;
0246 if (exists && bind)
0247 return 0;
0248
0249 if (!exists) {
0250 ret = tcf_idr_create(tn, index, est, a,
0251 &act_mpls_ops, bind, true, flags);
0252 if (ret) {
0253 tcf_idr_cleanup(tn, index);
0254 return ret;
0255 }
0256
0257 ret = ACT_P_CREATED;
0258 } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
0259 tcf_idr_release(*a, bind);
0260 return -EEXIST;
0261 }
0262
0263 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
0264 if (err < 0)
0265 goto release_idr;
0266
0267 m = to_mpls(*a);
0268
0269 p = kzalloc(sizeof(*p), GFP_KERNEL);
0270 if (!p) {
0271 err = -ENOMEM;
0272 goto put_chain;
0273 }
0274
0275 p->tcfm_action = parm->m_action;
0276 p->tcfm_label = tb[TCA_MPLS_LABEL] ? nla_get_u32(tb[TCA_MPLS_LABEL]) :
0277 ACT_MPLS_LABEL_NOT_SET;
0278 p->tcfm_tc = tb[TCA_MPLS_TC] ? nla_get_u8(tb[TCA_MPLS_TC]) :
0279 ACT_MPLS_TC_NOT_SET;
0280 p->tcfm_ttl = tb[TCA_MPLS_TTL] ? nla_get_u8(tb[TCA_MPLS_TTL]) :
0281 mpls_ttl;
0282 p->tcfm_bos = tb[TCA_MPLS_BOS] ? nla_get_u8(tb[TCA_MPLS_BOS]) :
0283 ACT_MPLS_BOS_NOT_SET;
0284 p->tcfm_proto = tb[TCA_MPLS_PROTO] ? nla_get_be16(tb[TCA_MPLS_PROTO]) :
0285 htons(ETH_P_MPLS_UC);
0286
0287 spin_lock_bh(&m->tcf_lock);
0288 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
0289 p = rcu_replace_pointer(m->mpls_p, p, lockdep_is_held(&m->tcf_lock));
0290 spin_unlock_bh(&m->tcf_lock);
0291
0292 if (goto_ch)
0293 tcf_chain_put_by_act(goto_ch);
0294 if (p)
0295 kfree_rcu(p, rcu);
0296
0297 return ret;
0298 put_chain:
0299 if (goto_ch)
0300 tcf_chain_put_by_act(goto_ch);
0301 release_idr:
0302 tcf_idr_release(*a, bind);
0303 return err;
0304 }
0305
0306 static void tcf_mpls_cleanup(struct tc_action *a)
0307 {
0308 struct tcf_mpls *m = to_mpls(a);
0309 struct tcf_mpls_params *p;
0310
0311 p = rcu_dereference_protected(m->mpls_p, 1);
0312 if (p)
0313 kfree_rcu(p, rcu);
0314 }
0315
0316 static int tcf_mpls_dump(struct sk_buff *skb, struct tc_action *a,
0317 int bind, int ref)
0318 {
0319 unsigned char *b = skb_tail_pointer(skb);
0320 struct tcf_mpls *m = to_mpls(a);
0321 struct tcf_mpls_params *p;
0322 struct tc_mpls opt = {
0323 .index = m->tcf_index,
0324 .refcnt = refcount_read(&m->tcf_refcnt) - ref,
0325 .bindcnt = atomic_read(&m->tcf_bindcnt) - bind,
0326 };
0327 struct tcf_t t;
0328
0329 spin_lock_bh(&m->tcf_lock);
0330 opt.action = m->tcf_action;
0331 p = rcu_dereference_protected(m->mpls_p, lockdep_is_held(&m->tcf_lock));
0332 opt.m_action = p->tcfm_action;
0333
0334 if (nla_put(skb, TCA_MPLS_PARMS, sizeof(opt), &opt))
0335 goto nla_put_failure;
0336
0337 if (p->tcfm_label != ACT_MPLS_LABEL_NOT_SET &&
0338 nla_put_u32(skb, TCA_MPLS_LABEL, p->tcfm_label))
0339 goto nla_put_failure;
0340
0341 if (p->tcfm_tc != ACT_MPLS_TC_NOT_SET &&
0342 nla_put_u8(skb, TCA_MPLS_TC, p->tcfm_tc))
0343 goto nla_put_failure;
0344
0345 if (p->tcfm_ttl && nla_put_u8(skb, TCA_MPLS_TTL, p->tcfm_ttl))
0346 goto nla_put_failure;
0347
0348 if (p->tcfm_bos != ACT_MPLS_BOS_NOT_SET &&
0349 nla_put_u8(skb, TCA_MPLS_BOS, p->tcfm_bos))
0350 goto nla_put_failure;
0351
0352 if (nla_put_be16(skb, TCA_MPLS_PROTO, p->tcfm_proto))
0353 goto nla_put_failure;
0354
0355 tcf_tm_dump(&t, &m->tcf_tm);
0356
0357 if (nla_put_64bit(skb, TCA_MPLS_TM, sizeof(t), &t, TCA_MPLS_PAD))
0358 goto nla_put_failure;
0359
0360 spin_unlock_bh(&m->tcf_lock);
0361
0362 return skb->len;
0363
0364 nla_put_failure:
0365 spin_unlock_bh(&m->tcf_lock);
0366 nlmsg_trim(skb, b);
0367 return -EMSGSIZE;
0368 }
0369
0370 static int tcf_mpls_walker(struct net *net, struct sk_buff *skb,
0371 struct netlink_callback *cb, int type,
0372 const struct tc_action_ops *ops,
0373 struct netlink_ext_ack *extack)
0374 {
0375 struct tc_action_net *tn = net_generic(net, mpls_net_id);
0376
0377 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
0378 }
0379
0380 static int tcf_mpls_search(struct net *net, struct tc_action **a, u32 index)
0381 {
0382 struct tc_action_net *tn = net_generic(net, mpls_net_id);
0383
0384 return tcf_idr_search(tn, a, index);
0385 }
0386
0387 static int tcf_mpls_offload_act_setup(struct tc_action *act, void *entry_data,
0388 u32 *index_inc, bool bind,
0389 struct netlink_ext_ack *extack)
0390 {
0391 if (bind) {
0392 struct flow_action_entry *entry = entry_data;
0393
0394 switch (tcf_mpls_action(act)) {
0395 case TCA_MPLS_ACT_PUSH:
0396 entry->id = FLOW_ACTION_MPLS_PUSH;
0397 entry->mpls_push.proto = tcf_mpls_proto(act);
0398 entry->mpls_push.label = tcf_mpls_label(act);
0399 entry->mpls_push.tc = tcf_mpls_tc(act);
0400 entry->mpls_push.bos = tcf_mpls_bos(act);
0401 entry->mpls_push.ttl = tcf_mpls_ttl(act);
0402 break;
0403 case TCA_MPLS_ACT_POP:
0404 entry->id = FLOW_ACTION_MPLS_POP;
0405 entry->mpls_pop.proto = tcf_mpls_proto(act);
0406 break;
0407 case TCA_MPLS_ACT_MODIFY:
0408 entry->id = FLOW_ACTION_MPLS_MANGLE;
0409 entry->mpls_mangle.label = tcf_mpls_label(act);
0410 entry->mpls_mangle.tc = tcf_mpls_tc(act);
0411 entry->mpls_mangle.bos = tcf_mpls_bos(act);
0412 entry->mpls_mangle.ttl = tcf_mpls_ttl(act);
0413 break;
0414 case TCA_MPLS_ACT_DEC_TTL:
0415 NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"dec_ttl\" option is used");
0416 return -EOPNOTSUPP;
0417 case TCA_MPLS_ACT_MAC_PUSH:
0418 NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"mac_push\" option is used");
0419 return -EOPNOTSUPP;
0420 default:
0421 NL_SET_ERR_MSG_MOD(extack, "Unsupported MPLS mode offload");
0422 return -EOPNOTSUPP;
0423 }
0424 *index_inc = 1;
0425 } else {
0426 struct flow_offload_action *fl_action = entry_data;
0427
0428 switch (tcf_mpls_action(act)) {
0429 case TCA_MPLS_ACT_PUSH:
0430 fl_action->id = FLOW_ACTION_MPLS_PUSH;
0431 break;
0432 case TCA_MPLS_ACT_POP:
0433 fl_action->id = FLOW_ACTION_MPLS_POP;
0434 break;
0435 case TCA_MPLS_ACT_MODIFY:
0436 fl_action->id = FLOW_ACTION_MPLS_MANGLE;
0437 break;
0438 default:
0439 return -EOPNOTSUPP;
0440 }
0441 }
0442
0443 return 0;
0444 }
0445
0446 static struct tc_action_ops act_mpls_ops = {
0447 .kind = "mpls",
0448 .id = TCA_ID_MPLS,
0449 .owner = THIS_MODULE,
0450 .act = tcf_mpls_act,
0451 .dump = tcf_mpls_dump,
0452 .init = tcf_mpls_init,
0453 .cleanup = tcf_mpls_cleanup,
0454 .walk = tcf_mpls_walker,
0455 .lookup = tcf_mpls_search,
0456 .offload_act_setup = tcf_mpls_offload_act_setup,
0457 .size = sizeof(struct tcf_mpls),
0458 };
0459
0460 static __net_init int mpls_init_net(struct net *net)
0461 {
0462 struct tc_action_net *tn = net_generic(net, mpls_net_id);
0463
0464 return tc_action_net_init(net, tn, &act_mpls_ops);
0465 }
0466
0467 static void __net_exit mpls_exit_net(struct list_head *net_list)
0468 {
0469 tc_action_net_exit(net_list, mpls_net_id);
0470 }
0471
0472 static struct pernet_operations mpls_net_ops = {
0473 .init = mpls_init_net,
0474 .exit_batch = mpls_exit_net,
0475 .id = &mpls_net_id,
0476 .size = sizeof(struct tc_action_net),
0477 };
0478
0479 static int __init mpls_init_module(void)
0480 {
0481 return tcf_register_action(&act_mpls_ops, &mpls_net_ops);
0482 }
0483
0484 static void __exit mpls_cleanup_module(void)
0485 {
0486 tcf_unregister_action(&act_mpls_ops, &mpls_net_ops);
0487 }
0488
0489 module_init(mpls_init_module);
0490 module_exit(mpls_cleanup_module);
0491
0492 MODULE_SOFTDEP("post: mpls_gso");
0493 MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
0494 MODULE_LICENSE("GPL");
0495 MODULE_DESCRIPTION("MPLS manipulation actions");