dpif-netdev: Allow different numbers of rx queues for different ports.
[cascardo/ovs.git] / ofproto / ofproto-dpif-ipfix.c
index 3ba6dce..a610c53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
 #include "ofpbuf.h"
 #include "ofproto.h"
 #include "ofproto-dpif.h"
+#include "dp-packet.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "sset.h"
@@ -42,13 +43,17 @@ static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
 /* Cf. IETF RFC 5101 Section 10.3.4. */
 #define IPFIX_DEFAULT_COLLECTOR_PORT 4739
 
+/* Cf. IETF RFC 5881 Setion 8. */
+#define BFD_CONTROL_DEST_PORT        3784
+#define BFD_ECHO_DEST_PORT           3785
+
 /* The standard layer2SegmentId (ID 351) element is included in vDS to send
  * the VxLAN tunnel's VNI. It is 64-bit long, the most significant byte is
  * used to indicate the type of tunnel (0x01 = VxLAN, 0x02 = GRE) and the three
  * least significant bytes hold the value of the layer 2 overlay network
  * segment identifier: a 24-bit VxLAN tunnel's VNI or a 24-bit GRE tunnel's
- * TNI. This is not compatible with GRE-64, as implemented in OVS, as its
- * tunnel IDs are 64-bit.
+ * TNI. This is not compatible with STT, as implemented in OVS, as
+ * its tunnel IDs is 64-bit.
  *
  * Two new enterprise information elements are defined which are similar to
  * laryerSegmentId but support 64-bit IDs:
@@ -63,6 +68,7 @@ enum dpif_ipfix_tunnel_type {
     DPIF_IPFIX_TUNNEL_VXLAN = 0x01,
     DPIF_IPFIX_TUNNEL_GRE = 0x02,
     DPIF_IPFIX_TUNNEL_LISP = 0x03,
+    DPIF_IPFIX_TUNNEL_STT = 0x04,
     DPIF_IPFIX_TUNNEL_IPSEC_GRE = 0x05,
     DPIF_IPFIX_TUNNEL_GENEVE = 0x07,
     NUM_DPIF_IPFIX_TUNNEL
@@ -228,8 +234,8 @@ OVS_PACKED(
 struct ipfix_data_record_flow_key_common {
     ovs_be32 observation_point_id;  /* OBSERVATION_POINT_ID */
     uint8_t flow_direction;  /* FLOW_DIRECTION */
-    uint8_t source_mac_address[ETH_ADDR_LEN]; /* SOURCE_MAC_ADDRESS */
-    uint8_t destination_mac_address[ETH_ADDR_LEN]; /* DESTINATION_MAC_ADDRESS */
+    struct eth_addr source_mac_address; /* SOURCE_MAC_ADDRESS */
+    struct eth_addr destination_mac_address; /* DESTINATION_MAC_ADDRESS */
     ovs_be16 ethernet_type;  /* ETHERNET_TYPE */
     uint8_t ethernet_header_length;  /* ETHERNET_HEADER_LENGTH */
 });
@@ -298,7 +304,7 @@ static uint8_t tunnel_protocol[NUM_DPIF_IPFIX_TUNNEL] = {
     IPPROTO_UDP,    /* DPIF_IPFIX_TUNNEL_VXLAN */
     IPPROTO_GRE,    /* DPIF_IPFIX_TUNNEL_GRE */
     IPPROTO_UDP,    /* DPIF_IPFIX_TUNNEL_LISP*/
-    0          ,    /* reserved */
+    IPPROTO_TCP,    /* DPIF_IPFIX_TUNNEL_STT*/
     IPPROTO_GRE,    /* DPIF_IPFIX_TUNNEL_IPSEC_GRE */
     0          ,    /* reserved */
     IPPROTO_UDP,    /* DPIF_IPFIX_TUNNEL_GENEVE*/
@@ -350,8 +356,9 @@ BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_aggregated_ip) == 32);
 /*
  * support tunnel key for:
  * VxLAN: 24-bit VIN,
- * GRE: 32- or 64-bit key,
+ * GRE: 32-bit key,
  * LISP: 24-bit instance ID
+ * STT: 64-bit key
  */
 #define MAX_TUNNEL_KEY_LEN 8
 
@@ -585,18 +592,10 @@ dpif_ipfix_add_tunnel_port(struct dpif_ipfix *di, struct ofport *ofport,
         /* 32-bit key gre */
         dip->tunnel_type = DPIF_IPFIX_TUNNEL_GRE;
         dip->tunnel_key_length = 4;
-    } else if (strcmp(type, "gre64") == 0) {
-        /* 64-bit key gre */
-        dip->tunnel_type = DPIF_IPFIX_TUNNEL_GRE;
-        dip->tunnel_key_length = 8;
     } else if (strcmp(type, "ipsec_gre") == 0) {
         /* 32-bit key ipsec_gre */
         dip->tunnel_type = DPIF_IPFIX_TUNNEL_IPSEC_GRE;
         dip->tunnel_key_length = 4;
-    } else if (strcmp(type, "ipsec_gre64") == 0) {
-        /* 64-bit key ipsec_gre */
-        dip->tunnel_type = DPIF_IPFIX_TUNNEL_IPSEC_GRE;
-        dip->tunnel_key_length = 8;
     } else if (strcmp(type, "vxlan") == 0) {
         dip->tunnel_type = DPIF_IPFIX_TUNNEL_VXLAN;
         dip->tunnel_key_length = 3;
@@ -606,6 +605,9 @@ dpif_ipfix_add_tunnel_port(struct dpif_ipfix *di, struct ofport *ofport,
     } 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;
@@ -970,11 +972,11 @@ dpif_ipfix_unref(struct dpif_ipfix *di) OVS_EXCLUDED(mutex)
 
 static void
 ipfix_init_header(uint32_t export_time_sec, uint32_t seq_number,
-                  uint32_t obs_domain_id, struct ofpbuf *msg)
+                  uint32_t obs_domain_id, struct dp_packet *msg)
 {
     struct ipfix_header *hdr;
 
-    hdr = ofpbuf_put_zeros(msg, sizeof *hdr);
+    hdr = dp_packet_put_zeros(msg, sizeof *hdr);
     hdr->version = htons(IPFIX_VERSION);
     hdr->length = htons(sizeof *hdr);  /* Updated in ipfix_send_msg. */
     hdr->export_time = htonl(export_time_sec);
@@ -983,16 +985,16 @@ ipfix_init_header(uint32_t export_time_sec, uint32_t seq_number,
 }
 
 static void
-ipfix_send_msg(const struct collectors *collectors, struct ofpbuf *msg)
+ipfix_send_msg(const struct collectors *collectors, struct dp_packet *msg)
 {
     struct ipfix_header *hdr;
 
     /* Adjust the length in the header. */
-    hdr = ofpbuf_data(msg);
-    hdr->length = htons(ofpbuf_size(msg));
+    hdr = dp_packet_data(msg);
+    hdr->length = htons(dp_packet_size(msg));
 
-    collectors_send(collectors, ofpbuf_data(msg), ofpbuf_size(msg));
-    ofpbuf_set_size(msg, 0);
+    collectors_send(collectors, dp_packet_data(msg), dp_packet_size(msg));
+    dp_packet_set_size(msg, 0);
 }
 
 static uint16_t
@@ -1011,7 +1013,7 @@ static void
 ipfix_define_template_entity(enum ipfix_entity_id id,
                              enum ipfix_entity_size size,
                              enum ipfix_entity_enterprise enterprise,
-                             struct ofpbuf *msg)
+                             struct dp_packet *msg)
 {
     struct ipfix_template_field_specifier *field;
     size_t field_size;
@@ -1022,7 +1024,7 @@ ipfix_define_template_entity(enum ipfix_entity_id id,
         /* No enterprise number */
         field_size = sizeof *field - sizeof(ovs_be32);
     }
-    field = ofpbuf_put_zeros(msg, field_size);
+    field = dp_packet_put_zeros(msg, field_size);
     field->element_id = htons(id);
     if (size) {
         field->field_length = htons(size);
@@ -1039,7 +1041,7 @@ ipfix_define_template_entity(enum ipfix_entity_id id,
 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,
-                             struct ofpbuf *msg)
+                             struct dp_packet *msg)
 {
     uint16_t count = 0;
 
@@ -1134,34 +1136,34 @@ ipfix_define_template_fields(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 l3,
 static void
 ipfix_init_template_msg(void *msg_stub, uint32_t export_time_sec,
                         uint32_t seq_number, uint32_t obs_domain_id,
-                        struct ofpbuf *msg, size_t *set_hdr_offset)
+                        struct dp_packet *msg, size_t *set_hdr_offset)
 {
     struct ipfix_set_header *set_hdr;
 
-    ofpbuf_use_stub(msg, msg_stub, sizeof msg_stub);
+    dp_packet_use_stub(msg, msg_stub, sizeof msg_stub);
 
     ipfix_init_header(export_time_sec, seq_number, obs_domain_id, msg);
-    *set_hdr_offset = ofpbuf_size(msg);
+    *set_hdr_offset = dp_packet_size(msg);
 
     /* Add a Template Set. */
-    set_hdr = ofpbuf_put_zeros(msg, sizeof *set_hdr);
+    set_hdr = dp_packet_put_zeros(msg, sizeof *set_hdr);
     set_hdr->set_id = htons(IPFIX_SET_ID_TEMPLATE);
 }
 
 static void
 ipfix_send_template_msg(const struct collectors *collectors,
-                        struct ofpbuf *msg, size_t set_hdr_offset)
+                        struct dp_packet *msg, size_t set_hdr_offset)
 {
     struct ipfix_set_header *set_hdr;
 
     /* Send template message. */
     set_hdr = (struct ipfix_set_header*)
-              ((uint8_t*)ofpbuf_data(msg) + set_hdr_offset);
-    set_hdr->length = htons(ofpbuf_size(msg) - set_hdr_offset);
+              ((uint8_t*)dp_packet_data(msg) + set_hdr_offset);
+    set_hdr->length = htons(dp_packet_size(msg) - set_hdr_offset);
 
     ipfix_send_msg(collectors, msg);
 
-    ofpbuf_uninit(msg);
+    dp_packet_uninit(msg);
 }
 
 static void
@@ -1169,7 +1171,7 @@ ipfix_send_template_msgs(struct dpif_ipfix_exporter *exporter,
                          uint32_t export_time_sec, uint32_t obs_domain_id)
 {
     uint64_t msg_stub[DIV_ROUND_UP(MAX_MESSAGE_LEN, 8)];
-    struct ofpbuf msg;
+    struct dp_packet msg;
     size_t set_hdr_offset, tmpl_hdr_offset;
     struct ipfix_template_record_header *tmpl_hdr;
     uint16_t field_count;
@@ -1195,7 +1197,7 @@ ipfix_send_template_msgs(struct dpif_ipfix_exporter *exporter,
                      * And then reinitialize the msg to construct a new
                      * packet for the following templates.
                      */
-                    if (ofpbuf_size(&msg) >= MAX_MESSAGE_LEN) {
+                    if (dp_packet_size(&msg) >= MAX_MESSAGE_LEN) {
                         /* Send template message. */
                         ipfix_send_template_msg(exporter->collectors,
                                                 &msg, set_hdr_offset);
@@ -1207,14 +1209,14 @@ ipfix_send_template_msgs(struct dpif_ipfix_exporter *exporter,
                                                 &set_hdr_offset);
                     }
 
-                    tmpl_hdr_offset = ofpbuf_size(&msg);
-                    tmpl_hdr = ofpbuf_put_zeros(&msg, sizeof *tmpl_hdr);
+                    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));
                     field_count =
                         ipfix_define_template_fields(l2, l3, l4, tunnel, &msg);
                     tmpl_hdr = (struct ipfix_template_record_header*)
-                        ((uint8_t*)ofpbuf_data(&msg) + tmpl_hdr_offset);
+                        ((uint8_t*)dp_packet_data(&msg) + tmpl_hdr_offset);
                     tmpl_hdr->field_count = htons(field_count);
                 }
             }
@@ -1358,14 +1360,14 @@ ipfix_cache_update(struct dpif_ipfix_exporter *exporter,
 
 static void
 ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
-                       const struct ofpbuf *packet, const struct flow *flow,
+                       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,
                        const struct dpif_ipfix_port *tunnel_port,
                        const struct flow_tnl *tunnel_key)
 {
     struct ipfix_flow_key *flow_key;
-    struct ofpbuf msg;
+    struct dp_packet msg;
     enum ipfix_proto_l2 l2;
     enum ipfix_proto_l3 l3;
     enum ipfix_proto_l4 l4;
@@ -1374,8 +1376,8 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
     uint16_t ethernet_total_length;
 
     flow_key = &entry->flow_key;
-    ofpbuf_use_stack(&msg, flow_key->flow_key_msg_part,
-                     sizeof flow_key->flow_key_msg_part);
+    dp_packet_use_stub(&msg, flow_key->flow_key_msg_part,
+                       sizeof flow_key->flow_key_msg_part);
 
     /* Choose the right template ID matching the protocols in the
      * sampled packet. */
@@ -1430,20 +1432,18 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
 
     ethernet_header_length = (l2 == IPFIX_PROTO_L2_VLAN)
         ? VLAN_ETH_HEADER_LEN : ETH_HEADER_LEN;
-    ethernet_total_length = ofpbuf_size(packet);
+    ethernet_total_length = dp_packet_size(packet);
 
     /* Common Ethernet entities. */
     {
         struct ipfix_data_record_flow_key_common *data_common;
 
-        data_common = ofpbuf_put_zeros(&msg, sizeof *data_common);
+        data_common = dp_packet_put_zeros(&msg, sizeof *data_common);
         data_common->observation_point_id = htonl(obs_point_id);
         data_common->flow_direction =
             (output_odp_port == ODPP_NONE) ? INGRESS_FLOW : EGRESS_FLOW;
-        memcpy(data_common->source_mac_address, flow->dl_src,
-               sizeof flow->dl_src);
-        memcpy(data_common->destination_mac_address, flow->dl_dst,
-               sizeof flow->dl_dst);
+        data_common->source_mac_address = flow->dl_src;
+        data_common->destination_mac_address = flow->dl_dst;
         data_common->ethernet_type = flow->dl_type;
         data_common->ethernet_header_length = ethernet_header_length;
     }
@@ -1453,7 +1453,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
         uint16_t vlan_id = vlan_tci_to_vid(flow->vlan_tci);
         uint8_t priority = vlan_tci_to_pcp(flow->vlan_tci);
 
-        data_vlan = ofpbuf_put_zeros(&msg, sizeof *data_vlan);
+        data_vlan = dp_packet_put_zeros(&msg, sizeof *data_vlan);
         data_vlan->vlan_id = htons(vlan_id);
         data_vlan->dot1q_vlan_id = htons(vlan_id);
         data_vlan->dot1q_priority = priority;
@@ -1462,7 +1462,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
     if (l3 != IPFIX_PROTO_L3_UNKNOWN) {
         struct ipfix_data_record_flow_key_ip *data_ip;
 
-        data_ip = ofpbuf_put_zeros(&msg, sizeof *data_ip);
+        data_ip = dp_packet_put_zeros(&msg, sizeof *data_ip);
         data_ip->ip_version = (l3 == IPFIX_PROTO_L3_IPV4) ? 4 : 6;
         data_ip->ip_ttl = flow->nw_ttl;
         data_ip->protocol_identifier = flow->nw_proto;
@@ -1473,13 +1473,13 @@ 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 = dp_packet_put_zeros(&msg, sizeof *data_ipv4);
             data_ipv4->source_ipv4_address = flow->nw_src;
             data_ipv4->destination_ipv4_address = flow->nw_dst;
         } else {  /* l3 == IPFIX_PROTO_L3_IPV6 */
             struct ipfix_data_record_flow_key_ipv6 *data_ipv6;
 
-            data_ipv6 = ofpbuf_put_zeros(&msg, sizeof *data_ipv6);
+            data_ipv6 = dp_packet_put_zeros(&msg, sizeof *data_ipv6);
             memcpy(data_ipv6->source_ipv6_address, &flow->ipv6_src,
                    sizeof flow->ipv6_src);
             memcpy(data_ipv6->destination_ipv6_address, &flow->ipv6_dst,
@@ -1491,13 +1491,13 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
     if (l4 == IPFIX_PROTO_L4_TCP_UDP_SCTP) {
         struct ipfix_data_record_flow_key_transport *data_transport;
 
-        data_transport = ofpbuf_put_zeros(&msg, sizeof *data_transport);
+        data_transport = dp_packet_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 = dp_packet_put_zeros(&msg, sizeof *data_icmp);
         data_icmp->icmp_type = ntohs(flow->tp_src) & 0xff;
         data_icmp->icmp_code = ntohs(flow->tp_dst) & 0xff;
     }
@@ -1506,7 +1506,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
         struct ipfix_data_record_flow_key_tunnel *data_tunnel;
         const uint8_t *tun_id;
 
-        data_tunnel = ofpbuf_put_zeros(&msg, sizeof *data_tunnel +
+        data_tunnel = dp_packet_put_zeros(&msg, sizeof *data_tunnel +
                                              tunnel_port->tunnel_key_length);
         data_tunnel->tunnel_source_ipv4_address = tunnel_key->ip_src;
         data_tunnel->tunnel_destination_ipv4_address = tunnel_key->ip_dst;
@@ -1532,7 +1532,7 @@ ipfix_cache_entry_init(struct ipfix_flow_cache_entry *entry,
                tunnel_port->tunnel_key_length);
     }
 
-    flow_key->flow_key_msg_part_size = ofpbuf_size(&msg);
+    flow_key->flow_key_msg_part_size = dp_packet_size(&msg);
 
     {
         struct timeval now;
@@ -1578,20 +1578,20 @@ static void
 ipfix_put_data_set(uint32_t export_time_sec,
                    struct ipfix_flow_cache_entry *entry,
                    enum ipfix_flow_end_reason flow_end_reason,
-                   struct ofpbuf *msg)
+                   struct dp_packet *msg)
 {
     size_t set_hdr_offset;
     struct ipfix_set_header *set_hdr;
 
-    set_hdr_offset = ofpbuf_size(msg);
+    set_hdr_offset = dp_packet_size(msg);
 
     /* Put a Data Set. */
-    set_hdr = ofpbuf_put_zeros(msg, sizeof *set_hdr);
+    set_hdr = dp_packet_put_zeros(msg, sizeof *set_hdr);
     set_hdr->set_id = htons(entry->flow_key.template_id);
 
     /* Copy the flow key part of the data record. */
 
-    ofpbuf_put(msg, entry->flow_key.flow_key_msg_part,
+    dp_packet_put(msg, entry->flow_key.flow_key_msg_part,
                entry->flow_key.flow_key_msg_part_size);
 
     /* Put the non-key part of the data record. */
@@ -1609,7 +1609,7 @@ ipfix_put_data_set(uint32_t export_time_sec,
         flow_end_delta_usec = export_time_usec
             - entry->flow_end_timestamp_usec;
 
-        data_aggregated_common = ofpbuf_put_zeros(
+        data_aggregated_common = dp_packet_put_zeros(
             msg, sizeof *data_aggregated_common);
         data_aggregated_common->flow_start_delta_microseconds = htonl(
             flow_start_delta_usec);
@@ -1625,7 +1625,7 @@ ipfix_put_data_set(uint32_t export_time_sec,
     if (entry->octet_delta_sum_of_squares) {  /* IP packet. */
         struct ipfix_data_record_aggregated_ip *data_aggregated_ip;
 
-        data_aggregated_ip = ofpbuf_put_zeros(
+        data_aggregated_ip = dp_packet_put_zeros(
             msg, sizeof *data_aggregated_ip);
         data_aggregated_ip->octet_delta_count = htonll(
             entry->octet_delta_count);
@@ -1637,8 +1637,8 @@ ipfix_put_data_set(uint32_t export_time_sec,
             entry->maximum_ip_total_length);
     }
 
-    set_hdr = (struct ipfix_set_header*)((uint8_t*)ofpbuf_data(msg) + set_hdr_offset);
-    set_hdr->length = htons(ofpbuf_size(msg) - set_hdr_offset);
+    set_hdr = (struct ipfix_set_header*)((uint8_t*)dp_packet_data(msg) + set_hdr_offset);
+    set_hdr->length = htons(dp_packet_size(msg) - set_hdr_offset);
 }
 
 /* Send an IPFIX message with a single data record. */
@@ -1649,20 +1649,20 @@ ipfix_send_data_msg(struct dpif_ipfix_exporter *exporter,
                     enum ipfix_flow_end_reason flow_end_reason)
 {
     uint64_t msg_stub[DIV_ROUND_UP(MAX_MESSAGE_LEN, 8)];
-    struct ofpbuf msg;
-    ofpbuf_use_stub(&msg, msg_stub, sizeof msg_stub);
+    struct dp_packet msg;
+    dp_packet_use_stub(&msg, msg_stub, sizeof msg_stub);
 
     ipfix_init_header(export_time_sec, exporter->seq_number++,
                       entry->flow_key.obs_domain_id, &msg);
     ipfix_put_data_set(export_time_sec, entry, flow_end_reason, &msg);
     ipfix_send_msg(exporter->collectors, &msg);
 
-    ofpbuf_uninit(&msg);
+    dp_packet_uninit(&msg);
 }
 
 static void
 dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter,
-                  const struct ofpbuf *packet, const struct flow *flow,
+                  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,
                   const struct dpif_ipfix_port *tunnel_port,
@@ -1678,8 +1678,14 @@ dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter,
     ipfix_cache_update(exporter, entry);
 }
 
+static bool
+bridge_exporter_enabled(struct dpif_ipfix *di)
+{
+    return di->bridge_exporter.probability > 0;
+}
+
 void
-dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct ofpbuf *packet,
+dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct dp_packet *packet,
                          const struct flow *flow,
                          odp_port_t input_odp_port, odp_port_t output_odp_port,
                          const struct flow_tnl *output_tunnel_key)
@@ -1690,6 +1696,27 @@ dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct ofpbuf *packet,
     struct dpif_ipfix_port * tunnel_port = NULL;
 
     ovs_mutex_lock(&mutex);
+    if (!bridge_exporter_enabled(di)) {
+        ovs_mutex_unlock(&mutex);
+        return;
+    }
+
+    /* Skip BFD packets:
+     * Bidirectional Forwarding Detection(BFD) packets are for monitoring
+     * the tunnel link status and consumed by ovs itself. No need to
+     * smaple them.
+     * CF  IETF RFC 5881, BFD control packet is the UDP packet with
+     * destination port 3784, and BFD echo packet is the UDP packet with
+     * destination port 3785.
+     */
+    if (is_ip_any(flow) &&
+        flow->nw_proto == IPPROTO_UDP &&
+        (flow->tp_dst == htons(BFD_CONTROL_DEST_PORT) ||
+         flow->tp_dst == htons(BFD_ECHO_DEST_PORT))) {
+        ovs_mutex_unlock(&mutex);
+        return;
+    }
+
     /* Use the sampling probability as an approximation of the number
      * of matched packets. */
     packet_delta_count = UINT32_MAX / di->bridge_exporter.probability;
@@ -1705,6 +1732,7 @@ dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct ofpbuf *packet,
             tunnel_port = dpif_ipfix_find_port(di, output_odp_port);
         }
     }
+
     dpif_ipfix_sample(&di->bridge_exporter.exporter, packet, flow,
                       packet_delta_count,
                       di->bridge_exporter.options->obs_domain_id,
@@ -1714,7 +1742,7 @@ dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct ofpbuf *packet,
 }
 
 void
-dpif_ipfix_flow_sample(struct dpif_ipfix *di, const struct ofpbuf *packet,
+dpif_ipfix_flow_sample(struct dpif_ipfix *di, const struct dp_packet *packet,
                        const struct flow *flow, uint32_t collector_set_id,
                        uint16_t probability, uint32_t obs_domain_id,
                        uint32_t obs_point_id) OVS_EXCLUDED(mutex)
@@ -1826,7 +1854,7 @@ dpif_ipfix_run(struct dpif_ipfix *di) OVS_EXCLUDED(mutex)
 
     ovs_mutex_lock(&mutex);
     get_export_time_now(&export_time_usec, &export_time_sec);
-    if (di->bridge_exporter.probability > 0) {  /* Bridge exporter enabled. */
+    if (bridge_exporter_enabled(di)) {
       dpif_ipfix_cache_expire(
           &di->bridge_exporter.exporter, false, export_time_usec,
           export_time_sec);
@@ -1846,7 +1874,7 @@ dpif_ipfix_wait(struct dpif_ipfix *di) OVS_EXCLUDED(mutex)
     struct dpif_ipfix_flow_exporter_map_node *flow_exporter_node;
 
     ovs_mutex_lock(&mutex);
-    if (di->bridge_exporter.probability > 0) {  /* Bridge exporter enabled. */
+    if (bridge_exporter_enabled(di)) {
         if (ipfix_cache_next_timeout_msec(
                 &di->bridge_exporter.exporter, &next_timeout_msec)) {
             poll_timer_wait_until(next_timeout_msec);