static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_mpls *mpls) { __be32 *new_mpls_lse; struct ethhdr *hdr; /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ if (skb->encapsulation) return -ENOTSUPP; if (skb_cow_head(skb, MPLS_HLEN) < 0) return -ENOMEM; skb_push(skb, MPLS_HLEN); memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), skb->mac_len); skb_reset_mac_header(skb); new_mpls_lse = (__be32 *)skb_mpls_header(skb); *new_mpls_lse = mpls->mpls_lse; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_add(skb->csum, csum_partial(new_mpls_lse, MPLS_HLEN, 0)); hdr = eth_hdr(skb); hdr->h_proto = mpls->mpls_ethertype; if (!skb->inner_protocol) skb_set_inner_protocol(skb, skb->protocol); skb->protocol = mpls->mpls_ethertype; invalidate_flow_key(key); return 0; }
static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, const __be16 ethertype) { struct ethhdr *hdr; int err; err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); if (unlikely(err)) return err; skb_postpull_rcsum(skb, skb_mpls_header(skb), MPLS_HLEN); memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), skb->mac_len); __skb_pull(skb, MPLS_HLEN); skb_reset_mac_header(skb); /* skb_mpls_header() is used to locate the ethertype * field correctly in the presence of VLAN tags. */ hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); hdr->h_proto = ethertype; if (eth_p_mpls(skb->protocol)) skb->protocol = ethertype; invalidate_flow_key(key); return 0; }
static int push_eth(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_eth *ethh) { struct ethhdr *hdr; /* Add the new Ethernet header */ if (skb_cow_head(skb, ETH_HLEN) < 0) return -ENOMEM; skb_push(skb, ETH_HLEN); skb_reset_mac_header(skb); skb_reset_mac_len(skb); hdr = eth_hdr(skb); ether_addr_copy(hdr->h_source, ethh->addresses.eth_src); ether_addr_copy(hdr->h_dest, ethh->addresses.eth_dst); hdr->h_proto = skb->protocol; skb_postpush_rcsum(skb, hdr, ETH_HLEN); /* safe right before invalidate_flow_key */ key->mac_proto = MAC_PROTO_ETHERNET; invalidate_flow_key(key); return 0; }
static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_mpls *mpls) { __be32 *new_mpls_lse; /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ if (skb->encapsulation) return -ENOTSUPP; if (skb_cow_head(skb, MPLS_HLEN) < 0) return -ENOMEM; skb_push(skb, MPLS_HLEN); memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), skb->mac_len); skb_reset_mac_header(skb); new_mpls_lse = (__be32 *)skb_mpls_header(skb); *new_mpls_lse = mpls->mpls_lse; skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype); if (!skb->inner_protocol) skb_set_inner_protocol(skb, skb->protocol); skb->protocol = mpls->mpls_ethertype; invalidate_flow_key(key); return 0; }
static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, const __be16 ethertype) { int err; err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); if (unlikely(err)) return err; skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN); memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), skb->mac_len); __skb_pull(skb, MPLS_HLEN); skb_reset_mac_header(skb); skb_set_network_header(skb, skb->mac_len); if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET) { struct ethhdr *hdr; /* mpls_hdr() is used to locate the ethertype field correctly in the * presence of VLAN tags. */ hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN); update_ethertype(skb, hdr, ethertype); } if (eth_p_mpls(skb->protocol)) skb->protocol = ethertype; invalidate_flow_key(key); return 0; }
static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_mpls *mpls) { struct mpls_shim_hdr *new_mpls_lse; /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ if (skb->encapsulation) return -ENOTSUPP; if (skb_cow_head(skb, MPLS_HLEN) < 0) return -ENOMEM; if (!skb->inner_protocol) { skb_set_inner_network_header(skb, skb->mac_len); skb_set_inner_protocol(skb, skb->protocol); } skb_push(skb, MPLS_HLEN); memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), skb->mac_len); skb_reset_mac_header(skb); skb_set_network_header(skb, skb->mac_len); new_mpls_lse = mpls_hdr(skb); new_mpls_lse->label_stack_entry = mpls->mpls_lse; skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET) update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype); skb->protocol = mpls->mpls_ethertype; invalidate_flow_key(key); return 0; }
static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_vlan *vlan) { if (skb_vlan_tag_present(skb)) invalidate_flow_key(key); else key->eth.tci = vlan->vlan_tci; return skb_vlan_push(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); }
static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key) { int err; err = skb_vlan_pop(skb); if (skb_vlan_tag_present(skb)) invalidate_flow_key(key); else key->eth.tci = 0; return err; }
/* pop_eth does not support VLAN packets as this action is never called * for them. */ static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key) { skb_pull_rcsum(skb, ETH_HLEN); skb_reset_mac_header(skb); skb_reset_mac_len(skb); /* safe right before invalidate_flow_key */ key->mac_proto = MAC_PROTO_NONE; invalidate_flow_key(key); return 0; }
static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key, const struct nshhdr *nh) { int err; err = nsh_push(skb, nh); if (err) return err; /* safe right before invalidate_flow_key */ key->mac_proto = MAC_PROTO_NONE; invalidate_flow_key(key); return 0; }
static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key) { int err; err = nsh_pop(skb); if (err) return err; /* safe right before invalidate_flow_key */ if (skb->protocol == htons(ETH_P_TEB)) key->mac_proto = MAC_PROTO_ETHERNET; else key->mac_proto = MAC_PROTO_NONE; invalidate_flow_key(key); return 0; }