Ethernet header could be pushed to/stripped from packets with flow action push_eth/pop_eth, origin packets will be treated as payload even the packets are Ethernet packets.
Derived from work by Lorand Jakub and Simon Horman. Cc: Lorand Jakab <loja...@cisco.com> Cc: Simon Horman <simon.hor...@netronome.com> --- This is extracted from l3 flow support paches currently being targeted at net-next by Simon Horman. Signed-off-by: Simon Horman <simon.hor...@netronome.com> Signed-off-by: Johnson Li <johnson...@intel.com> diff --git a/datapath/actions.c b/datapath/actions.c index 0c2927e..eda9106 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -312,6 +312,48 @@ static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key, return 0; } +static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key) +{ + if ((skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)) && + !skb_vlan_tag_present(skb)) { + int err = skb_vlan_pop(skb); + if (unlikely(err)) + return err; + } + + skb_pull_rcsum(skb, ETH_HLEN); + skb_reset_mac_header(skb); + skb->mac_len -= ETH_HLEN; + + 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, skb->data, ETH_HLEN); + + invalidate_flow_key(key); + return 0; +} + /* 'src' is already properly masked. */ static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_) { @@ -1218,6 +1260,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, case OVS_ACTION_ATTR_POP_NSH: err = pop_nsh(skb, key); break; + + case OVS_ACTION_ATTR_PUSH_ETH: + err = push_eth(skb, key, nla_data(a)); + break; + + case OVS_ACTION_ATTR_POP_ETH: + err = pop_eth(skb, key); + break; } if (unlikely(err)) { diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 376dfda..03ac37c 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -310,6 +310,14 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb, skb->ip_summed = CHECKSUM_NONE; } +#define skb_postpush_rcsum rpl_skb_postpush_rcsum +static inline void skb_postpush_rcsum(struct sk_buff *skb, + const void *start, unsigned int len) +{ + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_partial(start, len, skb->csum); +} + #define skb_pull_rcsum rpl_skb_pull_rcsum static inline unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) { -- 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