From: Ben Pfaff Date: Fri, 1 Apr 2011 17:17:52 +0000 (-0700) Subject: netdev-vport: Implement 'send' function. X-Git-Tag: v1.2.0~515 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=7feba1acdd806b54ec152d2e93169ab2a295128d;p=sliver-openvswitch.git netdev-vport: Implement 'send' function. The new implementation of the bonding code expects to be able to send packets on netdevs using netdev_send(). This implements it. --- diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index bdc770369..b5590c447 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -1027,6 +1027,34 @@ dpif_linux_is_internal_device(const char *name) return reply.type == ODP_VPORT_TYPE_INTERNAL; } +int +dpif_linux_vport_send(int dp_ifindex, uint32_t port_no, + const void *data, size_t size) +{ + struct odp_header *execute; + struct ofpbuf *buf; + size_t actions_ofs; + int error; + + buf = ofpbuf_new(128 + size); + + nl_msg_put_genlmsghdr(buf, 0, odp_packet_family, NLM_F_REQUEST, + ODP_PACKET_CMD_EXECUTE, 1); + + execute = ofpbuf_put_uninit(buf, sizeof *execute); + execute->dp_ifindex = dp_ifindex; + + nl_msg_put_unspec(buf, ODP_PACKET_ATTR_PACKET, data, size); + + actions_ofs = nl_msg_start_nested(buf, ODP_PACKET_ATTR_ACTIONS); + nl_msg_put_u32(buf, ODP_ACTION_ATTR_OUTPUT, port_no); + nl_msg_end_nested(buf, actions_ofs); + + error = nl_sock_transact(genl_sock, buf, NULL); + ofpbuf_delete(buf); + return error; +} + static void dpif_linux_port_changed(const struct rtnetlink_link_change *change, void *dpif_) diff --git a/lib/dpif-linux.h b/lib/dpif-linux.h index bd7b07cae..f942a8cc0 100644 --- a/lib/dpif-linux.h +++ b/lib/dpif-linux.h @@ -53,4 +53,7 @@ int dpif_linux_vport_get(const char *name, struct dpif_linux_vport *reply, bool dpif_linux_is_internal_device(const char *name); +int dpif_linux_vport_send(int dp_ifindex, uint32_t port_no, + const void *data, size_t size); + #endif /* dpif-linux.h */ diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 39a1bb94d..be2694159 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -56,6 +56,8 @@ struct netdev_vport_notifier { struct netdev_dev_vport { struct netdev_dev netdev_dev; struct ofpbuf *options; + int dp_ifindex; /* -1 if unknown. */ + uint32_t port_no; /* UINT32_MAX if unknown. */ }; struct netdev_vport { @@ -185,10 +187,14 @@ netdev_vport_create(const struct netdev_class *netdev_class, const char *name, const struct vport_class *vport_class = vport_class_cast(netdev_class); struct ofpbuf *options = NULL; struct shash fetched_args; + int dp_ifindex; + uint32_t port_no; int error; shash_init(&fetched_args); + dp_ifindex = -1; + port_no = UINT32_MAX; if (!shash_is_empty(args)) { /* Parse the provided configuration. */ options = ofpbuf_new(64); @@ -215,6 +221,8 @@ netdev_vport_create(const struct netdev_class *netdev_class, const char *name, name, strerror(error)); } else { options = ofpbuf_clone_data(reply.options, reply.options_len); + dp_ifindex = reply.dp_ifindex; + port_no = reply.port_no; } ofpbuf_delete(buf); } else { @@ -231,6 +239,8 @@ netdev_vport_create(const struct netdev_class *netdev_class, const char *name, shash_is_empty(&fetched_args) ? args : &fetched_args, netdev_class); dev->options = options; + dev->dp_ifindex = dp_ifindex; + dev->port_no = port_no; *netdev_devp = &dev->netdev_dev; route_table_register(); @@ -311,6 +321,32 @@ netdev_vport_set_config(struct netdev_dev *dev_, const struct shash *args) return error; } +static int +netdev_vport_send(struct netdev *netdev, const void *data, size_t size) +{ + struct netdev_dev *dev_ = netdev_get_dev(netdev); + struct netdev_dev_vport *dev = netdev_dev_vport_cast(dev_); + + if (dev->dp_ifindex == -1) { + const char *name = netdev_get_name(netdev); + struct dpif_linux_vport reply; + struct ofpbuf *buf; + int error; + + error = dpif_linux_vport_get(name, &reply, &buf); + if (error) { + VLOG_ERR_RL(&rl, "%s: failed to query vport for send (%s)", + name, strerror(error)); + return error; + } + dev->dp_ifindex = reply.dp_ifindex; + dev->port_no = reply.port_no; + ofpbuf_delete(buf); + } + + return dpif_linux_vport_send(dev->dp_ifindex, dev->port_no, data, size); +} + static int netdev_vport_set_etheraddr(struct netdev *netdev, const uint8_t mac[ETH_ADDR_LEN]) @@ -936,7 +972,7 @@ unparse_patch_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED, NULL, /* recv_wait */ \ NULL, /* drain */ \ \ - NULL, /* send */ \ + netdev_vport_send, /* send */ \ NULL, /* send_wait */ \ \ netdev_vport_set_etheraddr, \