+ struct odp_header *odp_header = info->userhdr;
+ struct nlattr **a = info->attrs;
+ struct sk_buff *packet;
+ struct sw_flow_key key;
+ struct datapath *dp;
+ struct ethhdr *eth;
+ bool is_frag;
+ int err;
+
+ err = -EINVAL;
+ if (!a[ODP_PACKET_ATTR_PACKET] || !a[ODP_PACKET_ATTR_ACTIONS] ||
+ nla_len(a[ODP_PACKET_ATTR_PACKET]) < ETH_HLEN)
+ goto err;
+
+ err = validate_actions(a[ODP_PACKET_ATTR_ACTIONS]);
+ if (err)
+ goto err;
+
+ packet = skb_clone(skb, GFP_KERNEL);
+ err = -ENOMEM;
+ if (!packet)
+ goto err;
+ packet->data = nla_data(a[ODP_PACKET_ATTR_PACKET]);
+ packet->len = nla_len(a[ODP_PACKET_ATTR_PACKET]);
+
+ skb_reset_mac_header(packet);
+ eth = eth_hdr(packet);
+
+ /* Normally, setting the skb 'protocol' field would be handled by a
+ * call to eth_type_trans(), but it assumes there's a sending
+ * device, which we may not have. */
+ if (ntohs(eth->h_proto) >= 1536)
+ packet->protocol = eth->h_proto;
+ else
+ packet->protocol = htons(ETH_P_802_2);
+
+ /* Initialize OVS_CB (it came from Netlink so might not be zeroed). */
+ memset(OVS_CB(packet), 0, sizeof(struct ovs_skb_cb));
+
+ err = flow_extract(packet, -1, &key, &is_frag);
+ if (err)
+ goto err_kfree_skb;
+
+ rcu_read_lock();
+ dp = get_dp(odp_header->dp_ifindex);
+ err = -ENODEV;
+ if (!dp)
+ goto err_unlock;
+ err = execute_actions(dp, packet, &key,
+ nla_data(a[ODP_PACKET_ATTR_ACTIONS]),
+ nla_len(a[ODP_PACKET_ATTR_ACTIONS]));
+ rcu_read_unlock();
+ return err;
+
+err_unlock:
+ rcu_read_unlock();
+err_kfree_skb:
+ kfree_skb(packet);
+err:
+ return err;
+}
+
+static const struct nla_policy packet_policy[ODP_PACKET_ATTR_MAX + 1] = {
+ [ODP_PACKET_ATTR_PACKET] = { .type = NLA_UNSPEC },
+ [ODP_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },
+};
+
+static struct genl_ops dp_packet_genl_ops[] = {
+ { .cmd = ODP_PACKET_CMD_EXECUTE,
+ .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
+ .policy = packet_policy,
+ .doit = odp_packet_cmd_execute
+ }
+};
+
+static void get_dp_stats(struct datapath *dp, struct odp_stats *stats)
+{
+ int i;
+
+ stats->n_frags = stats->n_hit = stats->n_missed = stats->n_lost = 0;
+ for_each_possible_cpu(i) {
+ const struct dp_stats_percpu *percpu_stats;
+ struct dp_stats_percpu local_stats;
+ unsigned seqcount;
+
+ percpu_stats = per_cpu_ptr(dp->stats_percpu, i);
+
+ do {
+ seqcount = read_seqcount_begin(&percpu_stats->seqlock);
+ local_stats = *percpu_stats;
+ } while (read_seqcount_retry(&percpu_stats->seqlock, seqcount));
+
+ stats->n_frags += local_stats.n_frags;
+ stats->n_hit += local_stats.n_hit;
+ stats->n_missed += local_stats.n_missed;
+ stats->n_lost += local_stats.n_lost;
+ }
+}
+
+/* MTU of the dp pseudo-device: ETH_DATA_LEN or the minimum of the ports.
+ * Called with RTNL lock.
+ */
+int dp_min_mtu(const struct datapath *dp)
+{
+ struct vport *p;
+ int mtu = 0;
+
+ ASSERT_RTNL();
+
+ list_for_each_entry (p, &dp->port_list, node) {
+ int dev_mtu;
+
+ /* Skip any internal ports, since that's what we're trying to
+ * set. */
+ if (is_internal_vport(p))
+ continue;
+
+ dev_mtu = vport_get_mtu(p);
+ if (!dev_mtu)
+ continue;
+ if (!mtu || dev_mtu < mtu)
+ mtu = dev_mtu;
+ }
+
+ return mtu ? mtu : ETH_DATA_LEN;
+}
+
+/* Sets the MTU of all datapath devices to the minimum of the ports
+ * Called with RTNL lock.
+ */
+void set_internal_devs_mtu(const struct datapath *dp)
+{
+ struct vport *p;
+ int mtu;
+
+ ASSERT_RTNL();
+
+ mtu = dp_min_mtu(dp);
+
+ list_for_each_entry (p, &dp->port_list, node) {
+ if (is_internal_vport(p))
+ vport_set_mtu(p, mtu);
+ }
+}
+
+static const struct nla_policy flow_policy[ODP_FLOW_ATTR_MAX + 1] = {
+ [ODP_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
+ [ODP_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
+ [ODP_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
+};
+
+static struct genl_family dp_flow_genl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = sizeof(struct odp_header),
+ .name = ODP_FLOW_FAMILY,
+ .version = 1,
+ .maxattr = ODP_FLOW_ATTR_MAX
+};
+
+static struct genl_multicast_group dp_flow_multicast_group = {
+ .name = ODP_FLOW_MCGROUP
+};
+
+/* Called with genl_lock. */
+static int odp_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
+ struct sk_buff *skb, u32 pid, u32 seq, u32 flags, u8 cmd)
+{
+ const int skb_orig_len = skb->len;
+ const struct sw_flow_actions *sf_acts;