^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/if_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/pkt_sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/pkt_cls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/tc_act/tc_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/tc_act/tc_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static unsigned int vlan_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static struct tc_action_ops act_vlan_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct tcf_result *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct tcf_vlan *v = to_vlan(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct tcf_vlan_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u16 tci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) tcf_lastuse_update(&v->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) tcf_action_update_bstats(&v->common, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Ensure 'data' points at mac_header prior calling vlan manipulating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (skb_at_tc_ingress(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) skb_push_rcsum(skb, skb->mac_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) action = READ_ONCE(v->tcf_action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) p = rcu_dereference_bh(v->vlan_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) switch (p->tcfv_action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case TCA_VLAN_ACT_POP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) err = skb_vlan_pop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case TCA_VLAN_ACT_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) err = skb_vlan_push(skb, p->tcfv_push_proto, p->tcfv_push_vid |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) (p->tcfv_push_prio << VLAN_PRIO_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case TCA_VLAN_ACT_MODIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* No-op if no vlan tag (either hw-accel or in-payload) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!skb_vlan_tagged(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* extract existing tag (and guarantee no hw-accel tag) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (skb_vlan_tag_present(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) tci = skb_vlan_tag_get(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) __vlan_hwaccel_clear_tag(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* in-payload vlan tag, pop it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) err = __skb_vlan_pop(skb, &tci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* replace the vid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) tci = (tci & ~VLAN_VID_MASK) | p->tcfv_push_vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* replace prio bits, if tcfv_push_prio specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (p->tcfv_push_prio_exists) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) tci &= ~VLAN_PRIO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) tci |= p->tcfv_push_prio << VLAN_PRIO_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* put updated tci as hwaccel tag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __vlan_hwaccel_put_tag(skb, p->tcfv_push_proto, tci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case TCA_VLAN_ACT_POP_ETH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) err = skb_eth_pop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case TCA_VLAN_ACT_PUSH_ETH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (skb_at_tc_ingress(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) skb_pull_rcsum(skb, skb->mac_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) tcf_action_inc_drop_qstats(&v->common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) [TCA_VLAN_UNSPEC] = { .strict_start_type = TCA_VLAN_PUSH_ETH_DST },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) [TCA_VLAN_PARMS] = { .len = sizeof(struct tc_vlan) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) [TCA_VLAN_PUSH_VLAN_ID] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) [TCA_VLAN_PUSH_ETH_DST] = NLA_POLICY_ETH_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) [TCA_VLAN_PUSH_ETH_SRC] = NLA_POLICY_ETH_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int tcf_vlan_init(struct net *net, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct nlattr *est, struct tc_action **a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int ovr, int bind, bool rtnl_held,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct tcf_proto *tp, u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct tc_action_net *tn = net_generic(net, vlan_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct nlattr *tb[TCA_VLAN_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct tcf_chain *goto_ch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) bool push_prio_exists = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct tcf_vlan_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct tc_vlan *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct tcf_vlan *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u16 push_vid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) __be16 push_proto = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 push_prio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) bool exists = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int ret = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) err = nla_parse_nested_deprecated(tb, TCA_VLAN_MAX, nla, vlan_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!tb[TCA_VLAN_PARMS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) parm = nla_data(tb[TCA_VLAN_PARMS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) index = parm->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) err = tcf_idr_check_alloc(tn, &index, a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) exists = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (exists && bind)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) switch (parm->v_action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case TCA_VLAN_ACT_POP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case TCA_VLAN_ACT_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case TCA_VLAN_ACT_MODIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (push_vid >= VLAN_VID_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) push_proto = nla_get_be16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) switch (push_proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case htons(ETH_P_8021Q):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) case htons(ETH_P_8021AD):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) push_proto = htons(ETH_P_8021Q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) push_prio_exists = !!tb[TCA_VLAN_PUSH_VLAN_PRIORITY];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (push_prio_exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) push_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case TCA_VLAN_ACT_POP_ETH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case TCA_VLAN_ACT_PUSH_ETH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!tb[TCA_VLAN_PUSH_ETH_DST] || !tb[TCA_VLAN_PUSH_ETH_SRC]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) action = parm->v_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!exists) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ret = tcf_idr_create_from_flags(tn, index, est, a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) &act_vlan_ops, bind, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ret = ACT_P_CREATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) } else if (!ovr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto release_idr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) v = to_vlan(*a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) p = kzalloc(sizeof(*p), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto put_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) p->tcfv_action = action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) p->tcfv_push_vid = push_vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) p->tcfv_push_prio = push_prio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) p->tcfv_push_prio_exists = push_prio_exists || action == TCA_VLAN_ACT_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) p->tcfv_push_proto = push_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (action == TCA_VLAN_ACT_PUSH_ETH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) nla_memcpy(&p->tcfv_push_dst, tb[TCA_VLAN_PUSH_ETH_DST],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) nla_memcpy(&p->tcfv_push_src, tb[TCA_VLAN_PUSH_ETH_SRC],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) spin_lock_bh(&v->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) p = rcu_replace_pointer(v->vlan_p, p, lockdep_is_held(&v->tcf_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) spin_unlock_bh(&v->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (goto_ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) tcf_chain_put_by_act(goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) kfree_rcu(p, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) put_chain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (goto_ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) tcf_chain_put_by_act(goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) release_idr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static void tcf_vlan_cleanup(struct tc_action *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct tcf_vlan *v = to_vlan(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct tcf_vlan_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) p = rcu_dereference_protected(v->vlan_p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) kfree_rcu(p, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int bind, int ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned char *b = skb_tail_pointer(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct tcf_vlan *v = to_vlan(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct tcf_vlan_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct tc_vlan opt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .index = v->tcf_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .refcnt = refcount_read(&v->tcf_refcnt) - ref,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .bindcnt = atomic_read(&v->tcf_bindcnt) - bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct tcf_t t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) spin_lock_bh(&v->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) opt.action = v->tcf_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) p = rcu_dereference_protected(v->vlan_p, lockdep_is_held(&v->tcf_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) opt.v_action = p->tcfv_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if ((p->tcfv_action == TCA_VLAN_ACT_PUSH ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) p->tcfv_action == TCA_VLAN_ACT_MODIFY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) (nla_put_u16(skb, TCA_VLAN_PUSH_VLAN_ID, p->tcfv_push_vid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) nla_put_be16(skb, TCA_VLAN_PUSH_VLAN_PROTOCOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) p->tcfv_push_proto) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) (nla_put_u8(skb, TCA_VLAN_PUSH_VLAN_PRIORITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) p->tcfv_push_prio))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (p->tcfv_action == TCA_VLAN_ACT_PUSH_ETH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (nla_put(skb, TCA_VLAN_PUSH_ETH_DST, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) p->tcfv_push_dst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (nla_put(skb, TCA_VLAN_PUSH_ETH_SRC, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) p->tcfv_push_src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) tcf_tm_dump(&t, &v->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) spin_unlock_bh(&v->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) spin_unlock_bh(&v->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) nlmsg_trim(skb, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct netlink_callback *cb, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) const struct tc_action_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct tc_action_net *tn = net_generic(net, vlan_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return tcf_generic_walker(tn, skb, cb, type, ops, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static void tcf_vlan_stats_update(struct tc_action *a, u64 bytes, u64 packets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u64 drops, u64 lastuse, bool hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct tcf_vlan *v = to_vlan(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct tcf_t *tm = &v->tcf_tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) tcf_action_update_stats(a, bytes, packets, drops, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) tm->lastuse = max_t(u64, tm->lastuse, lastuse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct tc_action_net *tn = net_generic(net, vlan_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return tcf_idr_search(tn, a, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return nla_total_size(sizeof(struct tc_vlan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static struct tc_action_ops act_vlan_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .kind = "vlan",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .id = TCA_ID_VLAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .act = tcf_vlan_act,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .dump = tcf_vlan_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .init = tcf_vlan_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .cleanup = tcf_vlan_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .walk = tcf_vlan_walker,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .stats_update = tcf_vlan_stats_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .get_fill_size = tcf_vlan_get_fill_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .lookup = tcf_vlan_search,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .size = sizeof(struct tcf_vlan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static __net_init int vlan_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct tc_action_net *tn = net_generic(net, vlan_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return tc_action_net_init(net, tn, &act_vlan_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void __net_exit vlan_exit_net(struct list_head *net_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) tc_action_net_exit(net_list, vlan_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static struct pernet_operations vlan_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .init = vlan_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .exit_batch = vlan_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .id = &vlan_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .size = sizeof(struct tc_action_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int __init vlan_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return tcf_register_action(&act_vlan_ops, &vlan_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void __exit vlan_cleanup_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) tcf_unregister_action(&act_vlan_ops, &vlan_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) module_init(vlan_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) module_exit(vlan_cleanup_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) MODULE_AUTHOR("Jiri Pirko <jiri@resnulli.us>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) MODULE_DESCRIPTION("vlan manipulation actions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) MODULE_LICENSE("GPL v2");