+static struct dpif_ipfix_port *
+dpif_ipfix_find_port(const struct dpif_ipfix *di,
+ odp_port_t odp_port) OVS_REQUIRES(mutex)
+{
+ struct dpif_ipfix_port *dip;
+
+ HMAP_FOR_EACH_IN_BUCKET (dip, hmap_node, hash_odp_port(odp_port),
+ &di->tunnel_ports) {
+ if (dip->odp_port == odp_port) {
+ return dip;
+ }
+ }
+ return NULL;
+}
+
+static void
+dpif_ipfix_del_port(struct dpif_ipfix *di,
+ struct dpif_ipfix_port *dip)
+ OVS_REQUIRES(mutex)
+{
+ hmap_remove(&di->tunnel_ports, &dip->hmap_node);
+ free(dip);
+}
+
+void
+dpif_ipfix_add_tunnel_port(struct dpif_ipfix *di, struct ofport *ofport,
+ odp_port_t odp_port) OVS_EXCLUDED(mutex)
+{
+ struct dpif_ipfix_port *dip;
+ const char *type;
+
+ ovs_mutex_lock(&mutex);
+ dip = dpif_ipfix_find_port(di, odp_port);
+ if (dip) {
+ dpif_ipfix_del_port(di, dip);
+ }
+
+ type = netdev_get_type(ofport->netdev);
+ if (type == NULL) {
+ goto out;
+ }
+
+ /* Add to table of tunnel 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, "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, "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));
+
+out:
+ ovs_mutex_unlock(&mutex);
+}
+
+void
+dpif_ipfix_del_tunnel_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);
+ }
+ ovs_mutex_unlock(&mutex);
+}
+
+bool
+dpif_ipfix_get_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);
+ ovs_mutex_unlock(&mutex);
+ return dip != NULL;
+}
+