X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-ipfix.c;h=a5298847c6d1213d2d75d693b2507b17ee20c3da;hb=813a8dd336d74465a27c05cfda124e2c91408a81;hp=55544cc660112ef91f14ccb0be62cfdc0dd41a6c;hpb=c5f81b20da9bbf0ac406a88718597a4e84729a98;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c index 55544cc66..a5298847c 100644 --- a/ofproto/ofproto-dpif-ipfix.c +++ b/ofproto/ofproto-dpif-ipfix.c @@ -70,7 +70,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_node. */ - atomic_int ref_cnt; + struct ovs_refcount ref_cnt; }; #define IPFIX_VERSION 0x000a @@ -117,7 +117,8 @@ enum ipfix_proto_l3 { }; enum ipfix_proto_l4 { IPFIX_PROTO_L4_UNKNOWN = 0, - IPFIX_PROTO_L4_TCP_UDP, + IPFIX_PROTO_L4_TCP_UDP_SCTP, + IPFIX_PROTO_L4_ICMP, NUM_IPFIX_PROTO_L4 }; @@ -200,13 +201,21 @@ struct ipfix_data_record_flow_key_ipv6 { }); BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_flow_key_ipv6) == 36); -/* Part of data record flow key for TCP/UDP entities. */ +/* Part of data record flow key for TCP/UDP/SCTP entities. */ OVS_PACKED( -struct ipfix_data_record_flow_key_tcpudp { +struct ipfix_data_record_flow_key_transport { ovs_be16 source_transport_port; /* SOURCE_TRANSPORT_PORT */ ovs_be16 destination_transport_port; /* DESTINATION_TRANSPORT_PORT */ }); -BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_flow_key_tcpudp) == 4); +BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_flow_key_transport) == 4); + +/* Part of data record flow key for ICMP entities. */ +OVS_PACKED( +struct ipfix_data_record_flow_key_icmp { + uint8_t icmp_type; /* ICMP_TYPE_IPV4 / ICMP_TYPE_IPV6 */ + uint8_t icmp_code; /* ICMP_CODE_IPV4 / ICMP_CODE_IPV6 */ +}); +BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_flow_key_icmp) == 2); /* Cf. IETF RFC 5102 Section 5.11.3. */ enum ipfix_flow_end_reason { @@ -231,18 +240,21 @@ BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_aggregated_common) == 25); /* Part of data record for IP aggregated elements. */ OVS_PACKED( struct ipfix_data_record_aggregated_ip { + ovs_be64 octet_delta_count; /* OCTET_DELTA_COUNT */ ovs_be64 octet_delta_sum_of_squares; /* OCTET_DELTA_SUM_OF_SQUARES */ ovs_be64 minimum_ip_total_length; /* MINIMUM_IP_TOTAL_LENGTH */ ovs_be64 maximum_ip_total_length; /* MAXIMUM_IP_TOTAL_LENGTH */ }); -BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_aggregated_ip) == 24); +BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_aggregated_ip) == 32); -#define MAX_FLOW_KEY_LEN \ - (sizeof(struct ipfix_data_record_flow_key_common) \ - + sizeof(struct ipfix_data_record_flow_key_vlan) \ - + sizeof(struct ipfix_data_record_flow_key_ip) \ - + sizeof(struct ipfix_data_record_flow_key_ipv6) \ - + sizeof(struct ipfix_data_record_flow_key_tcpudp)) +#define MAX_FLOW_KEY_LEN \ + (sizeof(struct ipfix_data_record_flow_key_common) \ + + sizeof(struct ipfix_data_record_flow_key_vlan) \ + + sizeof(struct ipfix_data_record_flow_key_ip) \ + + MAX(sizeof(struct ipfix_data_record_flow_key_ipv4), \ + sizeof(struct ipfix_data_record_flow_key_ipv6)) \ + + MAX(sizeof(struct ipfix_data_record_flow_key_icmp), \ + sizeof(struct ipfix_data_record_flow_key_transport))) #define MAX_DATA_RECORD_LEN \ (MAX_FLOW_KEY_LEN \ @@ -280,6 +292,7 @@ struct ipfix_flow_cache_entry { uint64_t flow_end_timestamp_usec; uint64_t packet_delta_count; uint64_t layer2_octet_delta_count; + uint64_t octet_delta_count; uint64_t octet_delta_sum_of_squares; /* 0 if not IP. */ uint16_t minimum_ip_total_length; /* 0 if not IP. */ uint16_t maximum_ip_total_length; /* 0 if not IP. */ @@ -639,7 +652,7 @@ dpif_ipfix_create(void) di = xzalloc(sizeof *di); dpif_ipfix_bridge_exporter_init(&di->bridge_exporter); hmap_init(&di->flow_exporter_map); - atomic_init(&di->ref_cnt, 1); + ovs_refcount_init(&di->ref_cnt); return di; } @@ -648,9 +661,7 @@ dpif_ipfix_ref(const struct dpif_ipfix *di_) { struct dpif_ipfix *di = CONST_CAST(struct dpif_ipfix *, di_); if (di) { - int orig; - atomic_add(&di->ref_cnt, 1, &orig); - ovs_assert(orig > 0); + ovs_refcount_ref(&di->ref_cnt); } return di; } @@ -683,20 +694,12 @@ dpif_ipfix_clear(struct dpif_ipfix *di) OVS_REQUIRES(mutex) void dpif_ipfix_unref(struct dpif_ipfix *di) OVS_EXCLUDED(mutex) { - int orig; - - if (!di) { - return; - } - - atomic_sub(&di->ref_cnt, 1, &orig); - ovs_assert(orig > 0); - if (orig == 1) { + if (di && ovs_refcount_unref(&di->ref_cnt) == 1) { ovs_mutex_lock(&mutex); dpif_ipfix_clear(di); dpif_ipfix_bridge_exporter_destroy(&di->bridge_exporter); hmap_destroy(&di->flow_exporter_map); - atomic_destroy(&di->ref_cnt); + ovs_refcount_destroy(&di->ref_cnt); free(di); ovs_mutex_unlock(&mutex); } @@ -791,18 +794,27 @@ ipfix_define_template_fields(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 l3, if (l3 == IPFIX_PROTO_L3_IPV4) { DEF(SOURCE_IPV4_ADDRESS); DEF(DESTINATION_IPV4_ADDRESS); + if (l4 == IPFIX_PROTO_L4_TCP_UDP_SCTP) { + DEF(SOURCE_TRANSPORT_PORT); + DEF(DESTINATION_TRANSPORT_PORT); + } else if (l4 == IPFIX_PROTO_L4_ICMP) { + DEF(ICMP_TYPE_IPV4); + DEF(ICMP_CODE_IPV4); + } } else { /* l3 == IPFIX_PROTO_L3_IPV6 */ DEF(SOURCE_IPV6_ADDRESS); DEF(DESTINATION_IPV6_ADDRESS); DEF(FLOW_LABEL_IPV6); + if (l4 == IPFIX_PROTO_L4_TCP_UDP_SCTP) { + DEF(SOURCE_TRANSPORT_PORT); + DEF(DESTINATION_TRANSPORT_PORT); + } else if (l4 == IPFIX_PROTO_L4_ICMP) { + DEF(ICMP_TYPE_IPV6); + DEF(ICMP_CODE_IPV6); + } } } - if (l4 != IPFIX_PROTO_L4_UNKNOWN) { - DEF(SOURCE_TRANSPORT_PORT); - DEF(DESTINATION_TRANSPORT_PORT); - } - /* 2. Flow aggregated data. */ DEF(FLOW_START_DELTA_MICROSECONDS); @@ -812,6 +824,7 @@ ipfix_define_template_fields(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 l3, DEF(FLOW_END_REASON); if (l3 != IPFIX_PROTO_L3_UNKNOWN) { + DEF(OCTET_DELTA_COUNT); DEF(OCTET_DELTA_SUM_OF_SQUARES); DEF(MINIMUM_IP_TOTAL_LENGTH); DEF(MAXIMUM_IP_TOTAL_LENGTH); @@ -956,6 +969,7 @@ ipfix_cache_aggregate_entries(struct ipfix_flow_cache_entry *from_entry, to_entry->packet_delta_count += from_entry->packet_delta_count; to_entry->layer2_octet_delta_count += from_entry->layer2_octet_delta_count; + to_entry->octet_delta_count += from_entry->octet_delta_count; to_entry->octet_delta_sum_of_squares += from_entry->octet_delta_sum_of_squares; @@ -1029,22 +1043,37 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry, switch(ntohs(flow->dl_type)) { case ETH_TYPE_IP: l3 = IPFIX_PROTO_L3_IPV4; + switch(flow->nw_proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_SCTP: + l4 = IPFIX_PROTO_L4_TCP_UDP_SCTP; + break; + case IPPROTO_ICMP: + l4 = IPFIX_PROTO_L4_ICMP; + break; + default: + l4 = IPFIX_PROTO_L4_UNKNOWN; + } break; case ETH_TYPE_IPV6: l3 = IPFIX_PROTO_L3_IPV6; - break; - default: - l3 = IPFIX_PROTO_L3_UNKNOWN; - } - - l4 = IPFIX_PROTO_L4_UNKNOWN; - if (l3 != IPFIX_PROTO_L3_UNKNOWN) { switch(flow->nw_proto) { - case IPPROTO_TCP: /* TCP */ - case IPPROTO_UDP: /* UDP */ - l4 = IPFIX_PROTO_L4_TCP_UDP; + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_SCTP: + l4 = IPFIX_PROTO_L4_TCP_UDP_SCTP; + break; + case IPPROTO_ICMPV6: + l4 = IPFIX_PROTO_L4_ICMP; break; + default: + l4 = IPFIX_PROTO_L4_UNKNOWN; } + break; + default: + l3 = IPFIX_PROTO_L3_UNKNOWN; + l4 = IPFIX_PROTO_L4_UNKNOWN; } flow_key->obs_domain_id = obs_domain_id; @@ -1096,6 +1125,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry, if (l3 == IPFIX_PROTO_L3_IPV4) { struct ipfix_data_record_flow_key_ipv4 *data_ipv4; + data_ipv4 = ofpbuf_put_zeros(&msg, sizeof *data_ipv4); data_ipv4->source_ipv4_address = flow->nw_src; data_ipv4->destination_ipv4_address = flow->nw_dst; @@ -1111,12 +1141,18 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry, } } - if (l4 != IPFIX_PROTO_L4_UNKNOWN) { - struct ipfix_data_record_flow_key_tcpudp *data_tcpudp; + if (l4 == IPFIX_PROTO_L4_TCP_UDP_SCTP) { + struct ipfix_data_record_flow_key_transport *data_transport; - data_tcpudp = ofpbuf_put_zeros(&msg, sizeof *data_tcpudp); - data_tcpudp->source_transport_port = flow->tp_src; - data_tcpudp->destination_transport_port = flow->tp_dst; + data_transport = ofpbuf_put_zeros(&msg, sizeof *data_transport); + data_transport->source_transport_port = flow->tp_src; + data_transport->destination_transport_port = flow->tp_dst; + } else if (l4 == IPFIX_PROTO_L4_ICMP) { + struct ipfix_data_record_flow_key_icmp *data_icmp; + + data_icmp = ofpbuf_put_zeros(&msg, sizeof *data_icmp); + data_icmp->icmp_type = ntohs(flow->tp_src) & 0xff; + data_icmp->icmp_code = ntohs(flow->tp_dst) & 0xff; } flow_key->flow_key_msg_part_size = msg.size; @@ -1140,9 +1176,15 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry, if (l3 != IPFIX_PROTO_L3_UNKNOWN) { uint16_t ip_total_length = ethernet_total_length - ethernet_header_length; + uint64_t octet_delta_count; + + /* Calculate the total matched octet count by considering as + * an approximation that all matched packets have the same + * length. */ + octet_delta_count = packet_delta_count * ip_total_length; - entry->octet_delta_sum_of_squares = - packet_delta_count * ip_total_length * ip_total_length; + entry->octet_delta_count = octet_delta_count; + entry->octet_delta_sum_of_squares = octet_delta_count * ip_total_length; entry->minimum_ip_total_length = ip_total_length; entry->maximum_ip_total_length = ip_total_length; } else { @@ -1208,6 +1250,8 @@ ipfix_put_data_set(uint32_t export_time_sec, data_aggregated_ip = ofpbuf_put_zeros( msg, sizeof *data_aggregated_ip); + data_aggregated_ip->octet_delta_count = htonll( + entry->octet_delta_count); data_aggregated_ip->octet_delta_sum_of_squares = htonll( entry->octet_delta_sum_of_squares); data_aggregated_ip->minimum_ip_total_length = htonll(