aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdev_features.h8
-rw-r--r--include/uapi/linux/openvswitch.h13
-rw-r--r--net/openvswitch/actions.c50
-rw-r--r--net/openvswitch/datapath.c26
-rw-r--r--net/openvswitch/vport-internal_dev.c5
-rw-r--r--net/openvswitch/vport.c101
-rw-r--r--net/openvswitch/vport.h27
7 files changed, 201 insertions, 29 deletions
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index d99800cbdcf3..dcfdecbfa0b7 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -176,4 +176,12 @@ enum {
176 NETIF_F_HW_VLAN_STAG_RX | \ 176 NETIF_F_HW_VLAN_STAG_RX | \
177 NETIF_F_HW_VLAN_STAG_TX) 177 NETIF_F_HW_VLAN_STAG_TX)
178 178
179#define NETIF_F_GSO_ENCAP_ALL (NETIF_F_GSO_GRE | \
180 NETIF_F_GSO_GRE_CSUM | \
181 NETIF_F_GSO_IPIP | \
182 NETIF_F_GSO_SIT | \
183 NETIF_F_GSO_UDP_TUNNEL | \
184 NETIF_F_GSO_UDP_TUNNEL_CSUM | \
185 NETIF_F_GSO_MPLS)
186
179#endif /* _LINUX_NETDEV_FEATURES_H */ 187#endif /* _LINUX_NETDEV_FEATURES_H */
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 0b979ee4bfc0..a794d1dd7b40 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -118,6 +118,9 @@ struct ovs_vport_stats {
118/* Allow last Netlink attribute to be unaligned */ 118/* Allow last Netlink attribute to be unaligned */
119#define OVS_DP_F_UNALIGNED (1 << 0) 119#define OVS_DP_F_UNALIGNED (1 << 0)
120 120
121/* Allow datapath to associate multiple Netlink PIDs to each vport */
122#define OVS_DP_F_VPORT_PIDS (1 << 1)
123
121/* Fixed logical ports. */ 124/* Fixed logical ports. */
122#define OVSP_LOCAL ((__u32)0) 125#define OVSP_LOCAL ((__u32)0)
123 126
@@ -203,9 +206,10 @@ enum ovs_vport_type {
203 * this is the name of the network device. Maximum length %IFNAMSIZ-1 bytes 206 * this is the name of the network device. Maximum length %IFNAMSIZ-1 bytes
204 * plus a null terminator. 207 * plus a null terminator.
205 * @OVS_VPORT_ATTR_OPTIONS: Vport-specific configuration information. 208 * @OVS_VPORT_ATTR_OPTIONS: Vport-specific configuration information.
206 * @OVS_VPORT_ATTR_UPCALL_PID: The Netlink socket in userspace that 209 * @OVS_VPORT_ATTR_UPCALL_PID: The array of Netlink socket pids in userspace
207 * OVS_PACKET_CMD_MISS upcalls will be directed to for packets received on 210 * among which OVS_PACKET_CMD_MISS upcalls will be distributed for packets
208 * this port. A value of zero indicates that upcalls should not be sent. 211 * received on this port. If this is a single-element array of value 0,
212 * upcalls should not be sent.
209 * @OVS_VPORT_ATTR_STATS: A &struct ovs_vport_stats giving statistics for 213 * @OVS_VPORT_ATTR_STATS: A &struct ovs_vport_stats giving statistics for
210 * packets sent or received through the vport. 214 * packets sent or received through the vport.
211 * 215 *
@@ -228,7 +232,8 @@ enum ovs_vport_attr {
228 OVS_VPORT_ATTR_TYPE, /* u32 OVS_VPORT_TYPE_* constant. */ 232 OVS_VPORT_ATTR_TYPE, /* u32 OVS_VPORT_TYPE_* constant. */
229 OVS_VPORT_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long */ 233 OVS_VPORT_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long */
230 OVS_VPORT_ATTR_OPTIONS, /* nested attributes, varies by vport type */ 234 OVS_VPORT_ATTR_OPTIONS, /* nested attributes, varies by vport type */
231 OVS_VPORT_ATTR_UPCALL_PID, /* u32 Netlink PID to receive upcalls */ 235 OVS_VPORT_ATTR_UPCALL_PID, /* array of u32 Netlink socket PIDs for */
236 /* receiving upcalls */
232 OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */ 237 OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */
233 __OVS_VPORT_ATTR_MAX 238 __OVS_VPORT_ATTR_MAX
234}; 239};
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index e70d8b18e962..fe5cda0deb39 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -38,7 +38,7 @@
38#include "vport.h" 38#include "vport.h"
39 39
40static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, 40static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
41 const struct nlattr *attr, int len, bool keep_skb); 41 const struct nlattr *attr, int len);
42 42
43static int make_writable(struct sk_buff *skb, int write_len) 43static int make_writable(struct sk_buff *skb, int write_len)
44{ 44{
@@ -434,11 +434,17 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
434 return ovs_dp_upcall(dp, skb, &upcall); 434 return ovs_dp_upcall(dp, skb, &upcall);
435} 435}
436 436
437static bool last_action(const struct nlattr *a, int rem)
438{
439 return a->nla_len == rem;
440}
441
437static int sample(struct datapath *dp, struct sk_buff *skb, 442static int sample(struct datapath *dp, struct sk_buff *skb,
438 const struct nlattr *attr) 443 const struct nlattr *attr)
439{ 444{
440 const struct nlattr *acts_list = NULL; 445 const struct nlattr *acts_list = NULL;
441 const struct nlattr *a; 446 const struct nlattr *a;
447 struct sk_buff *sample_skb;
442 int rem; 448 int rem;
443 449
444 for (a = nla_data(attr), rem = nla_len(attr); rem > 0; 450 for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
@@ -455,8 +461,34 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
455 } 461 }
456 } 462 }
457 463
458 return do_execute_actions(dp, skb, nla_data(acts_list), 464 rem = nla_len(acts_list);
459 nla_len(acts_list), true); 465 a = nla_data(acts_list);
466
467 /* Actions list is either empty or only contains a single user-space
468 * action, the latter being a special case as it is the only known
469 * usage of the sample action.
470 * In these special cases don't clone the skb as there are no
471 * side-effects in the nested actions.
472 * Otherwise, clone in case the nested actions have side effects.
473 */
474 if (likely(rem == 0 || (nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
475 last_action(a, rem)))) {
476 sample_skb = skb;
477 skb_get(skb);
478 } else {
479 sample_skb = skb_clone(skb, GFP_ATOMIC);
480 if (!sample_skb) /* Skip sample action when out of memory. */
481 return 0;
482 }
483
484 /* Note that do_execute_actions() never consumes skb.
485 * In the case where skb has been cloned above it is the clone that
486 * is consumed. Otherwise the skb_get(skb) call prevents
487 * consumption by do_execute_actions(). Thus, it is safe to simply
488 * return the error code and let the caller (also
489 * do_execute_actions()) free skb on error.
490 */
491 return do_execute_actions(dp, sample_skb, a, rem);
460} 492}
461 493
462static int execute_set_action(struct sk_buff *skb, 494static int execute_set_action(struct sk_buff *skb,
@@ -507,7 +539,7 @@ static int execute_set_action(struct sk_buff *skb,
507 539
508/* Execute a list of actions against 'skb'. */ 540/* Execute a list of actions against 'skb'. */
509static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, 541static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
510 const struct nlattr *attr, int len, bool keep_skb) 542 const struct nlattr *attr, int len)
511{ 543{
512 /* Every output action needs a separate clone of 'skb', but the common 544 /* Every output action needs a separate clone of 'skb', but the common
513 * case is just a single output action, so that doing a clone and 545 * case is just a single output action, so that doing a clone and
@@ -562,12 +594,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
562 } 594 }
563 } 595 }
564 596
565 if (prev_port != -1) { 597 if (prev_port != -1)
566 if (keep_skb)
567 skb = skb_clone(skb, GFP_ATOMIC);
568
569 do_output(dp, skb, prev_port); 598 do_output(dp, skb, prev_port);
570 } else if (!keep_skb) 599 else
571 consume_skb(skb); 600 consume_skb(skb);
572 601
573 return 0; 602 return 0;
@@ -579,6 +608,5 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
579 struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); 608 struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
580 609
581 OVS_CB(skb)->tun_key = NULL; 610 OVS_CB(skb)->tun_key = NULL;
582 return do_execute_actions(dp, skb, acts->actions, 611 return do_execute_actions(dp, skb, acts->actions, acts->actions_len);
583 acts->actions_len, false);
584} 612}
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 20f59b62721a..3c461e1e4554 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -266,7 +266,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
266 upcall.cmd = OVS_PACKET_CMD_MISS; 266 upcall.cmd = OVS_PACKET_CMD_MISS;
267 upcall.key = &key; 267 upcall.key = &key;
268 upcall.userdata = NULL; 268 upcall.userdata = NULL;
269 upcall.portid = p->upcall_portid; 269 upcall.portid = ovs_vport_find_upcall_portid(p, skb);
270 ovs_dp_upcall(dp, skb, &upcall); 270 ovs_dp_upcall(dp, skb, &upcall);
271 consume_skb(skb); 271 consume_skb(skb);
272 stats_counter = &stats->n_missed; 272 stats_counter = &stats->n_missed;
@@ -464,7 +464,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
464 upcall->dp_ifindex = dp_ifindex; 464 upcall->dp_ifindex = dp_ifindex;
465 465
466 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); 466 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
467 ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); 467 err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb);
468 BUG_ON(err);
468 nla_nest_end(user_skb, nla); 469 nla_nest_end(user_skb, nla);
469 470
470 if (upcall_info->userdata) 471 if (upcall_info->userdata)
@@ -1373,7 +1374,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1373 parms.options = NULL; 1374 parms.options = NULL;
1374 parms.dp = dp; 1375 parms.dp = dp;
1375 parms.port_no = OVSP_LOCAL; 1376 parms.port_no = OVSP_LOCAL;
1376 parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); 1377 parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
1377 1378
1378 ovs_dp_change(dp, a); 1379 ovs_dp_change(dp, a);
1379 1380
@@ -1632,8 +1633,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1632 1633
1633 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || 1634 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
1634 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || 1635 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
1635 nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || 1636 nla_put_string(skb, OVS_VPORT_ATTR_NAME,
1636 nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_portid)) 1637 vport->ops->get_name(vport)))
1637 goto nla_put_failure; 1638 goto nla_put_failure;
1638 1639
1639 ovs_vport_get_stats(vport, &vport_stats); 1640 ovs_vport_get_stats(vport, &vport_stats);
@@ -1641,6 +1642,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1641 &vport_stats)) 1642 &vport_stats))
1642 goto nla_put_failure; 1643 goto nla_put_failure;
1643 1644
1645 if (ovs_vport_get_upcall_portids(vport, skb))
1646 goto nla_put_failure;
1647
1644 err = ovs_vport_get_options(vport, skb); 1648 err = ovs_vport_get_options(vport, skb);
1645 if (err == -EMSGSIZE) 1649 if (err == -EMSGSIZE)
1646 goto error; 1650 goto error;
@@ -1762,7 +1766,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
1762 parms.options = a[OVS_VPORT_ATTR_OPTIONS]; 1766 parms.options = a[OVS_VPORT_ATTR_OPTIONS];
1763 parms.dp = dp; 1767 parms.dp = dp;
1764 parms.port_no = port_no; 1768 parms.port_no = port_no;
1765 parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1769 parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
1766 1770
1767 vport = new_vport(&parms); 1771 vport = new_vport(&parms);
1768 err = PTR_ERR(vport); 1772 err = PTR_ERR(vport);
@@ -1812,8 +1816,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1812 goto exit_unlock_free; 1816 goto exit_unlock_free;
1813 } 1817 }
1814 1818
1815 if (a[OVS_VPORT_ATTR_UPCALL_PID]) 1819
1816 vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1820 if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
1821 struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
1822
1823 err = ovs_vport_set_upcall_portids(vport, ids);
1824 if (err)
1825 goto exit_unlock_free;
1826 }
1817 1827
1818 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, 1828 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1819 info->snd_seq, 0, OVS_VPORT_CMD_NEW); 1829 info->snd_seq, 0, OVS_VPORT_CMD_NEW);
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index bd658555afdf..84516126e5f3 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -140,11 +140,14 @@ static void do_setup(struct net_device *netdev)
140 netdev->tx_queue_len = 0; 140 netdev->tx_queue_len = 0;
141 141
142 netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | 142 netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
143 NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE; 143 NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
144 NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
144 145
145 netdev->vlan_features = netdev->features; 146 netdev->vlan_features = netdev->features;
147 netdev->hw_enc_features = netdev->features;
146 netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; 148 netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
147 netdev->hw_features = netdev->features & ~NETIF_F_LLTX; 149 netdev->hw_features = netdev->features & ~NETIF_F_LLTX;
150
148 eth_hw_addr_random(netdev); 151 eth_hw_addr_random(netdev);
149} 152}
150 153
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 42c0f4a0b78c..702fb21bfe15 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -134,10 +134,12 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
134 134
135 vport->dp = parms->dp; 135 vport->dp = parms->dp;
136 vport->port_no = parms->port_no; 136 vport->port_no = parms->port_no;
137 vport->upcall_portid = parms->upcall_portid;
138 vport->ops = ops; 137 vport->ops = ops;
139 INIT_HLIST_NODE(&vport->dp_hash_node); 138 INIT_HLIST_NODE(&vport->dp_hash_node);
140 139
140 if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids))
141 return ERR_PTR(-EINVAL);
142
141 vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 143 vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
142 if (!vport->percpu_stats) { 144 if (!vport->percpu_stats) {
143 kfree(vport); 145 kfree(vport);
@@ -161,6 +163,10 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
161 */ 163 */
162void ovs_vport_free(struct vport *vport) 164void ovs_vport_free(struct vport *vport)
163{ 165{
166 /* vport is freed from RCU callback or error path, Therefore
167 * it is safe to use raw dereference.
168 */
169 kfree(rcu_dereference_raw(vport->upcall_portids));
164 free_percpu(vport->percpu_stats); 170 free_percpu(vport->percpu_stats);
165 kfree(vport); 171 kfree(vport);
166} 172}
@@ -327,6 +333,99 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
327} 333}
328 334
329/** 335/**
336 * ovs_vport_set_upcall_portids - set upcall portids of @vport.
337 *
338 * @vport: vport to modify.
339 * @ids: new configuration, an array of port ids.
340 *
341 * Sets the vport's upcall_portids to @ids.
342 *
343 * Returns 0 if successful, -EINVAL if @ids is zero length or cannot be parsed
344 * as an array of U32.
345 *
346 * Must be called with ovs_mutex.
347 */
348int ovs_vport_set_upcall_portids(struct vport *vport, struct nlattr *ids)
349{
350 struct vport_portids *old, *vport_portids;
351
352 if (!nla_len(ids) || nla_len(ids) % sizeof(u32))
353 return -EINVAL;
354
355 old = ovsl_dereference(vport->upcall_portids);
356
357 vport_portids = kmalloc(sizeof(*vport_portids) + nla_len(ids),
358 GFP_KERNEL);
359 if (!vport_portids)
360 return -ENOMEM;
361
362 vport_portids->n_ids = nla_len(ids) / sizeof(u32);
363 vport_portids->rn_ids = reciprocal_value(vport_portids->n_ids);
364 nla_memcpy(vport_portids->ids, ids, nla_len(ids));
365
366 rcu_assign_pointer(vport->upcall_portids, vport_portids);
367
368 if (old)
369 kfree_rcu(old, rcu);
370 return 0;
371}
372
373/**
374 * ovs_vport_get_upcall_portids - get the upcall_portids of @vport.
375 *
376 * @vport: vport from which to retrieve the portids.
377 * @skb: sk_buff where portids should be appended.
378 *
379 * Retrieves the configuration of the given vport, appending the
380 * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall
381 * portids to @skb.
382 *
383 * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room.
384 * If an error occurs, @skb is left unmodified. Must be called with
385 * ovs_mutex or rcu_read_lock.
386 */
387int ovs_vport_get_upcall_portids(const struct vport *vport,
388 struct sk_buff *skb)
389{
390 struct vport_portids *ids;
391
392 ids = rcu_dereference_ovsl(vport->upcall_portids);
393
394 if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS)
395 return nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID,
396 ids->n_ids * sizeof(u32), (void *)ids->ids);
397 else
398 return nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, ids->ids[0]);
399}
400
401/**
402 * ovs_vport_find_upcall_portid - find the upcall portid to send upcall.
403 *
404 * @vport: vport from which the missed packet is received.
405 * @skb: skb that the missed packet was received.
406 *
407 * Uses the skb_get_hash() to select the upcall portid to send the
408 * upcall.
409 *
410 * Returns the portid of the target socket. Must be called with rcu_read_lock.
411 */
412u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
413{
414 struct vport_portids *ids;
415 u32 ids_index;
416 u32 hash;
417
418 ids = rcu_dereference(p->upcall_portids);
419
420 if (ids->n_ids == 1 && ids->ids[0] == 0)
421 return 0;
422
423 hash = skb_get_hash(skb);
424 ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids);
425 return ids->ids[ids_index];
426}
427
428/**
330 * ovs_vport_receive - pass up received packet to the datapath for processing 429 * ovs_vport_receive - pass up received packet to the datapath for processing
331 * 430 *
332 * @vport: vport that received the packet 431 * @vport: vport that received the packet
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 8d721e62f388..35f89d84b45e 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -23,6 +23,7 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/netlink.h> 24#include <linux/netlink.h>
25#include <linux/openvswitch.h> 25#include <linux/openvswitch.h>
26#include <linux/reciprocal_div.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
27#include <linux/spinlock.h> 28#include <linux/spinlock.h>
28#include <linux/u64_stats_sync.h> 29#include <linux/u64_stats_sync.h>
@@ -52,6 +53,10 @@ void ovs_vport_get_stats(struct vport *, struct ovs_vport_stats *);
52int ovs_vport_set_options(struct vport *, struct nlattr *options); 53int ovs_vport_set_options(struct vport *, struct nlattr *options);
53int ovs_vport_get_options(const struct vport *, struct sk_buff *); 54int ovs_vport_get_options(const struct vport *, struct sk_buff *);
54 55
56int ovs_vport_set_upcall_portids(struct vport *, struct nlattr *pids);
57int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
58u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
59
55int ovs_vport_send(struct vport *, struct sk_buff *); 60int ovs_vport_send(struct vport *, struct sk_buff *);
56 61
57/* The following definitions are for implementers of vport devices: */ 62/* The following definitions are for implementers of vport devices: */
@@ -62,13 +67,27 @@ struct vport_err_stats {
62 u64 tx_dropped; 67 u64 tx_dropped;
63 u64 tx_errors; 68 u64 tx_errors;
64}; 69};
70/**
71 * struct vport_portids - array of netlink portids of a vport.
72 * must be protected by rcu.
73 * @rn_ids: The reciprocal value of @n_ids.
74 * @rcu: RCU callback head for deferred destruction.
75 * @n_ids: Size of @ids array.
76 * @ids: Array storing the Netlink socket pids to be used for packets received
77 * on this port that miss the flow table.
78 */
79struct vport_portids {
80 struct reciprocal_value rn_ids;
81 struct rcu_head rcu;
82 u32 n_ids;
83 u32 ids[];
84};
65 85
66/** 86/**
67 * struct vport - one port within a datapath 87 * struct vport - one port within a datapath
68 * @rcu: RCU callback head for deferred destruction. 88 * @rcu: RCU callback head for deferred destruction.
69 * @dp: Datapath to which this port belongs. 89 * @dp: Datapath to which this port belongs.
70 * @upcall_portid: The Netlink port to use for packets received on this port that 90 * @upcall_portids: RCU protected 'struct vport_portids'.
71 * miss the flow table.
72 * @port_no: Index into @dp's @ports array. 91 * @port_no: Index into @dp's @ports array.
73 * @hash_node: Element in @dev_table hash table in vport.c. 92 * @hash_node: Element in @dev_table hash table in vport.c.
74 * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. 93 * @dp_hash_node: Element in @datapath->ports hash table in datapath.c.
@@ -80,7 +99,7 @@ struct vport_err_stats {
80struct vport { 99struct vport {
81 struct rcu_head rcu; 100 struct rcu_head rcu;
82 struct datapath *dp; 101 struct datapath *dp;
83 u32 upcall_portid; 102 struct vport_portids __rcu *upcall_portids;
84 u16 port_no; 103 u16 port_no;
85 104
86 struct hlist_node hash_node; 105 struct hlist_node hash_node;
@@ -111,7 +130,7 @@ struct vport_parms {
111 /* For ovs_vport_alloc(). */ 130 /* For ovs_vport_alloc(). */
112 struct datapath *dp; 131 struct datapath *dp;
113 u16 port_no; 132 u16 port_no;
114 u32 upcall_portid; 133 struct nlattr *upcall_portids;
115}; 134};
116 135
117/** 136/**