Network Service Header is pushed to/stripped from packets with the data path flow actions push_nsh and pop_nsh.
Signed-off-by: Johnson Li <johnson...@intel.com> diff --git a/datapath/actions.c b/datapath/actions.c index 7ef1bae..0c2927e 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -29,6 +29,7 @@ #include <linux/in6.h> #include <linux/if_arp.h> #include <linux/if_vlan.h> +#include <linux/if_ether.h> #include <net/dst.h> #include <net/ip.h> @@ -37,6 +38,7 @@ #include <net/dsfield.h> #include <net/mpls.h> #include <net/sctp/checksum.h> +#include <net/nsh.h> #include "datapath.h" #include "conntrack.h" @@ -252,6 +254,64 @@ static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); } +static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key) +{ + struct nsh_hdr *nsh_hdr = NULL; + u16 length = 0; + + nsh_hdr = (struct nsh_hdr *)(skb->data); + length = nsh_hdr->base.length << 2; + + switch (nsh_hdr->base.next_proto) { + case NSH_P_IPV4: + skb->protocol = htons(ETH_P_IP); + key->eth.type = htons(ETH_P_IP); + break; + case NSH_P_IPV6: + skb->protocol = htons(ETH_P_IPV6); + key->eth.type = htons(ETH_P_IPV6); + break; + case NSH_P_ETHERNET: + skb->protocol = htons(ETH_P_TEB); + break; + default: + return -EINVAL; + } + + __skb_pull(skb, length); + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); + + memset(&key->nsh, 0, sizeof(key->nsh)); + + return 0; +} + +static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key, + const struct ovs_action_push_nsh *nsh) +{ + if (nsh->len > 0 && nsh->len <= 256) { + struct nsh_hdr *nsh_hdr = NULL; + + if (skb_cow_head(skb, nsh->len) < 0) + return -ENOMEM; + + skb_push(skb, nsh->len); + nsh_hdr = (struct nsh_hdr *)(skb->data); + memcpy(nsh_hdr, nsh->header, nsh->len); + + if (!skb->inner_protocol) + ovs_skb_set_inner_protocol(skb, skb->protocol); + + skb->protocol = htons(ETH_P_NSH); /* 0x894F */ + key->eth.type = htons(ETH_P_NSH); + } else { + return -EINVAL; + } + + return 0; +} + /* 'src' is already properly masked. */ static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_) { @@ -1150,6 +1210,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, if (err) return err == -EINPROGRESS ? 0 : err; break; + + case OVS_ACTION_ATTR_PUSH_NSH: + err = push_nsh(skb, key, nla_data(a)); + break; + + case OVS_ACTION_ATTR_POP_NSH: + err = pop_nsh(skb, key); + break; } if (unlikely(err)) { -- 1.8.4.2 -------------------------------------------------------------- Intel Research and Development Ireland Limited Registered in Ireland Registered Office: Collinstown Industrial Park, Leixlip, County Kildare Registered Number: 308263 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies. _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev