[ovs-dev] [PATCH v6 2/2] ofproto-dpif-ipfix: add interface Information Elements to flow key
Ben Pfaff
blp at ovn.org
Tue Dec 19 22:17:47 UTC 2017
I think that's OK.
On Tue, Dec 19, 2017 at 10:51:53AM +0000, Stokes, Ian wrote:
> Hi Greg,
>
> You had previously tested/reviewed this patchset when it was v5. Do you have any more comments on the v6?
>
> If not I was going to validate and merge this to the DPDK_MERGE branch today.
>
> Thanks
> Ian
>
> > -----Original Message-----
> > From: ovs-dev-bounces at openvswitch.org [mailto:ovs-dev-
> > bounces at openvswitch.org] On Behalf Of Michal Weglicki
> > Sent: Tuesday, November 14, 2017 11:00 AM
> > To: dev at openvswitch.org
> > Subject: [ovs-dev] [PATCH v6 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.
> >
> > v1->v2
> > * Add interfaceType and interfaceDescription
> > * Rework ipfix_get_iface_data_record function
> > v2->v3: Code rebase.
> > v3->v4: Minor comments applied.
> > v4->v5: Clang complation problem fix.
> >
> > Co-authored-by: Michal Weglicki <michalx.weglicki at intel.com>
> > Signed-off-by: Michal Weglicki <michalx.weglicki at intel.com>
> > Signed-off-by: Przemyslaw Szczerbik <przemyslawx.szczerbik at intel.com>
> > ---
> > ofproto/ofproto-dpif-ipfix.c | 358 +++++++++++++++++++++++++++++++-------
> > -----
> > ofproto/ofproto-dpif-ipfix.h | 6 +-
> > ofproto/ofproto-dpif-xlate.c | 4 +-
> > ofproto/ofproto-dpif.c | 19 +--
> > 4 files changed, 277 insertions(+), 110 deletions(-)
> >
> > diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
> > index 4d16878..98a8e7e 100644
> > --- a/ofproto/ofproto-dpif-ipfix.c
> > +++ b/ofproto/ofproto-dpif-ipfix.c
> > @@ -115,11 +115,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 {
> > @@ -157,9 +158,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;
> > };
> >
> > @@ -293,7 +294,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. */ @@ -308,6 +310,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 { @@ -745,7 +759,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;
> > }
> > @@ -754,82 +768,116 @@ 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;
> > }
> > @@ -1065,7 +1113,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;
> > }
> > @@ -1159,8 +1207,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);
> > }
> > }
> >
> > @@ -1172,7 +1220,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);
> > }
> > @@ -1211,13 +1259,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; }
> >
> > @@ -1229,7 +1279,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; } @@ -1324,7 +1375,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) {
> >
> > @@ -1342,6 +1395,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);
> > @@ -1543,6 +1609,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) { @@ -1550,14 +1634,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,
> > @@ -1572,41 +1656,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;
> >
> > @@ -1908,8 +1995,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) {
> > + 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;
> > +
> > + memset(&data, 0, sizeof(struct ipfix_data_record_flow_key_iface));
> > + 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,
> > @@ -1918,6 +2077,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry
> > *entry,
> > const struct flow_tnl *tunnel_key,
> > struct dpif_ipfix_global_stats *stats,
> > const struct dpif_ipfix_actions *ipfix_actions)
> > + OVS_REQUIRES(mutex)
> > {
> > struct ipfix_flow_key *flow_key;
> > struct dp_packet msg;
> > @@ -1992,8 +2152,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 @@ -2003,11
> > +2169,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; @@ -2021,6
> > +2182,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);
> > @@ -2468,7 +2636,8 @@ 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, @@ -
> > 2476,6 +2645,7 @@ dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter,
> > const struct dpif_ipfix_port *tunnel_port,
> > const struct flow_tnl *tunnel_key,
> > const struct dpif_ipfix_actions *ipfix_actions)
> > + OVS_REQUIRES(mutex)
> > {
> > struct ipfix_flow_cache_entry *entry;
> > enum ipfix_sampled_packet_type sampled_packet_type; @@ -2483,7
> > +2653,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, @@ -
> > 2541,16 +2711,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,
> > @@ -2586,16 +2756,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
> > f91d041..1309da1 100644
> > --- a/ofproto/ofproto-dpif-ipfix.h
> > +++ b/ofproto/ofproto-dpif-ipfix.h
> > @@ -38,8 +38,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 *); @@ -47,7 +47,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
> > 468cd16..5e271dc 100644
> > --- a/ofproto/ofproto-dpif-xlate.c
> > +++ b/ofproto/ofproto-dpif-xlate.c
> > @@ -2963,7 +2963,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;
> > }
> > }
> > @@ -5213,7 +5213,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
> > 0e86d04..5f7eca8 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -1872,9 +1872,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. */ @@ -1895,6 +1892,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;
> > }
> > @@ -1940,10 +1940,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); @@ -1958,6
> > +1954,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);
> > }
> > @@ -2083,13 +2082,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
> >
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
More information about the dev
mailing list