X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-ipfix.c;h=8e8e7a2a0cbcf16a6436a808d26c20f3fbcef4ca;hb=591cb419cf3694e0ae66a95973e73c61bad9e03d;hp=ef0e980d10dfe6b7ca6804ade913244e36904546;hpb=85606e05b691be7c2f2d4bcf0e91170b71ec8fbb;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c index ef0e980d1..8e8e7a2a0 100644 --- a/ofproto/ofproto-dpif-ipfix.c +++ b/ofproto/ofproto-dpif-ipfix.c @@ -33,6 +33,7 @@ VLOG_DEFINE_THIS_MODULE(ipfix); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); +static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; /* Cf. IETF RFC 5101 Section 10.3.4. */ #define IPFIX_DEFAULT_COLLECTOR_PORT 4739 @@ -62,7 +63,7 @@ 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_nodes. */ - int ref_cnt; + atomic_int ref_cnt; }; #define IPFIX_VERSION 0x000a @@ -73,23 +74,25 @@ struct dpif_ipfix { #define IPFIX_TEMPLATE_INTERVAL 600 /* Cf. IETF RFC 5101 Section 3.1. */ +OVS_PACKED( struct ipfix_header { ovs_be16 version; /* IPFIX_VERSION. */ ovs_be16 length; /* Length in bytes including this header. */ ovs_be32 export_time; /* Seconds since the epoch. */ ovs_be32 seq_number; /* Message sequence number. */ ovs_be32 obs_domain_id; /* Observation Domain ID. */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_header) == 16); #define IPFIX_SET_ID_TEMPLATE 2 #define IPFIX_SET_ID_OPTION_TEMPLATE 3 /* Cf. IETF RFC 5101 Section 3.3.2. */ +OVS_PACKED( struct ipfix_set_header { ovs_be16 set_id; /* IPFIX_SET_ID_* or valid template ID for Data Sets. */ ovs_be16 length; /* Length of the set in bytes including header. */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_set_header) == 4); /* Alternatives for templates at each layer. A template is defined by @@ -115,10 +118,11 @@ enum ipfix_proto_l4 { #define IPFIX_TEMPLATE_ID_MIN 256 /* Cf. IETF RFC 5101 Section 3.4.1. */ +OVS_PACKED( struct ipfix_template_record_header { ovs_be16 template_id; ovs_be16 field_count; -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_template_record_header) == 4); enum ipfix_entity_id { @@ -131,14 +135,16 @@ enum ipfix_entity_size { #include "ofproto/ipfix-entities.def" }; +OVS_PACKED( struct ipfix_template_field_specifier { ovs_be16 element_id; /* IPFIX_ENTITY_ID_*. */ ovs_be16 field_length; /* Length of the field's value, in bytes. */ /* No Enterprise ID, since only standard element IDs are specified. */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_template_field_specifier) == 4); /* Part of data record for common metadata and Ethernet entities. */ +OVS_PACKED( struct ipfix_data_record_common { ovs_be32 observation_point_id; /* OBSERVATION_POINT_ID */ ovs_be64 packet_delta_count; /* PACKET_DELTA_COUNT */ @@ -148,18 +154,20 @@ struct ipfix_data_record_common { ovs_be16 ethernet_type; /* ETHERNET_TYPE */ ovs_be16 ethernet_total_length; /* ETHERNET_TOTAL_LENGTH */ uint8_t ethernet_header_length; /* ETHERNET_HEADER_LENGTH */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_common) == 37); /* Part of data record for VLAN entities. */ +OVS_PACKED( struct ipfix_data_record_vlan { ovs_be16 vlan_id; /* VLAN_ID */ ovs_be16 dot1q_vlan_id; /* DOT1Q_VLAN_ID */ uint8_t dot1q_priority; /* DOT1Q_PRIORITY */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_vlan) == 5); /* Part of data record for IP entities. */ +OVS_PACKED( struct ipfix_data_record_ip { uint8_t ip_version; /* IP_VERSION */ uint8_t ip_ttl; /* IP_TTL */ @@ -167,29 +175,32 @@ struct ipfix_data_record_ip { uint8_t ip_diff_serv_code_point; /* IP_DIFF_SERV_CODE_POINT */ uint8_t ip_precedence; /* IP_PRECEDENCE */ uint8_t ip_class_of_service; /* IP_CLASS_OF_SERVICE */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ip) == 6); /* Part of data record for IPv4 entities. */ +OVS_PACKED( struct ipfix_data_record_ipv4 { ovs_be32 source_ipv4_address; /* SOURCE_IPV4_ADDRESS */ ovs_be32 destination_ipv4_address; /* DESTINATION_IPV4_ADDRESS */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ipv4) == 8); /* Part of data record for IPv4 entities. */ +OVS_PACKED( struct ipfix_data_record_ipv6 { uint8_t source_ipv6_address[16]; /* SOURCE_IPV6_ADDRESS */ uint8_t destination_ipv6_address[16]; /* DESTINATION_IPV6_ADDRESS */ ovs_be32 flow_label_ipv6; /* FLOW_LABEL_IPV6 */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ipv6) == 36); /* Part of data record for TCP/UDP entities. */ +OVS_PACKED( struct ipfix_data_record_tcpudp { ovs_be16 source_transport_port; /* SOURCE_TRANSPORT_PORT */ ovs_be16 destination_transport_port; /* DESTINATION_TRANSPORT_PORT */ -} __attribute__((packed)); +}); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_tcpudp) == 4); static bool @@ -401,13 +412,14 @@ dpif_ipfix_set_options( struct dpif_ipfix *di, const struct ofproto_ipfix_bridge_exporter_options *bridge_exporter_options, const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options, - size_t n_flow_exporters_options) + size_t n_flow_exporters_options) OVS_EXCLUDED(mutex) { int i; struct ofproto_ipfix_flow_exporter_options *options; struct dpif_ipfix_flow_exporter_map_node *node, *next; size_t n_broken_flow_exporters_options = 0; + ovs_mutex_lock(&mutex); dpif_ipfix_bridge_exporter_set_options(&di->bridge_exporter, bridge_exporter_options); @@ -456,6 +468,7 @@ dpif_ipfix_set_options( ovs_assert(hmap_count(&di->flow_exporter_map) == (n_flow_exporters_options - n_broken_flow_exporters_options)); + ovs_mutex_unlock(&mutex); } struct dpif_ipfix * @@ -465,7 +478,7 @@ dpif_ipfix_create(void) di = xzalloc(sizeof *di); dpif_ipfix_exporter_clear(&di->bridge_exporter.exporter); hmap_init(&di->flow_exporter_map); - di->ref_cnt = 1; + atomic_init(&di->ref_cnt, 1); return di; } @@ -474,20 +487,26 @@ dpif_ipfix_ref(const struct dpif_ipfix *di_) { struct dpif_ipfix *di = CONST_CAST(struct dpif_ipfix *, di_); if (di) { - ovs_assert(di->ref_cnt > 0); - di->ref_cnt++; + int orig; + atomic_add(&di->ref_cnt, 1, &orig); + ovs_assert(orig > 0); } return di; } uint32_t dpif_ipfix_get_bridge_exporter_probability(const struct dpif_ipfix *di) + OVS_EXCLUDED(mutex) { - return di->bridge_exporter.probability; + uint32_t ret; + ovs_mutex_lock(&mutex); + ret = di->bridge_exporter.probability; + ovs_mutex_unlock(&mutex); + return ret; } static void -dpif_ipfix_clear(struct dpif_ipfix *di) +dpif_ipfix_clear(struct dpif_ipfix *di) OVS_REQUIRES(mutex) { struct dpif_ipfix_flow_exporter_map_node *node, *next; @@ -501,17 +520,22 @@ dpif_ipfix_clear(struct dpif_ipfix *di) } void -dpif_ipfix_unref(struct dpif_ipfix *di) +dpif_ipfix_unref(struct dpif_ipfix *di) OVS_EXCLUDED(mutex) { + int orig; + if (!di) { return; } - ovs_assert(di->ref_cnt > 0); - if (!--di->ref_cnt) { + atomic_sub(&di->ref_cnt, 1, &orig); + ovs_assert(orig > 0); + if (orig == 1) { + ovs_mutex_lock(&mutex); dpif_ipfix_clear(di); hmap_destroy(&di->flow_exporter_map); free(di); + ovs_mutex_unlock(&mutex); } } @@ -832,35 +856,37 @@ dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter, void dpif_ipfix_bridge_sample(struct dpif_ipfix *di, struct ofpbuf *packet, - const struct flow *flow) + const struct flow *flow) OVS_EXCLUDED(mutex) { + uint64_t packet_delta_count; + + ovs_mutex_lock(&mutex); /* Use the sampling probability as an approximation of the number * of matched packets. */ - uint64_t packet_delta_count = UINT32_MAX / di->bridge_exporter.probability; - + packet_delta_count = UINT32_MAX / di->bridge_exporter.probability; dpif_ipfix_sample(&di->bridge_exporter.exporter, packet, flow, packet_delta_count, di->bridge_exporter.options->obs_domain_id, di->bridge_exporter.options->obs_point_id); + ovs_mutex_unlock(&mutex); } void dpif_ipfix_flow_sample(struct dpif_ipfix *di, struct ofpbuf *packet, const struct flow *flow, uint32_t collector_set_id, uint16_t probability, uint32_t obs_domain_id, - uint32_t obs_point_id) + uint32_t obs_point_id) OVS_EXCLUDED(mutex) { struct dpif_ipfix_flow_exporter_map_node *node; /* Use the sampling probability as an approximation of the number * of matched packets. */ uint64_t packet_delta_count = USHRT_MAX / probability; + ovs_mutex_lock(&mutex); node = dpif_ipfix_find_flow_exporter_map_node(di, collector_set_id); - - if (!node) { - return; + if (node) { + dpif_ipfix_sample(&node->exporter.exporter, packet, flow, + packet_delta_count, obs_domain_id, obs_point_id); } - - dpif_ipfix_sample(&node->exporter.exporter, packet, flow, - packet_delta_count, obs_domain_id, obs_point_id); + ovs_mutex_unlock(&mutex); }