History

net: core: move push MPLS functionality from OvS to core helper

Open vSwitch provides code to push an MPLS header to a packet. In preparation for supporting this in TC, move the push code to an skb helper that can be reused.

John Hurley committed 7 years ago

Commit 8822e271 parent af144a93 files · +69 −27Browse files

Unified · Split

3 files
  1. include/linux/skbuff.h +1 −0
  2. net/core/skbuff.c +64 −0
  3. net/openvswitch/actions.c +4 −27
include/linux/skbuff.h+1−0
@@ -3447,6 +3447,7 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len); · 3446 unmodified lines
34473447 int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
34483448 int skb_vlan_pop(struct sk_buff *skb);
34493449 int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
3450+int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
34503451 struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
34513452 gfp_t gfp);
34523453
net/core/skbuff.c+64−0
@@ -66,6 +66,7 @@ · 65 unmodified lines
6666 #include <net/checksum.h>
6767 #include <net/ip6_checksum.h>
6868 #include <net/xfrm.h>
69+#include <net/mpls.h>
6970
7071 #include <linux/uaccess.h>
7172 #include <trace/events/skb.h>
@@ -5425,6 +5426,69 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) · 5353 unmodified lines
54255426 }
54265427 EXPORT_SYMBOL(skb_vlan_push);
54275428
5429+/* Update the ethertype of hdr and the skb csum value if required. */
5430+static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr,
5431+ __be16 ethertype)
5432+{
5433+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
5434+ __be16 diff[] = { ~hdr->h_proto, ethertype };
5435+
5436+ skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
5437+ }
5438+
5439+ hdr->h_proto = ethertype;
5440+}
5441+
5442+/**
5443+ * skb_mpls_push() - push a new MPLS header after the mac header
5444+ *
5445+ * @skb: buffer
5446+ * @mpls_lse: MPLS label stack entry to push
5447+ * @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848)
5448+ *
5449+ * Expects skb->data at mac header.
5450+ *
5451+ * Returns 0 on success, -errno otherwise.
5452+ */
5453+int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto)
5454+{
5455+ struct mpls_shim_hdr *lse;
5456+ int err;
5457+
5458+ if (unlikely(!eth_p_mpls(mpls_proto)))
5459+ return -EINVAL;
5460+
5461+ /* Networking stack does not allow simultaneous Tunnel and MPLS GSO. */
5462+ if (skb->encapsulation)
5463+ return -EINVAL;
5464+
5465+ err = skb_cow_head(skb, MPLS_HLEN);
5466+ if (unlikely(err))
5467+ return err;
5468+
5469+ if (!skb->inner_protocol) {
5470+ skb_set_inner_network_header(skb, skb->mac_len);
5471+ skb_set_inner_protocol(skb, skb->protocol);
5472+ }
5473+
5474+ skb_push(skb, MPLS_HLEN);
5475+ memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
5476+ skb->mac_len);
5477+ skb_reset_mac_header(skb);
5478+ skb_set_network_header(skb, skb->mac_len);
5479+
5480+ lse = mpls_hdr(skb);
5481+ lse->label_stack_entry = mpls_lse;
5482+ skb_postpush_rcsum(skb, lse, MPLS_HLEN);
5483+
5484+ if (skb->dev && skb->dev->type == ARPHRD_ETHER)
5485+ skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto);
5486+ skb->protocol = mpls_proto;
5487+
5488+ return 0;
5489+}
5490+EXPORT_SYMBOL_GPL(skb_mpls_push);
5491+
54285492 /**
54295493 * alloc_skb_with_frags - allocate skb with page frags
54305494 *
net/openvswitch/actions.c+4−27
@@ -175,34 +175,11 @@ static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr, · 174 unmodified lines
175175 static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
176176 const struct ovs_action_push_mpls *mpls)
177177 {
178− struct mpls_shim_hdr *new_mpls_lse;
179−
180− /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */
181− if (skb->encapsulation)
182− return -ENOTSUPP;
183−
184− if (skb_cow_head(skb, MPLS_HLEN) < 0)
185− return -ENOMEM;
186−
187− if (!skb->inner_protocol) {
188− skb_set_inner_network_header(skb, skb->mac_len);
189− skb_set_inner_protocol(skb, skb->protocol);
190− }
191−
192− skb_push(skb, MPLS_HLEN);
193− memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
194− skb->mac_len);
195− skb_reset_mac_header(skb);
196− skb_set_network_header(skb, skb->mac_len);
197−
198− new_mpls_lse = mpls_hdr(skb);
199− new_mpls_lse->label_stack_entry = mpls->mpls_lse;
200−
201− skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
178+ int err;
202179
203− if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET)
204− update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
205− skb->protocol = mpls->mpls_ethertype;
180+ err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype);
181+ if (err)
182+ return err;
206183
207184 invalidate_flow_key(key);
208185 return 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t