Commit ef743c09 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-sched-Add-actions-for-MPLS-L2-VPNs'



Guillaume Nault says:

====================
net/sched: Add actions for MPLS L2 VPNs

This patch series adds the necessary TC actions for supporting layer 2
MPLS VPNs (VPLS).

The objective is to give the possibility to add an MPLS header right
before an skb's mac header, then to prepend this MPLS packet with a
new Ethernet header with the MAC address of the next hop.

Patch 1 implements the actions for adding and removing the external
Ethernet header.
Patch 2 adds the possibility to push an MPLS header before the mac
header.

Most of the code already exists as these operations were first
implemented in openvswitch.

Practical example, with encap on Host-A and decap on Host-B:

 Host-A# tc filter add dev ethAx ingress matchall         \
           action mpls mac_push label 20                  \
           action vlan push_eth dst_mac 02:00:00:00:00:02 \
                                src_mac 02:00:00:00:00:01 \
           action mirred egress redirect dev ethAy

 Host-B# tc filter add dev ethBx ingress protocol mpls_uc \
           flower mpls_label 20 mpls_bos 1                \
           action vlan pop_eth                            \
           action mpls pop proto teb                      \
           action mirred egress redirect dev ethBy
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e275d49a a45294af
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3573,6 +3573,9 @@ 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);
int skb_eth_pop(struct sk_buff *skb);
int skb_eth_push(struct sk_buff *skb, const unsigned char *dst,
		 const unsigned char *src);
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,
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@

struct tcf_vlan_params {
	int               tcfv_action;
	unsigned char     tcfv_push_dst[ETH_ALEN];
	unsigned char     tcfv_push_src[ETH_ALEN];
	u16               tcfv_push_vid;
	__be16            tcfv_push_proto;
	u8                tcfv_push_prio;
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#define TCA_MPLS_ACT_PUSH	2
#define TCA_MPLS_ACT_MODIFY	3
#define TCA_MPLS_ACT_DEC_TTL	4
#define TCA_MPLS_ACT_MAC_PUSH	5

struct tc_mpls {
	tc_gen;		/* generic TC action fields. */
+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)
+67 −0
Original line number Diff line number Diff line
@@ -5558,6 +5558,73 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
}
EXPORT_SYMBOL(skb_vlan_push);

/**
 * 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);

/* 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