Hi Lukasz,

Thanks for expanding the 802.1ad support.
I'm not familiar with sFlow, so I'll provide what feedback I can.

On Tue, Apr 18, 2017 at 12:08:22PM +0100, Lukasz Rzasik wrote:
> This patch implements QinQ related sFlow counters.
> It is implemented according to sFlow Version 5,
> http://www.sflow.org/sflow_version_5.txt
> Open vSwitch will send a stack of stripped VLAN tags
> to sFlow collector if the original packets have multiple
> VLAN tags.
> 
> Unit tests have been updated accordingly.
> 
> The patch is based on commit f0fb825a37 (Add support
> for 802.1ad (QinQ tunneling))
> 
> Signed-off-by: Lukasz Rzasik <lukaszx.rza...@intel.com>
> CC: Thomas F Herbert <thomasfherb...@gmail.com>
> CC: Xiao Liang <shaw.l...@gmail.com>
> CC: Eric Garver <e...@erig.me>
> CC: Neil McKee <neil.mc...@inmon.com>
> ---
>  lib/packets.h                |  4 +++
>  ofproto/ofproto-dpif-sflow.c | 60 +++++++++++++++++++++++++++++---
>  ofproto/ofproto-dpif-sflow.h |  9 +++++
>  tests/ofproto-dpif.at        | 83 
> ++++++++++++++++++++++++++++++++++++++++++++
>  tests/test-sflow.c           | 25 +++++++++++++
>  5 files changed, 177 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/packets.h b/lib/packets.h
> index 755f08d..7555dfc 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -384,6 +384,10 @@ static inline bool eth_type_vlan(ovs_be16 eth_type)
>          eth_type == htons(ETH_TYPE_VLAN_8021AD);
>  }
>  
> +static inline bool eth_type_8021Q(ovs_be16 eth_type)
> +{
> +    return eth_type == htons(ETH_TYPE_VLAN_8021Q);
> +}
>  
>  /* Minimum value for an Ethernet type.  Values below this are IEEE 802.2 
> frame
>   * lengths. */
> diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
> index 59fafa1..41972e2 100644
> --- a/ofproto/ofproto-dpif-sflow.c
> +++ b/ofproto/ofproto-dpif-sflow.c
> @@ -1084,6 +1084,31 @@ dpif_sflow_capture_input_mpls(const struct flow *flow,
>      }
>  }
>  
> +static void
> +dpif_sflow_pop_vlan(const struct flow *flow,
> +                    struct dpif_sflow_actions *sflow_actions)
> +{
> +    union flow_vlan_hdr vlan = flow->vlans[0];
> +    if (eth_type_vlan(vlan.tpid)) {
> +        int depth = 0;
> +        int ii;
> +        /* Calculate depth by detecting 8021Q TPID. */
> +        for (ii = 0; ii < FLOW_MAX_VLAN_HEADERS; ii++) {
> +            vlan = flow->vlans[ii];
> +            depth++;
> +            if (eth_type_8021Q(vlan.tpid)) {
> +                break;
> +            }

This seems to be using 0x8100 as a marker to stop. Does this mean double
stacked 0x8100 will not work?

flow_count_vlan_headers() can be used to find the number of tags.

> +        }
> +
> +        if (depth > 1) {
> +            sflow_actions->vlan_qtag[sflow_actions->vlan_stack_depth] =
> +            ntohl(flow->vlans[sflow_actions->vlan_stack_depth].qtag);
> +            sflow_actions->vlan_stack_depth++;
> +        }

AFAICS, this only adds the outermost tag to the stack. Is that
intentional? It's unclear to me if sFlow expects one or two VLANs to be
in the stack.

> +    }
> +}
> +
>  void
>  dpif_sflow_read_actions(const struct flow *flow,
>                       const struct nlattr *actions, size_t actions_len,
> @@ -1170,11 +1195,10 @@ dpif_sflow_read_actions(const struct flow *flow,
>           break;
>  
>       case OVS_ACTION_ATTR_PUSH_VLAN:
> +            break;
> +
>       case OVS_ACTION_ATTR_POP_VLAN:
> -         /* TODO: 802.1AD(QinQ) is not supported by OVS (yet), so do not
> -          * construct a VLAN-stack. The sFlow user-action cookie already
> -          * captures the egress VLAN ID so there is nothing more to do here.
> -          */
> +            dpif_sflow_pop_vlan(flow, sflow_actions);
>           break;
>  
>       case OVS_ACTION_ATTR_PUSH_MPLS: {
> @@ -1225,6 +1249,19 @@ dpif_sflow_encode_mpls_stack(SFLLabelStack *stack,
>      stack->stack[stack->depth - 1] |= MPLS_BOS_MASK;
>  }
>  
> +static void
> +dpif_sflow_encode_vlan_stack(SFLVlanStack *stack,
> +                             uint32_t *vlans_buf,
> +                             const struct dpif_sflow_actions *sflow_actions)
> +{
> +    int ii;
> +    stack->depth = sflow_actions->vlan_stack_depth;
> +    stack->stack = vlans_buf;
> +    for (ii = 0; ii < stack->depth; ii++) {
> +        stack->stack[ii] = sflow_actions->vlan_qtag[ii];
> +    }
> +}
> +
>  /* Extract the output port count from the user action cookie.
>   * See http://sflow.org/sflow_version_5.txt "Input/Output port information"
>   */
> @@ -1258,6 +1295,8 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct 
> dp_packet *packet,
>      SFLFlow_sample_element vniInElem, vniOutElem;
>      SFLFlow_sample_element mplsElem;
>      uint32_t mpls_lse_buf[FLOW_MAX_MPLS_LABELS];
> +    SFLFlow_sample_element vlanTunnelElem;
> +    uint32_t vlans_buf[FLOW_MAX_VLAN_HEADERS];
>      SFLSampler *sampler;
>      struct dpif_sflow_port *in_dsp;
>      struct dpif_sflow_port *out_dsp;
> @@ -1372,6 +1411,19 @@ dpif_sflow_received(struct dpif_sflow *ds, const 
> struct dp_packet *packet,
>       SFLADD_ELEMENT(&fs, &mplsElem);
>      }
>  
> +    /* stripped VLAN tags stack. */
> +    if (sflow_actions
> +        && sflow_actions->vlan_stack_depth > 0
> +        && dpif_sflow_cookie_num_outputs(cookie) == 1) {
> +        memset(&vlanTunnelElem, 0, sizeof(vlanTunnelElem));
> +        vlanTunnelElem.tag = SFLFLOW_EX_VLAN_TUNNEL;
> +        dpif_sflow_encode_vlan_stack(
> +                                 &vlanTunnelElem.flowType.vlan_tunnel.stack,
> +                                 vlans_buf,
> +                                 sflow_actions);
> +        SFLADD_ELEMENT(&fs, &vlanTunnelElem);
> +    }
> +
>      /* Submit the flow sample to be encoded into the next datagram. */
>      SFLADD_ELEMENT(&fs, &hdrElem);
>      SFLADD_ELEMENT(&fs, &switchElem);
> diff --git a/ofproto/ofproto-dpif-sflow.h b/ofproto/ofproto-dpif-sflow.h
> index 014e6cc..cfd5492 100644
> --- a/ofproto/ofproto-dpif-sflow.h
> +++ b/ofproto/ofproto-dpif-sflow.h
> @@ -49,6 +49,15 @@ struct dpif_sflow_actions {
>      uint32_t mpls_lse[FLOW_MAX_MPLS_LABELS]; /* Out stack in host byte 
> order. */
>      uint32_t mpls_stack_depth;               /* Out stack depth. */
>      bool mpls_err;                           /* MPLS actions parse failure. 
> */
> +
> +    /* Using host-byte order for the vlan stack here
> +       to match the expectations of the sFlow library.
> +       List of stripped 802.1Q TPID/TCI layers. Each
> +       TPID,TCI pair is represented as a single 32 bit
> +       integer. Layers listed from outermost to innermost.
> +    */
> +    uint32_t vlan_qtag[FLOW_MAX_VLAN_HEADERS]; /* Stack in host byte order. 
> */
> +    uint32_t vlan_stack_depth;                 /* Stack depth. */
>  };
>  
>  struct dpif_sflow *dpif_sflow_create(void);
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index 0c2ea38..f096175 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -6333,6 +6333,89 @@ HEADER
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
>  
> +AT_SETUP([ofproto-dpif - sFlow packet sampling - Extended VLAN tunnel])
> +AT_XFAIL_IF([test "$IS_WIN32" = "yes"])
> +OVS_VSWITCHD_START
> +AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
> +add_of_ports br0 1 2
> +AT_DATA([flows.txt], [dnl
> +table=0 dl_src=50:54:00:00:00:10 actions=strip_vlan,2
> +])
> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +
> +dnl set up sFlow logging
> +AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 
> 0:127.0.0.1 > sflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([sflow.log])
> +PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
> +ovs-appctl time/stop
> +
> +dnl configure sflow
> +ovs-vsctl \
> +   set Bridge br0 sflow=@sf -- \
> +   --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
> +     header=128 sampling=1 polling=0
> +
> +AT_CHECK([ovs-appctl netdev-dummy/receive p1 
> 'in_port(1),eth(src=50:54:00:00:00:10,dst=50:54:00:00:00:0a),eth_type(0x88a8),vlan(vid=150,pcp=0,cfi=1),encap(eth_type(0x8100),vlan(vid=2000,pcp=0,cfi=1),encap(eth_type(0x0800)))'])
> +AT_CHECK([ovs-appctl netdev-dummy/receive p1 
> 'in_port(1),eth(src=50:54:00:00:00:10,dst=50:54:00:00:00:0a),eth_type(0x8100),vlan(vid=2000,pcp=0,cfi=1),encap(eth_type(0x0800))'])
> +
> +dnl sleep long enough to get the sFlow datagram flushed out (may be delayed 
> for up to 1 second)
> +for i in `seq 1 30`; do
> +    ovs-appctl time/warp 100
> +done
> +
> +OVS_APP_EXIT_AND_WAIT([test-sflow])
> +
> +AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
> +        /g']], [0], [dnl
> +HEADER
> +        dgramSeqNo=1
> +        ds=127.0.0.1>2:1000
> +        fsSeqNo=1
> +        ext_vlan_tpid_0=0x88a8
> +        ext_vlan_vid_0=150
> +        ext_vlan_pcp_0=0
> +        ext_vlan_cfi_0=1
> +        in_vlan=150
> +        in_priority=0
> +        out_vlan=0
> +        out_priority=0
> +        meanSkip=1
> +        samplePool=1
> +        dropEvents=0
> +        in_ifindex=0
> +        in_format=0
> +        out_ifindex=1
> +        out_format=2
> +        hdr_prot=1
> +        pkt_len=22
> +        stripped=4
> +        hdr_len=18
> +        hdr=50-54-00-00-00-0A-50-54-00-00-00-10-88-A8-00-96-81-00
> +HEADER
> +        dgramSeqNo=1
> +        ds=127.0.0.1>2:1000
> +        fsSeqNo=2
> +        in_vlan=2000
> +        in_priority=0
> +        out_vlan=0
> +        out_priority=0
> +        meanSkip=1
> +        samplePool=2
> +        dropEvents=0
> +        in_ifindex=0
> +        in_format=0
> +        out_ifindex=1
> +        out_format=2
> +        hdr_prot=1
> +        pkt_len=42
> +        stripped=4
> +        hdr_len=38
> +        
> hdr=50-54-00-00-00-0A-50-54-00-00-00-10-81-00-07-D0-08-00-45-00-00-14-00-00-00-00-00-00-BA-EB-00-00-00-00-00-00-00-00
> +])
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
>  
>  # CHECK_NETFLOW_EXPIRATION(LOOPBACK_ADDR)
>  #
> diff --git a/tests/test-sflow.c b/tests/test-sflow.c
> index 6125d38..7d58ef3 100644
> --- a/tests/test-sflow.c
> +++ b/tests/test-sflow.c
> @@ -65,6 +65,7 @@ static unixctl_cb_func test_sflow_exit;
>  #define SFLOW_TAG_PKT_TUNNEL_VNI_OUT 1029
>  #define SFLOW_TAG_PKT_TUNNEL_VNI_IN 1030
>  #define SFLOW_TAG_PKT_MPLS 1006
> +#define SFLOW_TAG_PKT_EXTENDED_VLAN 1012
>  
>  /* string sizes */
>  #define SFL_MAX_PORTNAME_LEN 255
> @@ -116,6 +117,7 @@ struct sflow_xdr {
>       uint32_t TUNNEL_VNI_OUT;
>       uint32_t TUNNEL_VNI_IN;
>       uint32_t MPLS;
> +        uint32_t EXT_VLAN;
>       uint32_t IFCOUNTERS;
>       uint32_t ETHCOUNTERS;
>       uint32_t LACPCOUNTERS;
> @@ -428,6 +430,25 @@ process_flow_sample(struct sflow_xdr *x)
>              }
>          }
>  
> +        if (x->offset.EXT_VLAN) {
> +            uint32_t stack_depth, ii;
> +            union flow_vlan_hdr vlan;
> +            sflowxdr_setc(x, x->offset.EXT_VLAN);
> +            /* print stripped VLAN tags stack */
> +            stack_depth = sflowxdr_next(x);
> +            for (ii = 0; ii < stack_depth; ii++) {
> +                vlan.qtag=sflowxdr_next_n(x);
> +                printf(" ext_vlan_tpid_%"PRIu32"=0x%"PRIx32,
> +                       ii, ntohs(vlan.tpid));
> +                printf(" ext_vlan_vid_%"PRIu32"=%"PRIu32,
> +                       ii, vlan_tci_to_vid(vlan.tci));
> +                printf(" ext_vlan_pcp_%"PRIu32"=%"PRIu32,
> +                       ii, vlan_tci_to_pcp(vlan.tci));
> +                printf(" ext_vlan_cfi_%"PRIu32"=%"PRIu32,
> +                       ii, vlan_tci_to_cfi(vlan.tci));
> +            }
> +        }
> +
>          if (x->offset.SWITCH) {
>              sflowxdr_setc(x, x->offset.SWITCH);
>              printf(" in_vlan=%"PRIu32, sflowxdr_next(x));
> @@ -634,6 +655,10 @@ process_datagram(struct sflow_xdr *x)
>                      sflowxdr_mark_unique(x, &x->offset.MPLS);
>                      break;
>  
> +                case SFLOW_TAG_PKT_EXTENDED_VLAN:
> +                    sflowxdr_mark_unique(x, &x->offset.EXT_VLAN);
> +                    break;
> +
>                      /* Add others here... */
>                  }
>  
> -- 
> 1.9.3
> 
> --------------------------------------------------------------
> 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
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to