#include "rtnetlink.h"
#include "rtnetlink-link.h"
#include "shash.h"
-#include "svec.h"
+#include "sset.h"
#include "unaligned.h"
#include "util.h"
#include "vlog.h"
unsigned int listen_mask;
/* Change notification. */
- struct shash changed_ports; /* Ports that have changed. */
+ struct sset changed_ports; /* Ports that have changed. */
struct rtnetlink_notifier port_notifier;
bool change_error;
};
}
static int
-dpif_linux_enumerate(struct svec *all_dps)
+dpif_linux_enumerate(struct sset *all_dps)
{
struct nl_dump dump;
struct ofpbuf msg;
struct dpif_linux_dp dp;
if (!dpif_linux_dp_from_ofpbuf(&dp, &msg)) {
- svec_add(all_dps, dp.name);
+ sset_add(all_dps, dp.name);
}
}
return nl_dump_done(&dump);
}
dpif->listen_mask = 0;
dpif->dp_ifindex = dp->dp_ifindex;
- shash_init(&dpif->changed_ports);
+ sset_init(&dpif->changed_ports);
dpif->change_error = false;
*dpifp = &dpif->dpif;
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
rtnetlink_link_notifier_unregister(&dpif->port_notifier);
- shash_destroy(&dpif->changed_ports);
+ sset_destroy(&dpif->changed_ports);
free(dpif);
}
if (dpif->change_error) {
dpif->change_error = false;
- shash_clear(&dpif->changed_ports);
+ sset_clear(&dpif->changed_ports);
return ENOBUFS;
- } else if (!shash_is_empty(&dpif->changed_ports)) {
- struct shash_node *node = shash_first(&dpif->changed_ports);
- *devnamep = shash_steal(&dpif->changed_ports, node);
+ } else if (!sset_is_empty(&dpif->changed_ports)) {
+ *devnamep = sset_pop(&dpif->changed_ports);
return 0;
} else {
return EAGAIN;
dpif_linux_port_poll_wait(const struct dpif *dpif_)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
- if (!shash_is_empty(&dpif->changed_ports) || dpif->change_error) {
+ if (!sset_is_empty(&dpif->changed_ports) || dpif->change_error) {
poll_immediate_wake();
} else {
rtnetlink_link_notifier_wait();
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_)
{
/* Our datapath changed, either adding a new port or deleting an
* existing one. */
- shash_add_once(&dpif->changed_ports, change->ifname, NULL);
+ sset_add(&dpif->changed_ports, change->ifname);
}
} else {
dpif->change_error = true;
}
if (a[ODP_VPORT_ATTR_MTU]) {
vport->mtu = nl_attr_get_u32(a[ODP_VPORT_ATTR_MTU]);
+ } else {
+ vport->mtu = INT_MAX;
}
if (a[ODP_VPORT_ATTR_OPTIONS]) {
vport->options = nl_attr_get(a[ODP_VPORT_ATTR_OPTIONS]);
vport->address, ETH_ADDR_LEN);
}
- if (vport->mtu) {
+ if (vport->mtu && vport->mtu != INT_MAX) {
nl_msg_put_u32(buf, ODP_VPORT_ATTR_MTU, vport->mtu);
}