Merge "net/sched: act_vlan: Add {POP,PUSH}_ETH actions"

This commit is contained in:
qctecmdr 2022-08-12 10:24:17 -07:00 committed by Gerrit - the friendly Code Review server
commit df885aa30f
7 changed files with 148 additions and 0 deletions

View File

@ -383,3 +383,4 @@ CONFIG_SDX_EXT_IPC=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_MACSEC=y
CONFIG_SYSVIPC=y
CONFIG_NET_SCHED_ACT_VLAN_QGKI=y

View File

@ -3563,6 +3563,11 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len);
int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
int skb_eth_pop(struct sk_buff *skb);
int skb_eth_push(struct sk_buff *skb, const unsigned char *dst,
const unsigned char *src);
#endif
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
int mac_len, bool ethernet);
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,

View File

@ -16,6 +16,10 @@ struct tcf_vlan_params {
u8 tcfv_push_prio;
bool tcfv_push_prio_exists;
struct rcu_head rcu;
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
unsigned char tcfv_push_dst[ETH_ALEN];
unsigned char tcfv_push_src[ETH_ALEN];
#endif
};
struct tcf_vlan {

View File

@ -16,6 +16,8 @@
#define TCA_VLAN_ACT_POP 1
#define TCA_VLAN_ACT_PUSH 2
#define TCA_VLAN_ACT_MODIFY 3
#define TCA_VLAN_ACT_POP_ETH 4
#define TCA_VLAN_ACT_PUSH_ETH 5
struct tc_vlan {
tc_gen;
@ -30,6 +32,8 @@ enum {
TCA_VLAN_PUSH_VLAN_PROTOCOL,
TCA_VLAN_PAD,
TCA_VLAN_PUSH_VLAN_PRIORITY,
TCA_VLAN_PUSH_ETH_DST,
TCA_VLAN_PUSH_ETH_SRC,
__TCA_VLAN_MAX,
};
#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1)

View File

@ -5602,6 +5602,75 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
}
EXPORT_SYMBOL(skb_vlan_push);
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
/**
* skb_eth_pop() - Drop the Ethernet header at the head of a packet
*
* @skb: Socket buffer to modify
*
* Drop the Ethernet header of @skb.
*
* Expects that skb->data points to the mac header and that no VLAN tags are
* present.
*
* Returns 0 on success, -errno otherwise.
*/
int skb_eth_pop(struct sk_buff *skb)
{
if (!pskb_may_pull(skb, ETH_HLEN) || skb_vlan_tagged(skb) ||
skb_network_offset(skb) < ETH_HLEN)
return -EPROTO;
skb_pull_rcsum(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
return 0;
}
EXPORT_SYMBOL(skb_eth_pop);
/**
* skb_eth_push() - Add a new Ethernet header at the head of a packet
*
* @skb: Socket buffer to modify
* @dst: Destination MAC address of the new header
* @src: Source MAC address of the new header
*
* Prepend @skb with a new Ethernet header.
*
* Expects that skb->data points to the mac header, which must be empty.
*
* Returns 0 on success, -errno otherwise.
*/
int skb_eth_push(struct sk_buff *skb, const unsigned char *dst,
const unsigned char *src)
{
struct ethhdr *eth;
int err;
if (skb_network_offset(skb) || skb_vlan_tag_present(skb))
return -EPROTO;
err = skb_cow_head(skb, sizeof(*eth));
if (err < 0)
return err;
skb_push(skb, sizeof(*eth));
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
eth = eth_hdr(skb);
ether_addr_copy(eth->h_dest, dst);
ether_addr_copy(eth->h_source, src);
eth->h_proto = skb->protocol;
skb_postpush_rcsum(skb, eth, sizeof(*eth));
return 0;
}
EXPORT_SYMBOL(skb_eth_push);
#endif
/* Update the ethertype of hdr and the skb csum value if required. */
static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr,
__be16 ethertype)

View File

@ -975,6 +975,19 @@ config NET_TC_SKB_EXT
Say N here if you won't be using tc<->ovs offload or tc chains offload.
config NET_SCHED_ACT_VLAN_QGKI
bool "VLAN pop_eth/push_eth patch"
depends on NET_ACT_VLAN
depends on QGKI
help
Say Y here to support tc VLAN pop_eth/push_eth actions. Macro guards the
code against ABI breakage. When this flag is enabled, it is safe to assume
that the build is a Non GKI build.
Say N to exclude this support.
If unsure, say Y.
endif # NET_SCHED
config NET_SCH_FIFO

View File

@ -77,6 +77,18 @@ static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a,
/* put updated tci as hwaccel tag */
__vlan_hwaccel_put_tag(skb, p->tcfv_push_proto, tci);
break;
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
case TCA_VLAN_ACT_POP_ETH:
err = skb_eth_pop(skb);
if (err)
goto drop;
break;
case TCA_VLAN_ACT_PUSH_ETH:
err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
if (err)
goto drop;
break;
#endif
default:
BUG();
}
@ -93,10 +105,17 @@ static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a,
}
static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
[TCA_VLAN_UNSPEC] = { .strict_start_type = TCA_VLAN_PUSH_ETH_DST },
#endif
[TCA_VLAN_PARMS] = { .len = sizeof(struct tc_vlan) },
[TCA_VLAN_PUSH_VLAN_ID] = { .type = NLA_U16 },
[TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NLA_U16 },
[TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NLA_U8 },
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
[TCA_VLAN_PUSH_ETH_DST] = NLA_POLICY_ETH_ADDR,
[TCA_VLAN_PUSH_ETH_SRC] = NLA_POLICY_ETH_ADDR,
#endif
};
static int tcf_vlan_init(struct net *net, struct nlattr *nla,
@ -180,6 +199,19 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (push_prio_exists)
push_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
break;
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
case TCA_VLAN_ACT_POP_ETH:
break;
case TCA_VLAN_ACT_PUSH_ETH:
if (!tb[TCA_VLAN_PUSH_ETH_DST] || !tb[TCA_VLAN_PUSH_ETH_SRC]) {
if (exists)
tcf_idr_release(*a, bind);
else
tcf_idr_cleanup(tn, index);
return -EINVAL;
}
break;
#endif
default:
if (exists)
tcf_idr_release(*a, bind);
@ -221,6 +253,15 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
p->tcfv_push_prio_exists = push_prio_exists || action == TCA_VLAN_ACT_PUSH;
p->tcfv_push_proto = push_proto;
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
if (action == TCA_VLAN_ACT_PUSH_ETH) {
nla_memcpy(&p->tcfv_push_dst, tb[TCA_VLAN_PUSH_ETH_DST],
ETH_ALEN);
nla_memcpy(&p->tcfv_push_src, tb[TCA_VLAN_PUSH_ETH_SRC],
ETH_ALEN);
}
#endif
spin_lock_bh(&v->tcf_lock);
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock));
@ -279,6 +320,17 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
p->tcfv_push_prio))))
goto nla_put_failure;
#ifdef CONFIG_NET_SCHED_ACT_VLAN_QGKI
if (p->tcfv_action == TCA_VLAN_ACT_PUSH_ETH) {
if (nla_put(skb, TCA_VLAN_PUSH_ETH_DST, ETH_ALEN,
p->tcfv_push_dst))
goto nla_put_failure;
if (nla_put(skb, TCA_VLAN_PUSH_ETH_SRC, ETH_ALEN,
p->tcfv_push_src))
goto nla_put_failure;
}
#endif
tcf_tm_dump(&t, &v->tcf_tm);
if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))
goto nla_put_failure;