+ xpthread_create(&f->thread, NULL, dp_forwarder_main, f);
+ }
+}
+\f
+static void
+dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow,
+ const struct ofpbuf *packet)
+ OVS_REQUIRES(netdev_flow->mutex)
+{
+ netdev_flow->used = time_msec();
+ netdev_flow->packet_count++;
+ netdev_flow->byte_count += packet->size;
+ netdev_flow->tcp_flags |= packet_get_tcp_flags(packet, &netdev_flow->flow);
+}
+
+static void
+dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
+ struct pkt_metadata *md)
+ OVS_REQ_RDLOCK(dp->port_rwlock)
+{
+ struct dp_netdev_flow *netdev_flow;
+ struct flow key;
+
+ if (packet->size < ETH_HEADER_LEN) {
+ return;
+ }
+ flow_extract(packet, md->skb_priority, md->pkt_mark, &md->tunnel,
+ (union flow_in_port *)&md->in_port, &key);
+ netdev_flow = dp_netdev_lookup_flow(dp, &key);
+ if (netdev_flow) {
+ struct dp_netdev_actions *actions;
+
+ ovs_mutex_lock(&netdev_flow->mutex);
+ dp_netdev_flow_used(netdev_flow, packet);
+ actions = dp_netdev_actions_ref(netdev_flow->actions);
+ ovs_mutex_unlock(&netdev_flow->mutex);
+
+ dp_netdev_execute_actions(dp, &key, packet, md,
+ actions->actions, actions->size);
+ dp_netdev_actions_unref(actions);
+ ovsthread_counter_inc(dp->n_hit, 1);
+ } else {
+ ovsthread_counter_inc(dp->n_missed, 1);
+ dp_netdev_output_userspace(dp, packet, DPIF_UC_MISS, &key, NULL);