Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd20869d authored by Guillaume Nault's avatar Guillaume Nault Committed by James Wyatt Guidry
Browse files

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



    Implement TCA_VLAN_ACT_POP_ETH and TCA_VLAN_ACT_PUSH_ETH, to
    respectively pop and push a base Ethernet header at the beginning of a
    frame.

    POP_ETH is just a matter of pulling ETH_HLEN bytes. VLAN tags, if any,
    must be stripped before calling POP_ETH.

    PUSH_ETH is restricted to skbs with no mac_header, and only the MAC
    addresses can be configured. The Ethertype is automatically set from
    skb->protocol. These restrictions ensure that all skb's fields remain
    consistent, so that this action can't confuse other part of the
    networking stack (like GSO).

    Since openvswitch already had these actions, consolidate the code in
    skbuff.c (like for vlan and mpls push/pop).

Change-Id: Ifce1d5fee3eb1741bdc88b22f9000226744cc56c
Signed-off-by: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Git-commit: 19fbcb36a39eefbe8912a13ccc02e937b1c418d6
Git-repo: https://android.googlesource.com/kernel/common/


[quic_jguidry@quicinc.com: Added CONFIG_NET_SCHED_ACT_VLAN_QGKI to
 sdxlemur.config]
Signed-off-by: default avatarJames Wyatt Guidry <quic_jguidry@quicinc.com>
parent ded7fbf8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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,
+4 −0
Original line number Diff line number Diff line
@@ -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 {
+4 −0
Original line number Diff line number Diff line
@@ -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)
+69 −0
Original line number Diff line number Diff line
@@ -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)
Loading