This patch has been superseded by patch series
https://mail.openvswitch.org/pipermail/ovs-dev/2017-February/328391.html
specifically patch 
https://mail.openvswitch.org/pipermail/ovs-dev/2017-February/328394.html

Please exclude from review.

BR, Jan

> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On Behalf Of Yi Yang
> Sent: Monday, 06 February, 2017 14:05
> To: [email protected]
> Cc: Simon Horman <[email protected]>; Jiri Benc <[email protected]>
> Subject: [ovs-dev] [PATCH v3 09/16] userspace: add support for pop_eth and 
> push_eth actions
> 
> These actions will allow L2->L3 and L3->L2 switching, and are supposed
> to be added to flows installed in the datapath transparently by
> ovs-vswitchd.
> 
> Signed-off-by: Lorand Jakab <[email protected]>
> Signed-off-by: Simon Horman <[email protected]>
> Signed-off-by: Jiri Benc <[email protected]>
> Signed-off-by: Yi Yang <[email protected]>
> ---
>  lib/dpif-netdev.c            |  2 ++
>  lib/dpif.c                   |  2 ++
>  lib/odp-execute.c            | 18 ++++++++++
>  lib/odp-util.c               | 83 
> ++++++++++++++++++++++++++++++++++++++++++--
>  lib/packets.c                | 24 +++++++++++++
>  lib/packets.h                |  4 +++
>  ofproto/ofproto-dpif-sflow.c |  7 ++++
>  7 files changed, 137 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 0be5db5..73927c4 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -4732,6 +4732,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch 
> *packets_,
>      case OVS_ACTION_ATTR_HASH:
>      case OVS_ACTION_ATTR_UNSPEC:
>      case OVS_ACTION_ATTR_TRUNC:
> +    case OVS_ACTION_ATTR_PUSH_ETH:
> +    case OVS_ACTION_ATTR_POP_ETH:
>      case OVS_ACTION_ATTR_CLONE:
>      case __OVS_ACTION_ATTR_MAX:
>          OVS_NOT_REACHED();
> diff --git a/lib/dpif.c b/lib/dpif.c
> index 57aa3c6..1559ed4 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -1182,6 +1182,8 @@ dpif_execute_helper_cb(void *aux_, struct 
> dp_packet_batch *packets_,
>      case OVS_ACTION_ATTR_SET_MASKED:
>      case OVS_ACTION_ATTR_SAMPLE:
>      case OVS_ACTION_ATTR_TRUNC:
> +    case OVS_ACTION_ATTR_PUSH_ETH:
> +    case OVS_ACTION_ATTR_POP_ETH:
>      case OVS_ACTION_ATTR_CLONE:
>      case OVS_ACTION_ATTR_UNSPEC:
>      case __OVS_ACTION_ATTR_MAX:
> diff --git a/lib/odp-execute.c b/lib/odp-execute.c
> index 1f6812a..c0d6a20 100644
> --- a/lib/odp-execute.c
> +++ b/lib/odp-execute.c
> @@ -580,6 +580,8 @@ requires_datapath_assistance(const struct nlattr *a)
>      case OVS_ACTION_ATTR_PUSH_MPLS:
>      case OVS_ACTION_ATTR_POP_MPLS:
>      case OVS_ACTION_ATTR_TRUNC:
> +    case OVS_ACTION_ATTR_POP_ETH:
> +    case OVS_ACTION_ATTR_PUSH_ETH:
>      case OVS_ACTION_ATTR_CLONE:
>          return false;
> 
> @@ -724,6 +726,22 @@ odp_execute_actions(void *dp, struct dp_packet_batch 
> *batch, bool steal,
>              }
>              break;
> 
> +        case OVS_ACTION_ATTR_PUSH_ETH: {
> +            const struct ovs_action_push_eth *eth = nl_attr_get(a);
> +
> +            DP_PACKET_BATCH_FOR_EACH (packet, batch) {
> +                push_eth(packet, &eth->addresses.eth_dst,
> +                         &eth->addresses.eth_src);
> +            }
> +            break;
> +        }
> +
> +        case OVS_ACTION_ATTR_POP_ETH:
> +            DP_PACKET_BATCH_FOR_EACH (packet, batch) {
> +                pop_eth(packet);
> +            }
> +            break;
> +
>          case OVS_ACTION_ATTR_OUTPUT:
>          case OVS_ACTION_ATTR_TUNNEL_PUSH:
>          case OVS_ACTION_ATTR_TUNNEL_POP:
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 4106738..36e611b 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -124,6 +124,8 @@ odp_action_len(uint16_t type)
>      case OVS_ACTION_ATTR_SET_MASKED: return ATTR_LEN_VARIABLE;
>      case OVS_ACTION_ATTR_SAMPLE: return ATTR_LEN_VARIABLE;
>      case OVS_ACTION_ATTR_CT: return ATTR_LEN_VARIABLE;
> +    case OVS_ACTION_ATTR_PUSH_ETH: return sizeof(struct ovs_action_push_eth);
> +    case OVS_ACTION_ATTR_POP_ETH: return 0;
>      case OVS_ACTION_ATTR_CLONE: return ATTR_LEN_VARIABLE;
> 
>      case OVS_ACTION_ATTR_UNSPEC:
> @@ -850,6 +852,16 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
>          format_odp_key_attr(nl_attr_get(a), NULL, NULL, ds, true);
>          ds_put_cstr(ds, ")");
>          break;
> +    case OVS_ACTION_ATTR_PUSH_ETH: {
> +        const struct ovs_action_push_eth *eth = nl_attr_get(a);
> +        ds_put_format(ds, "push_eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT")",
> +                      ETH_ADDR_ARGS(eth->addresses.eth_src),
> +                      ETH_ADDR_ARGS(eth->addresses.eth_dst));
> +        break;
> +    }
> +    case OVS_ACTION_ATTR_POP_ETH:
> +        ds_put_cstr(ds, "pop_eth");
> +        break;
>      case OVS_ACTION_ATTR_PUSH_VLAN: {
>          const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
>          ds_put_cstr(ds, "push_vlan(");
> @@ -1055,14 +1067,39 @@ parse_odp_userspace_action(const char *s, struct 
> ofpbuf *actions)
>              odp_put_userspace_action(pid, user_data, user_data_size,
>                                       tunnel_out_port, include_actions, 
> actions);
>              res = n + n1;
> +            goto out;
>          } else if (s[n] == ')') {
>              odp_put_userspace_action(pid, user_data, user_data_size,
>                                       ODPP_NONE, include_actions, actions);
>              res = n + 1;
> -        } else {
> -            res = -EINVAL;
> +            goto out;
> +        }
> +    }
> +
> +    {
> +        struct ovs_action_push_eth push;
> +        int n1 = -1;
> +
> +        if (ovs_scan(&s[n], "push_eth(src="ETH_ADDR_SCAN_FMT","
> +                     "dst="ETH_ADDR_SCAN_FMT")%n",
> +                     ETH_ADDR_SCAN_ARGS(push.addresses.eth_src),
> +                     ETH_ADDR_SCAN_ARGS(push.addresses.eth_dst), &n1)) {
> +
> +            nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_ETH,
> +                              &push, sizeof push);
> +
> +            res = n + n1;
> +            goto out;
>          }
>      }
> +
> +    if (!strncmp(&s[n], "pop_eth", 7)) {
> +        nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_ETH);
> +        res = 7;
> +        goto out;
> +    }
> +
> +    res = -EINVAL;
>  out:
>      ofpbuf_uninit(&buf);
>      return res;
> @@ -5360,6 +5397,26 @@ odp_put_userspace_action(uint32_t pid,
>      return userdata_ofs;
>  }
> 
> +static void
> +odp_put_pop_eth_action(struct ofpbuf *odp_actions)
> +{
> +    nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_ETH);
> +}
> +
> +static void
> +odp_put_push_eth_action(struct ofpbuf *odp_actions,
> +                        const struct eth_addr *eth_src,
> +                        const struct eth_addr *eth_dst)
> +{
> +    struct ovs_action_push_eth eth;
> +
> +    eth.addresses.eth_src = *eth_src;
> +    eth.addresses.eth_dst = *eth_dst;
> +
> +    nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_ETH,
> +                      &eth, sizeof eth);
> +}
> +
>  void
>  odp_put_tunnel_action(const struct flow_tnl *tunnel,
>                        struct ofpbuf *odp_actions)
> @@ -5493,6 +5550,26 @@ commit_set_ether_addr_action(const struct flow *flow, 
> struct flow *base_flow,
>  }
> 
>  static void
> +commit_ether_action(const struct flow *flow, struct flow *base_flow,
> +                    struct ofpbuf *odp_actions, struct flow_wildcards *wc,
> +                    bool use_masked)
> +{
> +    if (flow->base_layer != base_flow->base_layer) {
> +        if (flow->base_layer == LAYER_2) {
> +            odp_put_push_eth_action(odp_actions, &flow->dl_src, 
> &flow->dl_dst);
> +            base_flow->dl_src = flow->dl_src;
> +            base_flow->dl_dst = flow->dl_dst;
> +        } else {
> +            odp_put_pop_eth_action(odp_actions);
> +        }
> +        base_flow->base_layer =  flow->base_layer;
> +    }
> +
> +    commit_set_ether_addr_action(flow, base_flow, odp_actions, wc,
> +                                 use_masked);
> +}
> +
> +static void
>  pop_vlan(struct flow *base,
>           struct ofpbuf *odp_actions, struct flow_wildcards *wc)
>  {
> @@ -5953,7 +6030,7 @@ commit_odp_actions(const struct flow *flow, struct flow 
> *base,
>      enum slow_path_reason slow1, slow2;
>      bool mpls_done = false;
> 
> -    commit_set_ether_addr_action(flow, base, odp_actions, wc, use_masked);
> +    commit_ether_action(flow, base, odp_actions, wc, use_masked);
>      /* Make packet a non-MPLS packet before committing L3/4 actions,
>       * which would otherwise do nothing. */
>      if (eth_type_mpls(base->dl_type) && !eth_type_mpls(flow->dl_type)) {
> diff --git a/lib/packets.c b/lib/packets.c
> index fa70df6..e440aaa 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -225,6 +225,30 @@ eth_pop_vlan(struct dp_packet *packet)
>      }
>  }
> 
> +/* Push Ethernet header onto 'packet' assuming it is layer 3 */
> +void
> +push_eth(struct dp_packet *packet, const struct eth_addr *dst,
> +         const struct eth_addr *src)
> +{
> +    struct eth_header *eh;
> +
> +    eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
> +    eh->eth_dst = *dst;
> +    eh->eth_src = *src;
> +}
> +
> +/* Removes Ethernet header, including all VLAN and MPLS headers, from 
> 'packet'.
> + *
> + * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */
> +void
> +pop_eth(struct dp_packet *packet)
> +{
> +    ovs_assert(dp_packet_l3(packet) != NULL);
> +
> +    dp_packet_resize_l2_5(packet, -packet->l3_ofs);
> +    dp_packet_set_l2_5(packet, NULL);
> +}
> +
>  /* Set ethertype of the packet. */
>  static void
>  set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
> diff --git a/lib/packets.h b/lib/packets.h
> index c4d3799..bf2e7c2 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -366,6 +366,10 @@ struct eth_header {
>  });
>  BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header));
> 
> +void push_eth(struct dp_packet *packet, const struct eth_addr *dst,
> +              const struct eth_addr *src);
> +void pop_eth(struct dp_packet *packet);
> +
>  #define LLC_DSAP_SNAP 0xaa
>  #define LLC_SSAP_SNAP 0xaa
>  #define LLC_CNTL_SNAP 3
> diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
> index 520b8dd..beb4b1f 100644
> --- a/ofproto/ofproto-dpif-sflow.c
> +++ b/ofproto/ofproto-dpif-sflow.c
> @@ -1164,6 +1164,13 @@ dpif_sflow_read_actions(const struct flow *flow,
>           dpif_sflow_pop_mpls_lse(sflow_actions);
>           break;
>       }
> +     case OVS_ACTION_ATTR_PUSH_ETH:
> +     case OVS_ACTION_ATTR_POP_ETH:
> +         /* TODO: SFlow does not currently define a MAC-in-MAC
> +          * encapsulation structure.  We could use an extension
> +          * structure to report this.
> +          */
> +         break;
>       case OVS_ACTION_ATTR_SAMPLE:
>       case OVS_ACTION_ATTR_CLONE:
>       case OVS_ACTION_ATTR_UNSPEC:
> --
> 2.1.0
> 
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to