On Mon, Jul 21, 2014 at 8:35 PM, Wenyu Zhang <wen...@vmware.com> wrote:
> Thanks for the review, my comments inline.
>
> Bests,
> Wenyu
> -----Original Message-----
> From: Pravin Shelar [mailto:pshe...@nicira.com]
> Sent: Tuesday, July 22, 2014 6:56 AM
> To: Wenyu Zhang
> Cc: Romain Lenglet; Ben Pfaff; Jesse Gross; dev@openvswitch.org
> Subject: Re: [PATCH v5] Extend OVS IPFIX exporter to export tunnel headers
>
> On Mon, Jul 21, 2014 at 2:39 AM, Wenyu Zhang <wen...@vmware.com> wrote:
>> Extend IPFIX exporter to export tunnel headers when both input and output
>> of the port.
>> Add three other_config options in IPFIX table: enable-input-sampling,
>> enable-output-sampling and enable-tunnel-sampling, to control whether
>> sampling tunnel info, on which direction (input or output).
>> Insert sampling action before output action and the output tunnel port
>> is sent to datapath in the sampling action.
>> Make datapath collect output tunnel info and send it back to userpace
>> in upcall message with a new additional optional attribute.
>> Add a tunnel ports map to make the tunnel port lookup faster in sampling
>> upcalls in IPFIX exporter. Make the IPFIX exporter generate IPFIX template
>> sets with enterprise elements for the tunnel info, save the tunnel info
>> in IPFIX cache entries, and send IPFIX DATA with tunnel info.
>> Add flowDirection element in IPFIX templates.
>>
>> Signed-off-by: Wenyu Zhang <wen...@vmware.com>
>> Acked-by: Romain Lenglet <rleng...@vmware.com>
>
> This looking close, I have few comments below.
>
>> ---
>> v2: Address Romain's comments
>> v3: Address Pravin's comments, make datapath sent all tunnel info,
>>     not only tunnel key to userspace.
>> v4: Address Pravin's comments, introduce a common function to get output
>>     tunnel info for all vports, remove duplicated codes.
>>     Rebase.
>> v5: Address Pravin's comments on v4, correct sparse errors, make a common
>>     function to setup tunnel info data for both input and output case.
>> ---
>>  datapath/actions.c                    |   18 ++
>>  datapath/datapath.c                   |   46 +++-
>>  datapath/datapath.h                   |    2 +
>>  datapath/flow.h                       |   54 ++--
>>  datapath/flow_netlink.c               |   58 ++++-
>>  datapath/flow_netlink.h               |    2 +
>>  datapath/vport-geneve.c               |   36 ++-
>>  datapath/vport-gre.c                  |   35 ++-
>>  datapath/vport-lisp.c                 |   40 ++-
>>  datapath/vport-vxlan.c                |   39 ++-
>>  datapath/vport.c                      |   40 +++
>>  datapath/vport.h                      |   11 +
>>  include/linux/openvswitch.h           |   21 +-
>>  lib/dpif-linux.c                      |    2 +
>>  lib/dpif.h                            |    1 +
>>  lib/odp-util.c                        |  183 +++++++++-----
>>  lib/odp-util.h                        |    2 +
>>  lib/packets.h                         |    9 +-
>>  ofproto/automake.mk                   |    3 +
>>  ofproto/ipfix-enterprise-entities.def |   19 ++
>>  ofproto/ofproto-dpif-ipfix.c          |  444 
>> ++++++++++++++++++++++++++++++---
>>  ofproto/ofproto-dpif-ipfix.h          |   14 +-
>>  ofproto/ofproto-dpif-upcall.c         |   20 +-
>>  ofproto/ofproto-dpif-xlate.c          |   51 +++-
>>  ofproto/ofproto-dpif.c                |   20 ++
>>  ofproto/ofproto.h                     |    3 +
>>  ofproto/tunnel.c                      |    4 +
>>  tests/odp.at                          |    9 +-
>>  utilities/ovs-vsctl.8.in              |    8 +-
>>  vswitchd/bridge.c                     |    9 +
>>  vswitchd/vswitch.ovsschema            |    5 +-
>>  vswitchd/vswitch.xml                  |   27 ++
>>  32 files changed, 1048 insertions(+), 187 deletions(-)
>>  create mode 100644 ofproto/ipfix-enterprise-entities.def
>>
>> diff --git a/datapath/actions.c b/datapath/actions.c
>> index 39a21f4..c1ad4dc 100644
>> --- a/datapath/actions.c
>> +++ b/datapath/actions.c
>> @@ -502,6 +502,7 @@ static int output_userspace(struct datapath *dp, struct 
>> sk_buff *skb,
>>         struct dp_upcall_info upcall;
>>         const struct nlattr *a;
>>         int rem;
>> +       struct ovs_tunnel_info output_tunnel_info;
>>
>>         BUG_ON(!OVS_CB(skb)->pkt_key);
>>
>> @@ -509,6 +510,7 @@ static int output_userspace(struct datapath *dp, struct 
>> sk_buff *skb,
>>         upcall.key = OVS_CB(skb)->pkt_key;
>>         upcall.userdata = NULL;
>>         upcall.portid = 0;
>> +       upcall.out_tun_info = NULL;
>>
>>         for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
>>                  a = nla_next(a, &rem)) {
>> @@ -520,7 +522,23 @@ static int output_userspace(struct datapath *dp, struct 
>> sk_buff *skb,
>>                 case OVS_USERSPACE_ATTR_PID:
>>                         upcall.portid = nla_get_u32(a);
>>                         break;
>> +
>> +               case OVS_USERSPACE_ATTR_TUNNEL_OUT_PORT: {
>> +                       /* Get out tunnel info. */
>> +                       int err;
>> +                       struct vport *vport;
>> +                       vport = ovs_vport_ovsl_rcu(dp, nla_get_u32(a));
> This function is never called under ovs_lock, so you can use rcu
> version of lookup.
> Wenyu: Sorry, I am confused. I have used ovs_vport_ovsl_rcu(), do you mean 
> another rcu version of lookup?
>

You can use ovs_vport_rcu().

>> +                       if (vport->ops->get_out_tun_info){
>
> You also need to check for vport, if it is NULL.
> Wenyu: Sure, I will add check for vport and vport->ops.
>
ok.

>> +                               err = vport->ops->get_out_tun_info(
>> +                                       vport, skb, &output_tunnel_info);
>> +                               if (err == 0) {
>> +                                       upcall.out_tun_info = 
>> &output_tunnel_info;
>> +                               }
>> +                       }
>> +                       break;
>>                 }
>> +
>> +               }/* End of switch. */
>>         }
>>
>
> .......
>>  {
>> +       BUILD_BUG_ON(sizeof(tun_info->tunnel) != OVS_TUNNEL_KEY_SIZE);
>> +
>>         tun_info->tunnel.tun_id = tun_id;
>> -       tun_info->tunnel.ipv4_src = iph->saddr;
>> -       tun_info->tunnel.ipv4_dst = iph->daddr;
>> -       tun_info->tunnel.ipv4_tos = iph->tos;
>> -       tun_info->tunnel.ipv4_ttl = iph->ttl;
>> +       tun_info->tunnel.ipv4_src = saddr;
>> +       tun_info->tunnel.ipv4_dst = daddr;
>> +       tun_info->tunnel.ipv4_tos = tos;
>> +       tun_info->tunnel.ipv4_ttl = ttl;
>>         tun_info->tunnel.tun_flags = tun_flags;
>>
>> -       /* clear struct padding. */
>> -       memset((unsigned char *) &tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
>> -              sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
>
> We still need this memset for case where we add another member to this
> struct, you can check for size of padding to avoid sparse warning.
> Wenyu:  The additional if condition  may affect performance, we'd better to 
> add some comments to mention this usage.
>                I have added a compling check about the size: 
> BUILD_BUG_ON(sizeof(tun_info->tunnel) != OVS_TUNNEL_KEY_SIZE);
>                If we add another member to this structre in future, this 
> check will failed when compling to mention us, and then we can add the memset 
> only when the failure happens.
>                 And I can add some comments  about the usage of memset here.
>

Compiler can determine size is zero and it does not generate code if
it is not required. so there is no performance penalty.

>> +       /* For the tunnel types on the top of IPsec, the tp_src and tp_dst of
>> +        * the upper tunnel are used.
>> +        * E.g: GRE over IPSEC, the tp_src and tp_port are zero.
>> +        */
>> +       tun_info->tunnel.tp_src = tp_src;
>> +       tun_info->tunnel.tp_dst = tp_dst;
>>
>>         tun_info->options = opts;
>>         tun_info->options_len = opts_len;
>>  }
>>
> .....
>
>>
>> +static int geneve_get_out_tun_info(struct vport *vport, struct sk_buff *skb,
>> +                                  struct ovs_tunnel_info *out_tun_info)
>> +{
>> +       struct geneve_port *geneve_port = geneve_vport(vport);
>> +
>> +       if (unlikely(!OVS_CB(skb)->tun_info))
>> +               return -EINVAL;
>> +
> Can you move this check inside ovs_vport_out_tun_info.
> Wenyu: Considering that the tp_src and tp_dst need be prepared before 
> ovs_vport_get_out_tun_info() is called, we'd better do the check before doing 
> the work to calculate tp_src and tp_dst. So I perfer to keep the check here.
>

tp_src and tp_dst does not depend on out_tun_info, so the check should
be moved to the common function.

>> +       /*
>> +        * Get tp_src and tp_dst, refert to geneve_build_header().
>> +        */
>> +       return ovs_vport_get_out_tun_info(out_tun_info, 
>> OVS_CB(skb)->tun_info,
>> +                                         ovs_dp_get_net(vport->dp),
>> +                                         IPPROTO_UDP, skb->mark,
>> +                                         vxlan_src_port(1, USHRT_MAX, skb),
>> +                                         inet_sport(geneve_port->sock->sk));
>> +
>> +}
>> +
>>  const struct vport_ops ovs_geneve_vport_ops = {
>> -       .type           = OVS_VPORT_TYPE_GENEVE,
>> -       .create         = geneve_tnl_create,
>> -       .destroy        = geneve_tnl_destroy,
>> -       .get_name       = geneve_get_name,
>> -       .get_options    = geneve_get_options,
>> -       .send           = geneve_send,
>> +       .type                   = OVS_VPORT_TYPE_GENEVE,
>> +       .create                 = geneve_tnl_create,
>> +       .destroy                = geneve_tnl_destroy,
>> +       .get_name               = geneve_get_name,
>> +       .get_options            = geneve_get_options,
>> +       .send                   = geneve_send,
>> +       .get_out_tun_info       = geneve_get_out_tun_info,
>>  };
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to