mirror of
https://github.com/openvswitch/ovs
synced 2025-10-29 15:28:56 +00:00
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.
This commit is contained in:
@@ -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_)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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, \
|
||||
|
||||
Reference in New Issue
Block a user