Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  * net/sched/ife.c	Inter-FE action based on ForCES WG InterFE LFB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *		Refer to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *		draft-ietf-forces-interfelfb-03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *		and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *		netdev01 paper:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *		"Distributing Linux Traffic Control Classifier-Action
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *		Subsystem"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *		Authors: Jamal Hadi Salim and Damascene M. Joachimpillai
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * copyright Jamal Hadi Salim (2015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <net/pkt_sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <net/pkt_cls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <uapi/linux/tc_act/tc_ife.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <net/tc_act/tc_ife.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <net/ife.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static unsigned int ife_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int max_metacnt = IFE_META_MAX + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static struct tc_action_ops act_ife_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	[TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	[TCA_IFE_DMAC] = { .len = ETH_ALEN},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	[TCA_IFE_SMAC] = { .len = ETH_ALEN},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	[TCA_IFE_TYPE] = { .type = NLA_U16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) int ife_encode_meta_u16(u16 metaval, void *skbdata, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	u16 edata = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	if (mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		edata = *(u16 *)mi->metaval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	else if (metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		edata = metaval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	if (!edata) /* will not encode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	edata = htons(edata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	return ife_tlv_meta_encode(skbdata, mi->metaid, 2, &edata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) EXPORT_SYMBOL_GPL(ife_encode_meta_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) int ife_get_meta_u32(struct sk_buff *skb, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		return nla_put_u32(skb, mi->metaid, *(u32 *)mi->metaval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		return nla_put(skb, mi->metaid, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) EXPORT_SYMBOL_GPL(ife_get_meta_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) int ife_check_meta_u32(u32 metaval, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (metaval || mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return 8; /* T+L+V == 2+2+4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) EXPORT_SYMBOL_GPL(ife_check_meta_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) int ife_check_meta_u16(u16 metaval, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (metaval || mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		return 8; /* T+L+(V) == 2+2+(2+2bytepad) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) EXPORT_SYMBOL_GPL(ife_check_meta_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) int ife_encode_meta_u32(u32 metaval, void *skbdata, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	u32 edata = metaval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		edata = *(u32 *)mi->metaval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	else if (metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		edata = metaval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	if (!edata) /* will not encode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	edata = htonl(edata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return ife_tlv_meta_encode(skbdata, mi->metaid, 4, &edata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) EXPORT_SYMBOL_GPL(ife_encode_meta_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int ife_get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		return nla_put_u16(skb, mi->metaid, *(u16 *)mi->metaval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		return nla_put(skb, mi->metaid, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) EXPORT_SYMBOL_GPL(ife_get_meta_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	mi->metaval = kmemdup(metaval, sizeof(u32), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (!mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) EXPORT_SYMBOL_GPL(ife_alloc_meta_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	mi->metaval = kmemdup(metaval, sizeof(u16), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (!mi->metaval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) EXPORT_SYMBOL_GPL(ife_alloc_meta_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) void ife_release_meta_gen(struct tcf_meta_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	kfree(mi->metaval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) EXPORT_SYMBOL_GPL(ife_release_meta_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int ife_validate_meta_u32(void *val, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (len == sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) EXPORT_SYMBOL_GPL(ife_validate_meta_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int ife_validate_meta_u16(void *val, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	/* length will not include padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (len == sizeof(u16))
^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) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) EXPORT_SYMBOL_GPL(ife_validate_meta_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static LIST_HEAD(ifeoplist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static DEFINE_RWLOCK(ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static struct tcf_meta_ops *find_ife_oplist(u16 metaid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	struct tcf_meta_ops *o;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	read_lock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	list_for_each_entry(o, &ifeoplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		if (o->metaid == metaid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			if (!try_module_get(o->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				o = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			read_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			return o;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	read_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int register_ife_op(struct tcf_meta_ops *mops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	struct tcf_meta_ops *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if (!mops->metaid || !mops->metatype || !mops->name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	    !mops->check_presence || !mops->encode || !mops->decode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	    !mops->get || !mops->alloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	write_lock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	list_for_each_entry(m, &ifeoplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		if (m->metaid == mops->metaid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		    (strcmp(mops->name, m->name) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			write_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (!mops->release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		mops->release = ife_release_meta_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	list_add_tail(&mops->list, &ifeoplist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	write_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) EXPORT_SYMBOL_GPL(unregister_ife_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int unregister_ife_op(struct tcf_meta_ops *mops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	struct tcf_meta_ops *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	int err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	write_lock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	list_for_each_entry(m, &ifeoplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		if (m->metaid == mops->metaid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			list_del(&mops->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	write_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) EXPORT_SYMBOL_GPL(register_ife_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int ife_validate_metatype(struct tcf_meta_ops *ops, void *val, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	/* XXX: unfortunately cant use nla_policy at this point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	* because a length of 0 is valid in the case of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	* "allow". "use" semantics do enforce for proper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	* length and i couldve use nla_policy but it makes it hard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	* to use it just for that..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	if (ops->validate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		return ops->validate(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (ops->metatype == NLA_U32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		ret = ife_validate_meta_u32(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	else if (ops->metatype == NLA_U16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		ret = ife_validate_meta_u16(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #ifdef CONFIG_MODULES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static const char *ife_meta_id2name(u32 metaid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	switch (metaid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	case IFE_META_SKBMARK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return "skbmark";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	case IFE_META_PRIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		return "skbprio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	case IFE_META_TCINDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		return "tcindex";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* called when adding new meta information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int load_metaops_and_vet(u32 metaid, void *val, int len, bool rtnl_held)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	struct tcf_meta_ops *ops = find_ife_oplist(metaid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (!ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #ifdef CONFIG_MODULES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		if (rtnl_held)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		request_module("ife-meta-%s", ife_meta_id2name(metaid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		if (rtnl_held)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		ops = find_ife_oplist(metaid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			ret = ife_validate_metatype(ops, val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* called when adding new meta information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int __add_metainfo(const struct tcf_meta_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 			  struct tcf_ife_info *ife, u32 metaid, void *metaval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			  int len, bool atomic, bool exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	struct tcf_meta_info *mi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	if (!mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	mi->metaid = metaid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	mi->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			kfree(mi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		spin_lock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	list_add_tail(&mi->metalist, &ife->metalist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		spin_unlock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int add_metainfo_and_get_ops(const struct tcf_meta_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 				    struct tcf_ife_info *ife, u32 metaid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 				    bool exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (!try_module_get(ops->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	ret = __add_metainfo(ops, ife, metaid, NULL, 0, true, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			int len, bool exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	const struct tcf_meta_ops *ops = find_ife_oplist(metaid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	if (!ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	ret = __add_metainfo(ops, ife, metaid, metaval, len, false, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		/*put back what find_ife_oplist took */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int use_all_metadata(struct tcf_ife_info *ife, bool exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	struct tcf_meta_ops *o;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	int installed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	read_lock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	list_for_each_entry(o, &ifeoplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		rc = add_metainfo_and_get_ops(o, ife, o->metaid, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			installed += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	read_unlock(&ife_mod_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	if (installed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int dump_metalist(struct sk_buff *skb, struct tcf_ife_info *ife)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	struct tcf_meta_info *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	unsigned char *b = skb_tail_pointer(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	int total_encoded = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	/*can only happen on decode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	if (list_empty(&ife->metalist))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	nest = nla_nest_start_noflag(skb, TCA_IFE_METALST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		goto out_nlmsg_trim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	list_for_each_entry(e, &ife->metalist, metalist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		if (!e->ops->get(skb, e))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			total_encoded += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	if (!total_encoded)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		goto out_nlmsg_trim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) out_nlmsg_trim:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	nlmsg_trim(skb, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* under ife->tcf_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void _tcf_ife_cleanup(struct tc_action *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	struct tcf_meta_info *e, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	list_for_each_entry_safe(e, n, &ife->metalist, metalist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		list_del(&e->metalist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		if (e->metaval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			if (e->ops->release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				e->ops->release(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 				kfree(e->metaval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		module_put(e->ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		kfree(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static void tcf_ife_cleanup(struct tc_action *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	struct tcf_ife_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	spin_lock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	_tcf_ife_cleanup(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	spin_unlock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	p = rcu_dereference_protected(ife->params, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		kfree_rcu(p, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int load_metalist(struct nlattr **tb, bool rtnl_held)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	for (i = 1; i < max_metacnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		if (tb[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			void *val = nla_data(tb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			int len = nla_len(tb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			rc = load_metaops_and_vet(i, val, len, rtnl_held);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 				return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 			     bool exists, bool rtnl_held)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	void *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	for (i = 1; i < max_metacnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		if (tb[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 			val = nla_data(tb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 			len = nla_len(tb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			rc = add_metainfo(ife, i, val, len, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 			if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 				return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int tcf_ife_init(struct net *net, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			struct nlattr *est, struct tc_action **a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 			int ovr, int bind, bool rtnl_held,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 			struct tcf_proto *tp, u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	struct tc_action_net *tn = net_generic(net, ife_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	struct nlattr *tb[TCA_IFE_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	struct nlattr *tb2[IFE_META_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	struct tcf_chain *goto_ch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	struct tcf_ife_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	struct tcf_ife_info *ife;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	u16 ife_type = ETH_P_IFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	struct tc_ife *parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	u8 *daddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	u8 *saddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	bool exists = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	if (!nla) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 					  NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	if (!tb[TCA_IFE_PARMS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	parm = nla_data(tb[TCA_IFE_PARMS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	/* IFE_DECODE is 0 and indicates the opposite of IFE_ENCODE because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	 * they cannot run as the same time. Check on all other values which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	 * are not supported right now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (parm->flags & ~IFE_ENCODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	p = kzalloc(sizeof(*p), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	if (tb[TCA_IFE_METALST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		err = nla_parse_nested_deprecated(tb2, IFE_META_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 						  tb[TCA_IFE_METALST], NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 						  NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		err = load_metalist(tb2, rtnl_held);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	index = parm->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	err = tcf_idr_check_alloc(tn, &index, a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	exists = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	if (exists && bind) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	if (!exists) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 				     bind, true, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 			kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		ret = ACT_P_CREATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	} else if (!ovr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	ife = to_ife(*a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	if (ret == ACT_P_CREATED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		INIT_LIST_HEAD(&ife->metalist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		goto release_idr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	p->flags = parm->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	if (parm->flags & IFE_ENCODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		if (tb[TCA_IFE_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 			ife_type = nla_get_u16(tb[TCA_IFE_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		if (tb[TCA_IFE_DMAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 			daddr = nla_data(tb[TCA_IFE_DMAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		if (tb[TCA_IFE_SMAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			saddr = nla_data(tb[TCA_IFE_SMAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	if (parm->flags & IFE_ENCODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		if (daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			ether_addr_copy(p->eth_dst, daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			eth_zero_addr(p->eth_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 		if (saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			ether_addr_copy(p->eth_src, saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			eth_zero_addr(p->eth_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		p->eth_type = ife_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	if (tb[TCA_IFE_METALST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		err = populate_metalist(ife, tb2, exists, rtnl_held);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 			goto metadata_parse_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		/* if no passed metadata allow list or passed allow-all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		 * then here we process by adding as many supported metadatum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		 * as we can. You better have at least one else we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		 * going to bail out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		err = use_all_metadata(ife, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 			goto metadata_parse_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		spin_lock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	/* protected by tcf_lock when modifying existing action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	p = rcu_replace_pointer(ife->params, p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		spin_unlock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	if (goto_ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		tcf_chain_put_by_act(goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		kfree_rcu(p, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) metadata_parse_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	if (goto_ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		tcf_chain_put_by_act(goto_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) release_idr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			int ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	unsigned char *b = skb_tail_pointer(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	struct tcf_ife_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	struct tc_ife opt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		.index = ife->tcf_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		.refcnt = refcount_read(&ife->tcf_refcnt) - ref,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	struct tcf_t t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	spin_lock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	opt.action = ife->tcf_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	p = rcu_dereference_protected(ife->params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 				      lockdep_is_held(&ife->tcf_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	opt.flags = p->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	if (nla_put(skb, TCA_IFE_PARMS, sizeof(opt), &opt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	tcf_tm_dump(&t, &ife->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	if (nla_put_64bit(skb, TCA_IFE_TM, sizeof(t), &t, TCA_IFE_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	if (!is_zero_ether_addr(p->eth_dst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 		if (nla_put(skb, TCA_IFE_DMAC, ETH_ALEN, p->eth_dst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 			goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	if (!is_zero_ether_addr(p->eth_src)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		if (nla_put(skb, TCA_IFE_SMAC, ETH_ALEN, p->eth_src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 			goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	if (nla_put(skb, TCA_IFE_TYPE, 2, &p->eth_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	if (dump_metalist(skb, ife)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		/*ignore failure to dump metalist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		pr_info("Failed to dump metalist\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	spin_unlock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	spin_unlock_bh(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	nlmsg_trim(skb, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static int find_decode_metaid(struct sk_buff *skb, struct tcf_ife_info *ife,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 			      u16 metaid, u16 mlen, void *mdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	struct tcf_meta_info *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	/* XXX: use hash to speed up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	list_for_each_entry(e, &ife->metalist, metalist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 		if (metaid == e->metaid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 			if (e->ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 				/* We check for decode presence already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 				return e->ops->decode(skb, mdata, mlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 			  struct tcf_result *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	int action = ife->tcf_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	u8 *ifehdr_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	u8 *tlv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	u16 metalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	bstats_cpu_update(this_cpu_ptr(ife->common.cpu_bstats), skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	tcf_lastuse_update(&ife->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	if (skb_at_tc_ingress(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		skb_push(skb, skb->dev->hard_header_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	tlv_data = ife_decode(skb, &metalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	if (unlikely(!tlv_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 		qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	ifehdr_end = tlv_data + metalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	for (; tlv_data < ifehdr_end; tlv_data = ife_tlv_meta_next(tlv_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 		u8 *curr_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		u16 mtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		u16 dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, &mtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 						&dlen, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		if (!curr_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 			qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 			return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 		if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 			/* abuse overlimits to count when we receive metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 			 * but dont have an ops for it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 			pr_info_ratelimited("Unknown metaid %d dlen %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 					    mtype, dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 			qstats_overlimit_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	if (WARN_ON(tlv_data != ifehdr_end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 		return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	skb->protocol = eth_type_trans(skb, skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 	return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /*XXX: check if we can do this at install time instead of current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)  * send data path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	struct tcf_meta_info *e, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	int tot_run_sz = 0, run_sz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	list_for_each_entry_safe(e, n, &ife->metalist, metalist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		if (e->ops->check_presence) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 			run_sz = e->ops->check_presence(skb, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 			tot_run_sz += run_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	return tot_run_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 			  struct tcf_result *res, struct tcf_ife_params *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	int action = ife->tcf_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	struct ethhdr *oethh;	/* outer ether header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	struct tcf_meta_info *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	   OUTERHDR:TOTMETALEN:{TLVHDR:Metadatum:TLVHDR..}:ORIGDATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	   where ORIGDATA = original ethernet header ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	u16 metalen = ife_get_sz(skb, ife);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	int hdrm = metalen + skb->dev->hard_header_len + IFE_METAHDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	unsigned int skboff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	int new_len = skb->len + hdrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	bool exceed_mtu = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	void *ife_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	if (!skb_at_tc_ingress(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 		if (new_len > skb->dev->mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 			exceed_mtu = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	bstats_cpu_update(this_cpu_ptr(ife->common.cpu_bstats), skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	tcf_lastuse_update(&ife->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	if (!metalen) {		/* no metadata to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 		/* abuse overlimits to count when we allow packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		 * with no metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 		qstats_overlimit_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 		return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	/* could be stupid policy setup or mtu config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	 * so lets be conservative.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	if ((action == TC_ACT_SHOT) || exceed_mtu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 		return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	if (skb_at_tc_ingress(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		skb_push(skb, skb->dev->hard_header_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	ife_meta = ife_encode(skb, metalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	spin_lock(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	/* XXX: we dont have a clever way of telling encode to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	 * not repeat some of the computations that are done by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	 * ops->presence_check...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 	list_for_each_entry(e, &ife->metalist, metalist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 		if (e->ops->encode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 			err = e->ops->encode(skb, (void *)(ife_meta + skboff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 					     e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 			/* too corrupt to keep around if overwritten */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 			spin_unlock(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 			qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 			return TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 		skboff += err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	spin_unlock(&ife->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	oethh = (struct ethhdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	if (!is_zero_ether_addr(p->eth_src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		ether_addr_copy(oethh->h_source, p->eth_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 	if (!is_zero_ether_addr(p->eth_dst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 		ether_addr_copy(oethh->h_dest, p->eth_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	oethh->h_proto = htons(p->eth_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	if (skb_at_tc_ingress(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 		skb_pull(skb, skb->dev->hard_header_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 		       struct tcf_result *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 	struct tcf_ife_info *ife = to_ife(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	struct tcf_ife_params *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	p = rcu_dereference_bh(ife->params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	if (p->flags & IFE_ENCODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 		ret = tcf_ife_encode(skb, a, res, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	return tcf_ife_decode(skb, a, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 			  struct netlink_callback *cb, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 			  const struct tc_action_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 			  struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	struct tc_action_net *tn = net_generic(net, ife_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 	struct tc_action_net *tn = net_generic(net, ife_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 	return tcf_idr_search(tn, a, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static struct tc_action_ops act_ife_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	.kind = "ife",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 	.id = TCA_ID_IFE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	.act = tcf_ife_act,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 	.dump = tcf_ife_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	.cleanup = tcf_ife_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 	.init = tcf_ife_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	.walk = tcf_ife_walker,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 	.lookup = tcf_ife_search,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	.size =	sizeof(struct tcf_ife_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static __net_init int ife_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	struct tc_action_net *tn = net_generic(net, ife_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 	return tc_action_net_init(net, tn, &act_ife_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static void __net_exit ife_exit_net(struct list_head *net_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 	tc_action_net_exit(net_list, ife_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static struct pernet_operations ife_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 	.init = ife_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	.exit_batch = ife_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 	.id   = &ife_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	.size = sizeof(struct tc_action_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static int __init ife_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	return tcf_register_action(&act_ife_ops, &ife_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static void __exit ife_cleanup_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 	tcf_unregister_action(&act_ife_ops, &ife_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) module_init(ife_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) module_exit(ife_cleanup_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) MODULE_AUTHOR("Jamal Hadi Salim(2015)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) MODULE_DESCRIPTION("Inter-FE LFB action");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) MODULE_LICENSE("GPL");