On 09/08/2017 06:35 AM, Weglicki, MichalX wrote:
Greg,

Patch is rebased and sent to mailing list as V3 (Last patch was supposed to be 
V2 - Przemek by accident sent it again as V1).

Br,
Michal.

Thanks, I'll have a look at it!

- Greg


> -----Original Message-----
> From: Greg Rose [mailto:[email protected]]
> Sent: Thursday, September 7, 2017 12:02 AM
> To: Weglicki, MichalX <[email protected]>
> Cc: [email protected]; Szczerbik, PrzemyslawX 
<[email protected]>
> Subject: Re: [ovs-dev] [PATCH 2/2] ofproto-dpif-ipfix: add interface 
Information Elements to flow key
>
> On 09/06/2017 02:53 AM, Weglicki, MichalX wrote:
>> Hey Greg,
>>
>> Do you have any schedule for checking this patch?
>>
>> Thank you in advance!
>>
>> Br,
>> Michal.
>
> Michal,
>
> The good news is that I have my ntopng/nprobe ipfix collector properly 
configured now and can see
> flows, hosts, etc. when I enable IPFIX.  So I'm ready to test these two 
patches from Przemyslaw:
>
> https://patchwork.ozlabs.org/patch/793773/
> https://patchwork.ozlabs.org/patch/793772/
>
> Unfortunately the patches no longer apply to master.
>
> Can you rebase and resubmit a V3 series?
>
> Thanks,
>
> - Greg
>
>>
>>> -----Original Message-----
>>> From: Greg Rose [mailto:[email protected]]
>>> Sent: Tuesday, August 29, 2017 5:15 PM
>>> To: Weglicki, MichalX <[email protected]>
>>> Cc: [email protected]; Szczerbik, PrzemyslawX 
<[email protected]>
>>> Subject: Re: [ovs-dev] [PATCH 2/2] ofproto-dpif-ipfix: add interface 
Information Elements to flow key
>>>
>>> On 08/29/2017 04:48 AM, Weglicki, MichalX wrote:
>>>> Hello Greg,
>>>>
>>>> Unfortunately Przemek is not available, but I'm more or less familiar with 
this patch.
>>>>
>>>> Did you manage to fix this issue? I think that your problems lies on 
connection level, which wasn't modified by this patch. Patch
>>> added additional counters on reporting level, and based on your 
description, ovs just can't connect to collector.
>>>>
>>>> Br,
>>>> Michal.
>>>
>>> Correct - it is not an issue with the patch.  However, I need to test the 
patch and ran into problems while trying to do so.  Since
> then
>>> I've been pulled into some other work and will get back to this afterwards. 
 I'll just need to debug the connection issue to the
>>> collector.
>>>
>>> Thanks,
>>>
>>> - Greg
>>>
>>>>
>>>>> -----Original Message-----
>>>>> From: [email protected] 
[mailto:[email protected]] On Behalf Of Greg Rose
>>>>> Sent: Saturday, August 19, 2017 12:51 AM
>>>>> To: Szczerbik, PrzemyslawX <[email protected]>
>>>>> Cc: [email protected]
>>>>> Subject: Re: [ovs-dev] [PATCH 2/2] ofproto-dpif-ipfix: add interface 
Information Elements to flow key
>>>>>
>>>>> On 08/16/2017 01:54 AM, Szczerbik, PrzemyslawX wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I haven't received any feedback on this patch for quite some time.
>>>>>> Is there anything that I can do to expedite review process?
>>>>>>
>>>>>> Regards,
>>>>>> Przemek
>>>>>>
>>>>>
>>>>> Przemek,
>>>>>
>>>>> I'm in the process of looking into this patch but I'm running into an 
issue with the vswitch not sending flows to the
>>> ntopng/nprobe
>>>>> collector I have set up.  I see this in the vswitchd log:
>>>>>
>>>>> 2017-08-18T21:48:57.917Z|00058|collectors|WARN|couldn't open connection 
to collector 192.168.0.21:2055 (Network is
>>>>> unreachable)
>>>>> 2017-08-18T21:48:57.917Z|00059|ipfix|WARN|no collectors could be 
initialized, IPFIX exporter disabled
>>>>>
>>>>> However, 192.168.0.21 is reachable, at least from the br0 bridge that has 
the IPFIX flows enabled.
>>>>>
>>>>> ntopng/nprobe on the collector machine has the right ports open:
>>>>>
>>>>> netstat -tulpen | grep 2055
>>>>> udp        0      0 0.0.0.0:2055            0.0.0.0:*                     
      99         27671      3038/nprobe
>>>>> udp6       0      0 :::2055                 :::*                          
      99         27672      3038/nprobe
>>>>>
>>>>> netstat -tulpen | grep 5556
>>>>> tcp        0      0 0.0.0.0:5556            0.0.0.0:*               
LISTEN      0          27666      3038/nprobe
>>>>>
>>>>> I'm not sure exactly what the problem is but I'm debugging that.  Until I 
can get past this issue I can't really test and review
> your
>>>>> patch.  I am actively working on getting this issue fixed though.
>>>>>
>>>>> Regards,
>>>>>
>>>>> - Greg
>>>>>>> -----Original Message-----
>>>>>>> From: [email protected] [mailto:ovs-dev-
>>>>>>> [email protected]] On Behalf Of Szczerbik, PrzemyslawX
>>>>>>> Sent: Wednesday, July 26, 2017 12:01 PM
>>>>>>> To: [email protected]
>>>>>>> Subject: Re: [ovs-dev] [PATCH 2/2] ofproto-dpif-ipfix: add interface 
Information
>>>>>>> Elements to flow key
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> This patch was supposed to be v2, but I forgot to mention that in the 
subject.
>>>>>>> Previous version: https://patchwork.ozlabs.org/patch/792730/
>>>>>>>
>>>>>>> Let me know if you want me to re-sent it with a proper version.
>>>>>>>
>>>>>>> Regards,
>>>>>>> Przemek
>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: Szczerbik, PrzemyslawX
>>>>>>>> Sent: Wednesday, July 26, 2017 10:44 AM
>>>>>>>> To: [email protected]
>>>>>>>> Cc: Szczerbik, PrzemyslawX <[email protected]>
>>>>>>>> Subject: [PATCH 2/2] ofproto-dpif-ipfix: add interface Information 
Elements to
>>>>>>>> flow key
>>>>>>>>
>>>>>>>> Extend flow key part of data record to include following Information 
Elements:
>>>>>>>> - ingressInterface
>>>>>>>> - ingressInterfaceType
>>>>>>>> - egressInterface
>>>>>>>> - egressInterfaceType
>>>>>>>> - interfaceName
>>>>>>>> - interfaceDescription
>>>>>>>>
>>>>>>>> In case of input sampling we don't have information about egress port.
>>>>>>>> Define templates depending not only on protocol types, but also on flow
>>>>>>>> direction. Only egress flow will include egress information elements.
>>>>>>>>
>>>>>>>> With this change, dpif_ipfix_exporter stores every port in hmap rather
>>>>>>>> than only tunnel ports. It allows to easily retrieve required
>>>>>>>> information about interfaces during sampling upcalls.
>>>>>>>>
>>>>>>>> Signed-off-by: Przemyslaw Szczerbik <[email protected]>
>>>>>>>> ---
>>>>>>>> v1->v2
>>>>>>>> * Add interfaceType and interfaceDescription
>>>>>>>> * Rework ipfix_get_iface_data_record function
>>>>>>>>
>>>>>>>>      ofproto/ofproto-dpif-ipfix.c | 356 
+++++++++++++++++++++++++++++++-----
>>>>>>> --
>>>>>>>> -----
>>>>>>>>      ofproto/ofproto-dpif-ipfix.h |   6 +-
>>>>>>>>      ofproto/ofproto-dpif-xlate.c |   4 +-
>>>>>>>>      ofproto/ofproto-dpif.c       |  19 +--
>>>>>>>>      4 files changed, 275 insertions(+), 110 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/ofproto/ofproto-dpif-ipfix.c 
b/ofproto/ofproto-dpif-ipfix.c
>>>>>>>> index 13ff426..e7ce279 100644
>>>>>>>> --- a/ofproto/ofproto-dpif-ipfix.c
>>>>>>>> +++ b/ofproto/ofproto-dpif-ipfix.c
>>>>>>>> @@ -113,11 +113,12 @@ struct dpif_ipfix_global_stats {
>>>>>>>>      };
>>>>>>>>
>>>>>>>>      struct dpif_ipfix_port {
>>>>>>>> -    struct hmap_node hmap_node; /* In struct dpif_ipfix's 
"tunnel_ports"
>>>>>>> hmap.
>>>>>>>> */
>>>>>>>> +    struct hmap_node hmap_node; /* In struct dpif_ipfix's "ports" 
hmap. */
>>>>>>>>          struct ofport *ofport;      /* To retrieve port stats. */
>>>>>>>>          odp_port_t odp_port;
>>>>>>>>          enum dpif_ipfix_tunnel_type tunnel_type;
>>>>>>>>          uint8_t tunnel_key_length;
>>>>>>>> +    uint32_t ifindex;
>>>>>>>>      };
>>>>>>>>
>>>>>>>>      struct dpif_ipfix_exporter {
>>>>>>>> @@ -155,9 +156,9 @@ struct dpif_ipfix_flow_exporter_map_node {
>>>>>>>>      struct dpif_ipfix {
>>>>>>>>          struct dpif_ipfix_bridge_exporter bridge_exporter;
>>>>>>>>          struct hmap flow_exporter_map;  /* 
dpif_ipfix_flow_exporter_map_node.
>>>>>>> */
>>>>>>>> -    struct hmap tunnel_ports;       /* Contains "struct 
dpif_ipfix_port"s.
>>>>>>>> -                                     * It makes tunnel port lookups 
faster in
>>>>>>>> -                                     * sampling upcalls. */
>>>>>>>> +    struct hmap ports;              /* Contains "struct 
dpif_ipfix_port"s.
>>>>>>>> +                                     * It makes port lookups faster 
in sampling
>>>>>>>> +                                     * upcalls. */
>>>>>>>>          struct ovs_refcount ref_cnt;
>>>>>>>>      };
>>>>>>>>
>>>>>>>> @@ -291,7 +292,8 @@ BUILD_ASSERT_DECL(sizeof(struct
>>>>>>>> ipfix_template_field_specifier) == 8);
>>>>>>>>      /* Cf. IETF RFC 5102 Section 5.11.6. */
>>>>>>>>      enum ipfix_flow_direction {
>>>>>>>>          INGRESS_FLOW = 0x00,
>>>>>>>> -    EGRESS_FLOW = 0x01
>>>>>>>> +    EGRESS_FLOW = 0x01,
>>>>>>>> +    NUM_IPFIX_FLOW_DIRECTION
>>>>>>>>      };
>>>>>>>>
>>>>>>>>      /* Part of data record flow key for common metadata and Ethernet 
entities. */
>>>>>>>> @@ -306,6 +308,18 @@ struct ipfix_data_record_flow_key_common {
>>>>>>>>      });
>>>>>>>>      BUILD_ASSERT_DECL(sizeof(struct 
ipfix_data_record_flow_key_common) ==
>>>>>>>> 20);
>>>>>>>>
>>>>>>>> +/* Part of data record flow key for interface information. Since some 
of the
>>>>>>>> + * elements have variable length, members of this structure should be
>>>>>>>> appended
>>>>>>>> + * to the 'struct dp_packet' one by one. */
>>>>>>>> +struct ipfix_data_record_flow_key_iface {
>>>>>>>> +    ovs_be32 if_index;     /* (INGRESS|EGRESS)_INTERFACE */
>>>>>>>> +    ovs_be32 if_type;     /* (INGRESS|EGRESS)_INTERFACE_TYPE */
>>>>>>>> +    uint8_t if_name_len;   /* Variable length element: INTERFACE_NAME 
*/
>>>>>>>> +    char *if_name;
>>>>>>>> +    uint8_t if_descr_len; /* Variable length element: 
INTERFACE_DESCRIPTION
>>>>>>> */
>>>>>>>> +    char *if_descr;
>>>>>>>> +};
>>>>>>>> +
>>>>>>>>      /* Part of data record flow key for VLAN entities. */
>>>>>>>>      OVS_PACKED(
>>>>>>>>      struct ipfix_data_record_flow_key_vlan {
>>>>>>>> @@ -735,7 +749,7 @@ dpif_ipfix_find_port(const struct dpif_ipfix *di,
>>>>>>>>          struct dpif_ipfix_port *dip;
>>>>>>>>
>>>>>>>>          HMAP_FOR_EACH_IN_BUCKET (dip, hmap_node,
>>>>>>> hash_odp_port(odp_port),
>>>>>>>> -                             &di->tunnel_ports) {
>>>>>>>> +                             &di->ports) {
>>>>>>>>              if (dip->odp_port == odp_port) {
>>>>>>>>                  return dip;
>>>>>>>>              }
>>>>>>>> @@ -744,82 +758,114 @@ dpif_ipfix_find_port(const struct dpif_ipfix 
*di,
>>>>>>>>      }
>>>>>>>>
>>>>>>>>      static void
>>>>>>>> -dpif_ipfix_del_port(struct dpif_ipfix *di,
>>>>>>>> +dpif_ipfix_del_port__(struct dpif_ipfix *di,
>>>>>>>>                            struct dpif_ipfix_port *dip)
>>>>>>>>          OVS_REQUIRES(mutex)
>>>>>>>>      {
>>>>>>>> -    hmap_remove(&di->tunnel_ports, &dip->hmap_node);
>>>>>>>> +    hmap_remove(&di->ports, &dip->hmap_node);
>>>>>>>>          free(dip);
>>>>>>>>      }
>>>>>>>>
>>>>>>>> +static enum dpif_ipfix_tunnel_type
>>>>>>>> +dpif_ipfix_tunnel_type(const struct ofport *ofport) {
>>>>>>>> +    const char *type = netdev_get_type(ofport->netdev);
>>>>>>>> +
>>>>>>>> +    if (type == NULL) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_UNKNOWN;
>>>>>>>> +    }
>>>>>>>> +    if (strcmp(type, "gre") == 0) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_GRE;
>>>>>>>> +    } else if (strcmp(type, "vxlan") == 0) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_VXLAN;
>>>>>>>> +    } else if (strcmp(type, "lisp") == 0) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_LISP;
>>>>>>>> +    } else if (strcmp(type, "geneve") == 0) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_GENEVE;
>>>>>>>> +    } else if (strcmp(type, "stt") == 0) {
>>>>>>>> +        return DPIF_IPFIX_TUNNEL_STT;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    return DPIF_IPFIX_TUNNEL_UNKNOWN;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static uint8_t
>>>>>>>> +dpif_ipfix_tunnel_key_length(enum dpif_ipfix_tunnel_type tunnel_type) 
{
>>>>>>>> +
>>>>>>>> +    switch (tunnel_type) {
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_GRE:
>>>>>>>> +            /* 32-bit key gre */
>>>>>>>> +            return 4;
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_VXLAN:
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_LISP:
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_GENEVE:
>>>>>>>> +            return 3;
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_STT:
>>>>>>>> +            return 8;
>>>>>>>> +        case DPIF_IPFIX_TUNNEL_UNKNOWN:
>>>>>>>> +        case NUM_DPIF_IPFIX_TUNNEL:
>>>>>>>> +        default:
>>>>>>>> +            return 0;
>>>>>>>> +    }
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      void
>>>>>>>> -dpif_ipfix_add_tunnel_port(struct dpif_ipfix *di, struct ofport 
*ofport,
>>>>>>>> -                           odp_port_t odp_port) OVS_EXCLUDED(mutex)
>>>>>>>> +dpif_ipfix_add_port(struct dpif_ipfix *di, struct ofport *ofport,
>>>>>>>> +                    odp_port_t odp_port) OVS_EXCLUDED(mutex)
>>>>>>>>      {
>>>>>>>>          struct dpif_ipfix_port *dip;
>>>>>>>> -    const char *type;
>>>>>>>> +    int64_t ifindex;
>>>>>>>>
>>>>>>>>          ovs_mutex_lock(&mutex);
>>>>>>>>          dip = dpif_ipfix_find_port(di, odp_port);
>>>>>>>>          if (dip) {
>>>>>>>> -        dpif_ipfix_del_port(di, dip);
>>>>>>>> +        dpif_ipfix_del_port__(di, dip);
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    type = netdev_get_type(ofport->netdev);
>>>>>>>> -    if (type == NULL) {
>>>>>>>> -        goto out;
>>>>>>>> +    ifindex = netdev_get_ifindex(ofport->netdev);
>>>>>>>> +    if (ifindex < 0) {
>>>>>>>> +        ifindex = 0;
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    /* Add to table of tunnel ports. */
>>>>>>>> +    /* Add to table of ports. */
>>>>>>>>          dip = xmalloc(sizeof *dip);
>>>>>>>>          dip->ofport = ofport;
>>>>>>>>          dip->odp_port = odp_port;
>>>>>>>> -    if (strcmp(type, "gre") == 0) {
>>>>>>>> -        /* 32-bit key gre */
>>>>>>>> -        dip->tunnel_type = DPIF_IPFIX_TUNNEL_GRE;
>>>>>>>> -        dip->tunnel_key_length = 4;
>>>>>>>> -    } else if (strcmp(type, "vxlan") == 0) {
>>>>>>>> -        dip->tunnel_type = DPIF_IPFIX_TUNNEL_VXLAN;
>>>>>>>> -        dip->tunnel_key_length = 3;
>>>>>>>> -    } else if (strcmp(type, "lisp") == 0) {
>>>>>>>> -        dip->tunnel_type = DPIF_IPFIX_TUNNEL_LISP;
>>>>>>>> -        dip->tunnel_key_length = 3;
>>>>>>>> -    } else if (strcmp(type, "geneve") == 0) {
>>>>>>>> -        dip->tunnel_type = DPIF_IPFIX_TUNNEL_GENEVE;
>>>>>>>> -        dip->tunnel_key_length = 3;
>>>>>>>> -    } else if (strcmp(type, "stt") == 0) {
>>>>>>>> -        dip->tunnel_type = DPIF_IPFIX_TUNNEL_STT;
>>>>>>>> -        dip->tunnel_key_length = 8;
>>>>>>>> -    } else {
>>>>>>>> -        free(dip);
>>>>>>>> -        goto out;
>>>>>>>> -    }
>>>>>>>> -    hmap_insert(&di->tunnel_ports, &dip->hmap_node,
>>>>>>>> hash_odp_port(odp_port));
>>>>>>>> +    dip->tunnel_type = dpif_ipfix_tunnel_type(ofport);
>>>>>>>> +    dip->tunnel_key_length = dpif_ipfix_tunnel_key_length(dip-
>>>>>>>> tunnel_type);
>>>>>>>> +    dip->ifindex = ifindex;
>>>>>>>> +    hmap_insert(&di->ports, &dip->hmap_node, hash_odp_port(odp_port));
>>>>>>>>
>>>>>>>> -out:
>>>>>>>>          ovs_mutex_unlock(&mutex);
>>>>>>>>      }
>>>>>>>>
>>>>>>>>      void
>>>>>>>> -dpif_ipfix_del_tunnel_port(struct dpif_ipfix *di, odp_port_t odp_port)
>>>>>>>> +dpif_ipfix_del_port(struct dpif_ipfix *di, odp_port_t odp_port)
>>>>>>>>          OVS_EXCLUDED(mutex)
>>>>>>>>      {
>>>>>>>>          struct dpif_ipfix_port *dip;
>>>>>>>>          ovs_mutex_lock(&mutex);
>>>>>>>>          dip = dpif_ipfix_find_port(di, odp_port);
>>>>>>>>          if (dip) {
>>>>>>>> -        dpif_ipfix_del_port(di, dip);
>>>>>>>> +        dpif_ipfix_del_port__(di, dip);
>>>>>>>>          }
>>>>>>>>          ovs_mutex_unlock(&mutex);
>>>>>>>>      }
>>>>>>>>
>>>>>>>> +static struct dpif_ipfix_port *
>>>>>>>> +dpif_ipfix_find_tunnel_port(const struct dpif_ipfix *di, odp_port_t 
odp_port)
>>>>>>>> +    OVS_REQUIRES(mutex)
>>>>>>>> +{
>>>>>>>> +    struct dpif_ipfix_port *dip = dpif_ipfix_find_port(di, odp_port);
>>>>>>>> +    return (dip && dip->tunnel_type != DPIF_IPFIX_TUNNEL_UNKNOWN) ? 
dip
>>>>>>> :
>>>>>>>> NULL;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      bool
>>>>>>>> -dpif_ipfix_get_tunnel_port(const struct dpif_ipfix *di, odp_port_t 
odp_port)
>>>>>>>> +dpif_ipfix_is_tunnel_port(const struct dpif_ipfix *di, odp_port_t 
odp_port)
>>>>>>>>          OVS_EXCLUDED(mutex)
>>>>>>>>      {
>>>>>>>>          struct dpif_ipfix_port *dip;
>>>>>>>>          ovs_mutex_lock(&mutex);
>>>>>>>> -    dip = dpif_ipfix_find_port(di, odp_port);
>>>>>>>> +    dip = dpif_ipfix_find_tunnel_port(di, odp_port);
>>>>>>>>          ovs_mutex_unlock(&mutex);
>>>>>>>>          return dip != NULL;
>>>>>>>>      }
>>>>>>>> @@ -1055,7 +1101,7 @@ dpif_ipfix_create(void)
>>>>>>>>          di = xzalloc(sizeof *di);
>>>>>>>>          dpif_ipfix_bridge_exporter_init(&di->bridge_exporter);
>>>>>>>>          hmap_init(&di->flow_exporter_map);
>>>>>>>> -    hmap_init(&di->tunnel_ports);
>>>>>>>> +    hmap_init(&di->ports);
>>>>>>>>          ovs_refcount_init(&di->ref_cnt);
>>>>>>>>          return di;
>>>>>>>>      }
>>>>>>>> @@ -1149,8 +1195,8 @@ dpif_ipfix_clear(struct dpif_ipfix *di)
>>>>>>>> OVS_REQUIRES(mutex)
>>>>>>>>              free(exp_node);
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    HMAP_FOR_EACH_SAFE (dip, next, hmap_node, &di->tunnel_ports) {
>>>>>>>> -        dpif_ipfix_del_port(di, dip);
>>>>>>>> +    HMAP_FOR_EACH_SAFE (dip, next, hmap_node, &di->ports) {
>>>>>>>> +        dpif_ipfix_del_port__(di, dip);
>>>>>>>>          }
>>>>>>>>      }
>>>>>>>>
>>>>>>>> @@ -1162,7 +1208,7 @@ dpif_ipfix_unref(struct dpif_ipfix *di)
>>>>>>>> OVS_EXCLUDED(mutex)
>>>>>>>>              dpif_ipfix_clear(di);
>>>>>>>>              dpif_ipfix_bridge_exporter_destroy(&di->bridge_exporter);
>>>>>>>>              hmap_destroy(&di->flow_exporter_map);
>>>>>>>> -        hmap_destroy(&di->tunnel_ports);
>>>>>>>> +        hmap_destroy(&di->ports);
>>>>>>>>              free(di);
>>>>>>>>              ovs_mutex_unlock(&mutex);
>>>>>>>>          }
>>>>>>>> @@ -1201,13 +1247,15 @@ ipfix_send_msg(const struct collectors 
*collectors,
>>>>>>>> struct dp_packet *msg)
>>>>>>>>
>>>>>>>>      static uint16_t
>>>>>>>>      ipfix_get_template_id(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 
l3,
>>>>>>>> -                      enum ipfix_proto_l4 l4, enum ipfix_proto_tunnel 
tunnel)
>>>>>>>> +                      enum ipfix_proto_l4 l4, enum ipfix_proto_tunnel 
tunnel,
>>>>>>>> +                      enum ipfix_flow_direction flow_direction)
>>>>>>>>      {
>>>>>>>>          uint16_t template_id;
>>>>>>>>          template_id = l2;
>>>>>>>>          template_id = template_id * NUM_IPFIX_PROTO_L3 + l3;
>>>>>>>>          template_id = template_id * NUM_IPFIX_PROTO_L4 + l4;
>>>>>>>>          template_id = template_id * NUM_IPFIX_PROTO_TUNNEL + tunnel;
>>>>>>>> +    template_id = template_id * NUM_IPFIX_FLOW_DIRECTION +
>>>>>>> flow_direction;
>>>>>>>>          return IPFIX_TEMPLATE_ID_MIN + template_id;
>>>>>>>>      }
>>>>>>>>
>>>>>>>> @@ -1219,7 +1267,8 @@ ipfix_get_options_template_id(enum
>>>>>>>> ipfix_options_template opt_tmpl_type)
>>>>>>>>          uint16_t max_tmpl_id = 
ipfix_get_template_id(NUM_IPFIX_PROTO_L2,
>>>>>>>>                                                       
NUM_IPFIX_PROTO_L3,
>>>>>>>>                                                       
NUM_IPFIX_PROTO_L4,
>>>>>>>> -                                                 
NUM_IPFIX_PROTO_TUNNEL);
>>>>>>>> +                                                 
NUM_IPFIX_PROTO_TUNNEL,
>>>>>>>> +                                                 
NUM_IPFIX_FLOW_DIRECTION);
>>>>>>>>
>>>>>>>>          return max_tmpl_id + opt_tmpl_type;
>>>>>>>>      }
>>>>>>>> @@ -1315,7 +1364,9 @@ ipfix_def_options_template_fields(enum
>>>>>>>> ipfix_options_template opt_tmpl_type,
>>>>>>>>      static uint16_t
>>>>>>>>      ipfix_define_template_fields(enum ipfix_proto_l2 l2, enum 
ipfix_proto_l3 l3,
>>>>>>>>                                   enum ipfix_proto_l4 l4, enum 
ipfix_proto_tunnel tunnel,
>>>>>>>> -                             bool virtual_obs_id_set, size_t 
tmpl_hdr_offset,
>>>>>>>> +                             enum ipfix_flow_direction flow_direction,
>>>>>>>> +                             bool virtual_obs_id_set,
>>>>>>>> +                             size_t tmpl_hdr_offset,
>>>>>>>>                                   struct dp_packet *msg)
>>>>>>>>      {
>>>>>>>>
>>>>>>>> @@ -1333,6 +1384,19 @@ ipfix_define_template_fields(enum ipfix_proto_l2
>>>>>>> l2,
>>>>>>>> enum ipfix_proto_l3 l3,
>>>>>>>>          DEF(ETHERNET_TYPE);
>>>>>>>>          DEF(ETHERNET_HEADER_LENGTH);
>>>>>>>>
>>>>>>>> +    /* Interface Information Elements */
>>>>>>>> +    DEF(INGRESS_INTERFACE);
>>>>>>>> +    DEF(INGRESS_INTERFACE_TYPE);
>>>>>>>> +    DEF(INTERFACE_NAME);
>>>>>>>> +    DEF(INTERFACE_DESCRIPTION);
>>>>>>>> +
>>>>>>>> +    if (flow_direction == EGRESS_FLOW) {
>>>>>>>> +        DEF(EGRESS_INTERFACE);
>>>>>>>> +        DEF(EGRESS_INTERFACE_TYPE);
>>>>>>>> +        DEF(INTERFACE_NAME);
>>>>>>>> +        DEF(INTERFACE_DESCRIPTION);
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>>          if (l2 == IPFIX_PROTO_L2_VLAN) {
>>>>>>>>              DEF(VLAN_ID);
>>>>>>>>              DEF(DOT1Q_VLAN_ID);
>>>>>>>> @@ -1530,6 +1594,24 @@ ipfix_send_options_template_msgs(struct
>>>>>>>> dpif_ipfix_exporter *exporter,
>>>>>>>>      }
>>>>>>>>
>>>>>>>>      static void
>>>>>>>> +ipfix_add_template_record(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 
l3,
>>>>>>>> +                          enum ipfix_proto_l4 l4,
>>>>>>>> +                          enum ipfix_proto_tunnel tunnel,
>>>>>>>> +                          enum ipfix_flow_direction flow_direction,
>>>>>>>> +                          bool virtual_obs_id_set,
>>>>>>>> +                          struct dp_packet *msg)
>>>>>>>> +{
>>>>>>>> +    struct ipfix_template_record_header *tmpl_hdr;
>>>>>>>> +    size_t tmpl_hdr_offset = dp_packet_size(msg);
>>>>>>>> +
>>>>>>>> +    tmpl_hdr = dp_packet_put_zeros(msg, sizeof *tmpl_hdr);
>>>>>>>> +    tmpl_hdr->template_id =
>>>>>>>> +        htons(ipfix_get_template_id(l2, l3, l4, tunnel, 
flow_direction));
>>>>>>>> +    ipfix_define_template_fields(l2, l3, l4, tunnel, flow_direction,
>>>>>>>> +                                 virtual_obs_id_set, tmpl_hdr_offset, 
msg);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static void
>>>>>>>>      ipfix_send_template_msgs(struct dpif_ipfix_exporter *exporter,
>>>>>>>>                               uint32_t export_time_sec, uint32_t 
obs_domain_id)
>>>>>>>>      {
>>>>>>>> @@ -1537,14 +1619,14 @@ ipfix_send_template_msgs(struct
>>>>>>>> dpif_ipfix_exporter *exporter,
>>>>>>>>          struct dp_packet msg;
>>>>>>>>          dp_packet_use_stub(&msg, msg_stub, sizeof msg_stub);
>>>>>>>>
>>>>>>>> -    size_t set_hdr_offset, tmpl_hdr_offset, error_pkts;
>>>>>>>> -    struct ipfix_template_record_header *tmpl_hdr;
>>>>>>>> +    size_t set_hdr_offset, error_pkts;
>>>>>>>>          size_t tx_packets = 0;
>>>>>>>>          size_t tx_errors = 0;
>>>>>>>>          enum ipfix_proto_l2 l2;
>>>>>>>>          enum ipfix_proto_l3 l3;
>>>>>>>>          enum ipfix_proto_l4 l4;
>>>>>>>>          enum ipfix_proto_tunnel tunnel;
>>>>>>>> +    enum ipfix_flow_direction flow_direction;
>>>>>>>>
>>>>>>>>          ipfix_init_template_msg(export_time_sec, exporter->seq_number,
>>>>>>>>                                  obs_domain_id, IPFIX_SET_ID_TEMPLATE, 
&msg,
>>>>>>>> @@ -1559,41 +1641,44 @@ ipfix_send_template_msgs(struct
>>>>>>>> dpif_ipfix_exporter *exporter,
>>>>>>>>                          continue;
>>>>>>>>                      }
>>>>>>>>                      for (tunnel = 0; tunnel < NUM_IPFIX_PROTO_TUNNEL; 
tunnel++) {
>>>>>>>> -                    /* When the size of the template packet reaches
>>>>>>>> -                     * MAX_MESSAGE_LEN(1024), send it out.
>>>>>>>> -                     * And then reinitialize the msg to construct a 
new
>>>>>>>> -                     * packet for the following templates.
>>>>>>>> -                     */
>>>>>>>> -                    if (dp_packet_size(&msg) >= MAX_MESSAGE_LEN) {
>>>>>>>> -                        /* Send template message. */
>>>>>>>> -                        error_pkts = 
ipfix_send_template_msg(exporter->collectors,
>>>>>>>> -                                                             &msg, 
set_hdr_offset);
>>>>>>>> -                        tx_errors += error_pkts;
>>>>>>>> -                        tx_packets += 
collectors_count(exporter->collectors) - error_pkts;
>>>>>>>> -
>>>>>>>> -                        /* Reinitialize the template msg. */
>>>>>>>> -                        ipfix_init_template_msg(export_time_sec,
>>>>>>>> -                                                exporter->seq_number,
>>>>>>>> -                                                obs_domain_id,
>>>>>>>> -                                                IPFIX_SET_ID_TEMPLATE,
>>>>>>>> -                                                &msg,
>>>>>>>> -                                                &set_hdr_offset);
>>>>>>>> +                    for (flow_direction = 0;
>>>>>>>> +                         flow_direction < NUM_IPFIX_FLOW_DIRECTION;
>>>>>>>> +                         flow_direction++) {
>>>>>>>> +                        /* When the size of the template packet 
reaches
>>>>>>>> +                         * MAX_MESSAGE_LEN(1024), send it out.
>>>>>>>> +                         * And then reinitialize the msg to construct 
a new
>>>>>>>> +                         * packet for the following templates.
>>>>>>>> +                         */
>>>>>>>> +                        if (dp_packet_size(&msg) >= MAX_MESSAGE_LEN) {
>>>>>>>> +                            /* Send template message. */
>>>>>>>> +                            error_pkts =
>>>>>>>> +                                
ipfix_send_template_msg(exporter->collectors,
>>>>>>>> +                                                        &msg, 
set_hdr_offset);
>>>>>>>> +                            tx_errors += error_pkts;
>>>>>>>> +                            tx_packets +=
>>>>>>>> +                                collectors_count(exporter->collectors)
>>>>>>>> +                                - error_pkts;
>>>>>>>> +
>>>>>>>> +                            /* Reinitialize the template msg. */
>>>>>>>> +                            ipfix_init_template_msg(export_time_sec,
>>>>>>>> +                                                    
exporter->seq_number,
>>>>>>>> +                                                    obs_domain_id,
>>>>>>>> +                                                    
IPFIX_SET_ID_TEMPLATE,
>>>>>>>> +                                                    &msg, 
&set_hdr_offset);
>>>>>>>> +                        }
>>>>>>>> +
>>>>>>>> +                        ipfix_add_template_record(l2, l3, l4, tunnel,
>>>>>>>> +                                flow_direction,
>>>>>>>> +                                exporter->virtual_obs_id != NULL, 
&msg);
>>>>>>>>                          }
>>>>>>>> -
>>>>>>>> -                    tmpl_hdr_offset = dp_packet_size(&msg);
>>>>>>>> -                    tmpl_hdr = dp_packet_put_zeros(&msg, sizeof 
*tmpl_hdr);
>>>>>>>> -                    tmpl_hdr->template_id = htons(
>>>>>>>> -                        ipfix_get_template_id(l2, l3, l4, tunnel));
>>>>>>>> -                    ipfix_define_template_fields(
>>>>>>>> -                        l2, l3, l4, tunnel, exporter->virtual_obs_id 
!= NULL,
>>>>>>>> -                        tmpl_hdr_offset, &msg);
>>>>>>>>                      }
>>>>>>>>                  }
>>>>>>>>              }
>>>>>>>>          }
>>>>>>>>
>>>>>>>>          /* Send template message. */
>>>>>>>> -    error_pkts = ipfix_send_template_msg(exporter->collectors, &msg,
>>>>>>>> set_hdr_offset);
>>>>>>>> +    error_pkts = ipfix_send_template_msg(exporter->collectors, &msg,
>>>>>>>> +                                         set_hdr_offset);
>>>>>>>>          tx_errors += error_pkts;
>>>>>>>>          tx_packets += collectors_count(exporter->collectors) - 
error_pkts;
>>>>>>>>
>>>>>>>> @@ -1878,8 +1963,80 @@ ipfix_cache_update(struct dpif_ipfix_exporter
>>>>>>>> *exporter,
>>>>>>>>          }
>>>>>>>>      }
>>>>>>>>
>>>>>>>> +static void
>>>>>>>> +ipfix_destroy_iface_data_record(struct 
ipfix_data_record_flow_key_iface
>>>>>>>> *data)
>>>>>>>> +{
>>>>>>>> +    free(data->if_descr);
>>>>>>>> +    free(data->if_name);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/* Fills '*data' structure based on port number 'port_no'.  Caller 
must destroy
>>>>>>>> + * 'data' with ipfix_destroy_iface_data_record(). */
>>>>>>>> +static int
>>>>>>>> +ipfix_get_iface_data_record(const struct dpif_ipfix *di, odp_port_t 
port_no,
>>>>>>>> +                            struct ipfix_data_record_flow_key_iface 
*data)
>>>>>>>> +    OVS_REQUIRES(mutex)
>>>>>>>> +{
>>>>>>>> +    struct dpif_ipfix_port *port;
>>>>>>>> +    struct smap netdev_status;
>>>>>>>> +
>>>>>>>> +    port = dpif_ipfix_find_port(di, port_no);
>>>>>>>> +    if (!port) {
>>>>>>>> +        *data = (struct ipfix_data_record_flow_key_iface) {0};
>>>>>>>> +        return -1;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    smap_init(&netdev_status);
>>>>>>>> +    if (!netdev_get_status(port->ofport->netdev, &netdev_status)) {
>>>>>>>> +        data->if_type = htonl(smap_get_ullong(&netdev_status, 
"if_type", 0));
>>>>>>>> +        data->if_descr = nullable_xstrdup(smap_get(&netdev_status,
>>>>>>>> +                                                   "if_descr"));
>>>>>>>> +    } else {
>>>>>>>> +        data->if_type = 0;
>>>>>>>> +        data->if_descr = NULL;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    smap_destroy(&netdev_status);
>>>>>>>> +    data->if_index = htonl(port->ifindex);
>>>>>>>> +    data->if_descr_len = data->if_descr ? strlen(data->if_descr) : 0;
>>>>>>>> +    data->if_name = nullable_xstrdup(netdev_get_name(port->ofport-
>>>>>>>>> netdev));
>>>>>>>> +    data->if_name_len = data->if_name ? strlen(data->if_name) : 0;
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static void
>>>>>>>> +ipfix_put_iface_data_record(const struct dpif_ipfix *di, odp_port_t 
port_no,
>>>>>>>> +                            struct dp_packet *msg)
>>>>>>>> +    OVS_REQUIRES(mutex)
>>>>>>>> +{
>>>>>>>> +    struct ipfix_data_record_flow_key_iface data;
>>>>>>>> +    int err;
>>>>>>>> +
>>>>>>>> +    err = ipfix_get_iface_data_record(di, port_no, &data);
>>>>>>>> +    if (err == 0) {
>>>>>>>> +        dp_packet_put(msg, &data.if_index, sizeof data.if_index);
>>>>>>>> +        dp_packet_put(msg, &data.if_type, sizeof data.if_type);
>>>>>>>> +        dp_packet_put(msg, &data.if_name_len, sizeof 
data.if_name_len);
>>>>>>>> +        if (data.if_name_len) {
>>>>>>>> +            dp_packet_put(msg, data.if_name, data.if_name_len);
>>>>>>>> +        }
>>>>>>>> +        dp_packet_put(msg, &data.if_descr_len, sizeof 
data.if_descr_len);
>>>>>>>> +        if (data.if_descr_len) {
>>>>>>>> +            dp_packet_put(msg, data.if_descr, data.if_descr_len);
>>>>>>>> +        }
>>>>>>>> +        ipfix_destroy_iface_data_record(&data);
>>>>>>>> +    } else {
>>>>>>>> +        dp_packet_put_zeros(msg, sizeof data.if_index);
>>>>>>>> +        dp_packet_put_zeros(msg, sizeof data.if_type);
>>>>>>>> +        dp_packet_put_zeros(msg, sizeof data.if_name_len);
>>>>>>>> +        dp_packet_put_zeros(msg, sizeof data.if_descr_len);
>>>>>>>> +    }
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      static enum ipfix_sampled_packet_type
>>>>>>>> -ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
>>>>>>>> +ipfix_cache_entry_init(const struct dpif_ipfix *di,
>>>>>>>> +                       struct ipfix_flow_cache_entry *entry,
>>>>>>>>                             const struct dp_packet *packet, const 
struct flow *flow,
>>>>>>>>                             uint64_t packet_delta_count, uint32_t 
obs_domain_id,
>>>>>>>>                             uint32_t obs_point_id, odp_port_t 
output_odp_port,
>>>>>>>> @@ -1887,6 +2044,7 @@ ipfix_cache_entry_init(struct 
ipfix_flow_cache_entry
>>>>>>>> *entry,
>>>>>>>>                             const struct dpif_ipfix_port *tunnel_port,
>>>>>>>>                             const struct flow_tnl *tunnel_key,
>>>>>>>>                             struct dpif_ipfix_global_stats *stats)
>>>>>>>> +    OVS_REQUIRES(mutex)
>>>>>>>>      {
>>>>>>>>          struct ipfix_flow_key *flow_key;
>>>>>>>>          struct dp_packet msg;
>>>>>>>> @@ -1961,8 +2119,14 @@ ipfix_cache_entry_init(struct
>>>>>>> ipfix_flow_cache_entry
>>>>>>>> *entry,
>>>>>>>>             tunnel = IPFIX_PROTO_TUNNELED;
>>>>>>>>          }
>>>>>>>>
>>>>>>>> +    uint8_t flow_direction =
>>>>>>>> +        (direction == NX_ACTION_SAMPLE_INGRESS ? INGRESS_FLOW
>>>>>>>> +         : direction == NX_ACTION_SAMPLE_EGRESS ? EGRESS_FLOW
>>>>>>>> +         : output_odp_port == ODPP_NONE ? INGRESS_FLOW : EGRESS_FLOW);
>>>>>>>> +
>>>>>>>>          flow_key->obs_domain_id = obs_domain_id;
>>>>>>>> -    flow_key->template_id = ipfix_get_template_id(l2, l3, l4, tunnel);
>>>>>>>> +    flow_key->template_id = ipfix_get_template_id(l2, l3, l4, tunnel,
>>>>>>>> +                                                  flow_direction);
>>>>>>>>
>>>>>>>>          /* The fields defined in the ipfix_data_record_* structs and 
sent
>>>>>>>>           * below must match exactly the templates defined in
>>>>>>>> @@ -1972,11 +2136,6 @@ ipfix_cache_entry_init(struct
>>>>>>> ipfix_flow_cache_entry
>>>>>>>> *entry,
>>>>>>>>              ? VLAN_ETH_HEADER_LEN : ETH_HEADER_LEN;
>>>>>>>>          ethernet_total_length = dp_packet_size(packet);
>>>>>>>>
>>>>>>>> -    uint8_t flow_direction =
>>>>>>>> -        (direction == NX_ACTION_SAMPLE_INGRESS ? INGRESS_FLOW
>>>>>>>> -         : direction == NX_ACTION_SAMPLE_EGRESS ? EGRESS_FLOW
>>>>>>>> -         : output_odp_port == ODPP_NONE ? INGRESS_FLOW : EGRESS_FLOW);
>>>>>>>> -
>>>>>>>>          /* Common Ethernet entities. */
>>>>>>>>          {
>>>>>>>>              struct ipfix_data_record_flow_key_common *data_common;
>>>>>>>> @@ -1990,6 +2149,13 @@ ipfix_cache_entry_init(struct
>>>>>>> ipfix_flow_cache_entry
>>>>>>>> *entry,
>>>>>>>>              data_common->ethernet_header_length = 
ethernet_header_length;
>>>>>>>>          }
>>>>>>>>
>>>>>>>> +    /* Interface Information Elements */
>>>>>>>> +    ipfix_put_iface_data_record(di, flow->in_port.odp_port, &msg);
>>>>>>>> +
>>>>>>>> +    if (flow_direction == EGRESS_FLOW) {
>>>>>>>> +        ipfix_put_iface_data_record(di, output_odp_port, &msg);
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>>          if (l2 == IPFIX_PROTO_L2_VLAN) {
>>>>>>>>              struct ipfix_data_record_flow_key_vlan *data_vlan;
>>>>>>>>              uint16_t vlan_id = vlan_tci_to_vid(flow->vlans[0].tci);
>>>>>>>> @@ -2414,13 +2580,15 @@ ipfix_send_data_msg(struct dpif_ipfix_exporter
>>>>>>>> *exporter,
>>>>>>>>      }
>>>>>>>>
>>>>>>>>      static void
>>>>>>>> -dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter,
>>>>>>>> +dpif_ipfix_sample(const struct dpif_ipfix *di,
>>>>>>>> +                  struct dpif_ipfix_exporter *exporter,
>>>>>>>>                        const struct dp_packet *packet, const struct 
flow *flow,
>>>>>>>>                        uint64_t packet_delta_count, uint32_t 
obs_domain_id,
>>>>>>>>                        uint32_t obs_point_id, odp_port_t 
output_odp_port,
>>>>>>>>                        enum nx_action_sample_direction direction,
>>>>>>>>                        const struct dpif_ipfix_port *tunnel_port,
>>>>>>>>                        const struct flow_tnl *tunnel_key)
>>>>>>>> +    OVS_REQUIRES(mutex)
>>>>>>>>      {
>>>>>>>>          struct ipfix_flow_cache_entry *entry;
>>>>>>>>          enum ipfix_sampled_packet_type sampled_packet_type;
>>>>>>>> @@ -2428,7 +2596,7 @@ dpif_ipfix_sample(struct dpif_ipfix_exporter
>>>>>>>> *exporter,
>>>>>>>>          /* Create a flow cache entry from the sample. */
>>>>>>>>          entry = xmalloc(sizeof *entry);
>>>>>>>>          sampled_packet_type =
>>>>>>>> -            ipfix_cache_entry_init(entry, packet,
>>>>>>>> +            ipfix_cache_entry_init(di, entry, packet,
>>>>>>>>                                         flow, packet_delta_count,
>>>>>>>>                                         obs_domain_id, obs_point_id,
>>>>>>>>                                         output_odp_port, direction,
>>>>>>>> @@ -2484,16 +2652,16 @@ dpif_ipfix_bridge_sample(struct dpif_ipfix *di,
>>>>>>> const
>>>>>>>> struct dp_packet *packet,
>>>>>>>>              if (output_odp_port == ODPP_NONE && flow->tunnel.ip_dst) {
>>>>>>>>                  /* Input tunnel. */
>>>>>>>>                  tunnel_key = &flow->tunnel;
>>>>>>>> -            tunnel_port = dpif_ipfix_find_port(di, input_odp_port);
>>>>>>>> +            tunnel_port = dpif_ipfix_find_tunnel_port(di, 
input_odp_port);
>>>>>>>>              }
>>>>>>>>              if (output_odp_port != ODPP_NONE && output_tunnel_key) {
>>>>>>>>                  /* Output tunnel, output_tunnel_key must be valid. */
>>>>>>>>                  tunnel_key = output_tunnel_key;
>>>>>>>> -            tunnel_port = dpif_ipfix_find_port(di, output_odp_port);
>>>>>>>> +            tunnel_port = dpif_ipfix_find_tunnel_port(di, 
output_odp_port);
>>>>>>>>              }
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    dpif_ipfix_sample(&di->bridge_exporter.exporter, packet, flow,
>>>>>>>> +    dpif_ipfix_sample(di, &di->bridge_exporter.exporter, packet, flow,
>>>>>>>>                            packet_delta_count,
>>>>>>>>                            di->bridge_exporter.options->obs_domain_id,
>>>>>>>>                            di->bridge_exporter.options->obs_point_id,
>>>>>>>> @@ -2528,16 +2696,16 @@ dpif_ipfix_flow_sample(struct dpif_ipfix *di, 
const
>>>>>>>> struct dp_packet *packet,
>>>>>>>>                  if (output_odp_port == ODPP_NONE && 
flow->tunnel.ip_dst) {
>>>>>>>>                      /* Input tunnel. */
>>>>>>>>                      tunnel_key = &flow->tunnel;
>>>>>>>> -                tunnel_port = dpif_ipfix_find_port(di, 
input_odp_port);
>>>>>>>> +                tunnel_port = dpif_ipfix_find_tunnel_port(di, 
input_odp_port);
>>>>>>>>                  }
>>>>>>>>                  if (output_odp_port != ODPP_NONE && 
output_tunnel_key) {
>>>>>>>>                      /* Output tunnel, output_tunnel_key must be 
valid. */
>>>>>>>>                      tunnel_key = output_tunnel_key;
>>>>>>>> -                tunnel_port = dpif_ipfix_find_port(di, 
output_odp_port);
>>>>>>>> +                tunnel_port = dpif_ipfix_find_tunnel_port(di, 
output_odp_port);
>>>>>>>>                  }
>>>>>>>>              }
>>>>>>>>
>>>>>>>> -        dpif_ipfix_sample(&node->exporter.exporter, packet, flow,
>>>>>>>> +        dpif_ipfix_sample(di, &node->exporter.exporter, packet, flow,
>>>>>>>>                                packet_delta_count,
>>>>>>>>                                cookie->flow_sample.obs_domain_id,
>>>>>>>>                                cookie->flow_sample.obs_point_id,
>>>>>>>> diff --git a/ofproto/ofproto-dpif-ipfix.h 
b/ofproto/ofproto-dpif-ipfix.h
>>>>>>>> index 0808ede..0b21441 100644
>>>>>>>> --- a/ofproto/ofproto-dpif-ipfix.h
>>>>>>>> +++ b/ofproto/ofproto-dpif-ipfix.h
>>>>>>>> @@ -33,8 +33,8 @@ struct dpif_ipfix *dpif_ipfix_create(void);
>>>>>>>>      struct dpif_ipfix *dpif_ipfix_ref(const struct dpif_ipfix *);
>>>>>>>>      void dpif_ipfix_unref(struct dpif_ipfix *);
>>>>>>>>
>>>>>>>> -void dpif_ipfix_add_tunnel_port(struct dpif_ipfix *, struct ofport *,
>>>>>>>> odp_port_t);
>>>>>>>> -void dpif_ipfix_del_tunnel_port(struct dpif_ipfix *, odp_port_t);
>>>>>>>> +void dpif_ipfix_add_port(struct dpif_ipfix *, struct ofport *, 
odp_port_t);
>>>>>>>> +void dpif_ipfix_del_port(struct dpif_ipfix *, odp_port_t);
>>>>>>>>
>>>>>>>>      uint32_t dpif_ipfix_get_bridge_exporter_probability(const struct 
dpif_ipfix *);
>>>>>>>>      bool dpif_ipfix_get_bridge_exporter_tunnel_sampling(const struct 
dpif_ipfix
>>>>>>> *);
>>>>>>>> @@ -42,7 +42,7 @@ bool
>>>>>>> dpif_ipfix_get_bridge_exporter_input_sampling(const
>>>>>>>> struct dpif_ipfix *);
>>>>>>>>      bool dpif_ipfix_get_bridge_exporter_output_sampling(const struct 
dpif_ipfix
>>>>>>>> *);
>>>>>>>>      bool dpif_ipfix_get_flow_exporter_tunnel_sampling(const struct 
dpif_ipfix *,
>>>>>>>>                                                        const uint32_t);
>>>>>>>> -bool dpif_ipfix_get_tunnel_port(const struct dpif_ipfix *, 
odp_port_t);
>>>>>>>> +bool dpif_ipfix_is_tunnel_port(const struct dpif_ipfix *, odp_port_t);
>>>>>>>>      void dpif_ipfix_set_options(
>>>>>>>>          struct dpif_ipfix *,
>>>>>>>>          const struct ofproto_ipfix_bridge_exporter_options *,
>>>>>>>> diff --git a/ofproto/ofproto-dpif-xlate.c 
b/ofproto/ofproto-dpif-xlate.c
>>>>>>>> index 7f7adb2..3a37559 100644
>>>>>>>> --- a/ofproto/ofproto-dpif-xlate.c
>>>>>>>> +++ b/ofproto/ofproto-dpif-xlate.c
>>>>>>>> @@ -2946,7 +2946,7 @@ compose_ipfix_action(struct xlate_ctx *ctx,
>>>>>>> odp_port_t
>>>>>>>> output_odp_port)
>>>>>>>>               * OVS_USERSPACE_ATTR_TUNNEL_OUT_PORT
>>>>>>>>               */
>>>>>>>>              if (dpif_ipfix_get_bridge_exporter_tunnel_sampling(ipfix) 
&&
>>>>>>>> -            dpif_ipfix_get_tunnel_port(ipfix, output_odp_port) ) {
>>>>>>>> +            dpif_ipfix_is_tunnel_port(ipfix, output_odp_port) ) {
>>>>>>>>                 tunnel_out_port = output_odp_port;
>>>>>>>>              }
>>>>>>>>          }
>>>>>>>> @@ -5199,7 +5199,7 @@ xlate_sample_action(struct xlate_ctx *ctx,
>>>>>>>>
>>>>>>>>              if (dpif_ipfix_get_flow_exporter_tunnel_sampling(ipfix,
>>>>>>>>                                                               
os->collector_set_id)
>>>>>>>> -            && dpif_ipfix_get_tunnel_port(ipfix, output_odp_port)) {
>>>>>>>> +            && dpif_ipfix_is_tunnel_port(ipfix, output_odp_port)) {
>>>>>>>>                  tunnel_out_port = output_odp_port;
>>>>>>>>                  emit_set_tunnel = true;
>>>>>>>>              }
>>>>>>>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>>>>>>>> index 50f440f..72a4334 100644
>>>>>>>> --- a/ofproto/ofproto-dpif.c
>>>>>>>> +++ b/ofproto/ofproto-dpif.c
>>>>>>>> @@ -1865,9 +1865,6 @@ port_construct(struct ofport *port_)
>>>>>>>>              }
>>>>>>>>
>>>>>>>>              port->is_tunnel = true;
>>>>>>>> -        if (ofproto->ipfix) {
>>>>>>>> -           dpif_ipfix_add_tunnel_port(ofproto->ipfix, port_, 
port->odp_port);
>>>>>>>> -        }
>>>>>>>>          } else {
>>>>>>>>              /* Sanity-check that a mapping doesn't already exist.  
This
>>>>>>>>               * shouldn't happen for non-tunnel ports. */
>>>>>>>> @@ -1888,6 +1885,9 @@ port_construct(struct ofport *port_)
>>>>>>>>          if (ofproto->sflow) {
>>>>>>>>              dpif_sflow_add_port(ofproto->sflow, port_, 
port->odp_port);
>>>>>>>>          }
>>>>>>>> +    if (ofproto->ipfix) {
>>>>>>>> +       dpif_ipfix_add_port(ofproto->ipfix, port_, port->odp_port);
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>          return 0;
>>>>>>>>      }
>>>>>>>> @@ -1933,10 +1933,6 @@ port_destruct(struct ofport *port_, bool del)
>>>>>>>>              atomic_count_dec(&ofproto->backer->tnl_count);
>>>>>>>>          }
>>>>>>>>
>>>>>>>> -    if (port->is_tunnel && ofproto->ipfix) {
>>>>>>>> -       dpif_ipfix_del_tunnel_port(ofproto->ipfix, port->odp_port);
>>>>>>>> -    }
>>>>>>>> -
>>>>>>>>          tnl_port_del(port);
>>>>>>>>          sset_find_and_delete(&ofproto->ports, devname);
>>>>>>>>          sset_find_and_delete(&ofproto->ghost_ports, devname);
>>>>>>>> @@ -1951,6 +1947,9 @@ port_destruct(struct ofport *port_, bool del)
>>>>>>>>          if (ofproto->sflow) {
>>>>>>>>              dpif_sflow_del_port(ofproto->sflow, port->odp_port);
>>>>>>>>          }
>>>>>>>> +    if (ofproto->ipfix) {
>>>>>>>> +       dpif_ipfix_del_port(ofproto->ipfix, port->odp_port);
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>          free(port->qdscp);
>>>>>>>>      }
>>>>>>>> @@ -2076,13 +2075,11 @@ set_ipfix(
>>>>>>>>                  di, bridge_exporter_options, flow_exporters_options,
>>>>>>>>                  n_flow_exporters_options);
>>>>>>>>
>>>>>>>> -        /* Add tunnel ports only when a new ipfix created */
>>>>>>>> +        /* Add ports only when a new ipfix created */
>>>>>>>>              if (new_di == true) {
>>>>>>>>                  struct ofport_dpif *ofport;
>>>>>>>>                  HMAP_FOR_EACH (ofport, up.hmap_node, 
&ofproto->up.ports) {
>>>>>>>> -                if (ofport->is_tunnel == true) {
>>>>>>>> -                    dpif_ipfix_add_tunnel_port(di, &ofport->up, 
ofport->odp_port);
>>>>>>>> -                }
>>>>>>>> +                dpif_ipfix_add_port(di, &ofport->up, 
ofport->odp_port);
>>>>>>>>                  }
>>>>>>>>              }
>>>>>>>>
>>>>>>>> --
>>>>>>>> 1.8.3.1
>>>>>>>
>>>>>>> --------------------------------------------------------------
>>>>>>> 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
>>>>>>> [email protected]
>>>>>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>>>> --------------------------------------------------------------
>>>>>> 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
>>>>>> [email protected]
>>>>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> 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