X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-linux.c;h=87c9f327c79bf95b5357d64e3cd923c78df5bcd0;hb=3abc4a1a6c29ebecffeecedd582c64e0bb7d4c53;hp=e7d43811dc66068cc8dece6a12e6e487318a3b17;hpb=49c36903d6d65bed96cba31f05534510a21a68d7;p=openvswitch diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index e7d43811..87c9f327 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -31,6 +31,7 @@ #include #include "dpif-provider.h" +#include "netdev.h" #include "ofpbuf.h" #include "poll-loop.h" #include "rtnetlink.h" @@ -95,10 +96,10 @@ dpif_linux_enumerate(struct svec *all_dps) int retval; sprintf(devname, "dp%d", i); - retval = dpif_open(devname, &dpif); + retval = dpif_open(devname, "system", &dpif); if (!retval) { svec_add(all_dps, devname); - dpif_close(dpif); + dpif_uninit(dpif, true); } else if (retval != ENODEV && !error) { error = retval; } @@ -107,7 +108,7 @@ dpif_linux_enumerate(struct svec *all_dps) } static int -dpif_linux_open(const char *name UNUSED, char *suffix, bool create, +dpif_linux_open(const char *name, const char *type OVS_UNUSED, bool create, struct dpif **dpifp) { int minor; @@ -116,11 +117,11 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create, && isdigit((unsigned char)name[2]) ? atoi(name + 2) : -1; if (create) { if (minor >= 0) { - return create_minor(suffix, minor, dpifp); + return create_minor(name, minor, dpifp); } else { /* Scan for unused minor number. */ for (minor = 0; minor < ODP_MAX; minor++) { - int error = create_minor(suffix, minor, dpifp); + int error = create_minor(name, minor, dpifp); if (error != EBUSY) { return error; } @@ -135,7 +136,7 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create, int error; if (minor < 0) { - error = lookup_minor(suffix, &minor); + error = lookup_minor(name, &minor); if (error) { return error; } @@ -157,7 +158,7 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create, VLOG_WARN("%s: probe returned unexpected error: %s", dpif_name(*dpifp), strerror(error)); } - dpif_close(*dpifp); + dpif_uninit(*dpifp, true); return error; } @@ -188,8 +189,30 @@ dpif_linux_get_all_names(const struct dpif *dpif_, struct svec *all_names) } static int -dpif_linux_delete(struct dpif *dpif_) +dpif_linux_destroy(struct dpif *dpif_) { + struct odp_port *ports; + size_t n_ports; + int err; + int i; + + err = dpif_port_list(dpif_, &ports, &n_ports); + if (err) { + return err; + } + + for (i = 0; i < n_ports; i++) { + if (ports[i].port != ODPP_LOCAL) { + err = do_ioctl(dpif_, ODP_VPORT_DEL, ports[i].devname); + if (err) { + VLOG_WARN_RL(&error_rl, "%s: error deleting port %s (%s)", + dpif_name(dpif_), ports[i].devname, strerror(err)); + } + } + } + + free(ports); + return do_ioctl(dpif_, ODP_DP_DESTROY, NULL); } @@ -230,7 +253,7 @@ dpif_linux_port_add(struct dpif *dpif_, const char *devname, uint16_t flags, memset(&port, 0, sizeof port); strncpy(port.devname, devname, sizeof port.devname); port.flags = flags; - error = do_ioctl(dpif_, ODP_PORT_ADD, &port); + error = do_ioctl(dpif_, ODP_PORT_ATTACH, &port); if (!error) { *port_no = port.port; } @@ -241,7 +264,27 @@ static int dpif_linux_port_del(struct dpif *dpif_, uint16_t port_no) { int tmp = port_no; - return do_ioctl(dpif_, ODP_PORT_DEL, &tmp); + int err; + struct odp_port port; + + err = dpif_port_query_by_number(dpif_, port_no, &port); + if (err) { + return err; + } + + err = do_ioctl(dpif_, ODP_PORT_DETACH, &tmp); + if (err) { + return err; + } + + if (!netdev_is_open(port.devname)) { + /* Try deleting the port if no one has it open. This shouldn't + * actually be necessary unless the config changed while we weren't + * running but it won't hurt anything if the port is already gone. */ + do_ioctl(dpif_, ODP_VPORT_DEL, port.devname); + } + + return 0; } static int @@ -460,15 +503,14 @@ dpif_linux_recv_wait(struct dpif *dpif_) } const struct dpif_class dpif_linux_class = { - "", /* This is the default class. */ - "linux", + "system", NULL, NULL, dpif_linux_enumerate, dpif_linux_open, dpif_linux_close, dpif_linux_get_all_names, - dpif_linux_delete, + dpif_linux_destroy, dpif_linux_get_stats, dpif_linux_get_drop_frags, dpif_linux_set_drop_frags, @@ -678,6 +720,8 @@ get_major(const char *target) } } + fclose(file); + VLOG_ERR("%s: %s major not found (is the module loaded?)", fn, target); return -ENODEV; } @@ -686,11 +730,11 @@ static int finish_open(struct dpif *dpif_, const char *local_ifname) { struct dpif_linux *dpif = dpif_linux_cast(dpif_); - dpif->local_ifname = strdup(local_ifname); + dpif->local_ifname = xstrdup(local_ifname); dpif->local_ifindex = if_nametoindex(local_ifname); if (!dpif->local_ifindex) { int error = errno; - dpif_close(dpif_); + dpif_uninit(dpif_, true); VLOG_WARN("could not get ifindex of %s device: %s", local_ifname, strerror(errno)); return error; @@ -707,7 +751,7 @@ create_minor(const char *name, int minor, struct dpif **dpifp) if (!error) { error = finish_open(*dpifp, name); } else { - dpif_close(*dpifp); + dpif_uninit(*dpifp, true); } } return error;