X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif-linux.c;h=2bf329f453732137c1d08c936ecae7c5e151ee4e;hb=2d2d6d4a71776813f8d2fd1af1051f22b836befc;hp=e075c8b02da0c25250b21f76145e6086753c4da1;hpb=8b61709d5ec6c4ef58a04fcaefde617ff63fa10d;p=openvswitch diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index e075c8b0..2bf329f4 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -31,9 +31,9 @@ #include #include "dpif-provider.h" -#include "netdev-linux.h" #include "ofpbuf.h" #include "poll-loop.h" +#include "rtnetlink.h" #include "svec.h" #include "util.h" @@ -52,7 +52,7 @@ struct dpif_linux { /* Change notification. */ int local_ifindex; /* Ifindex of local port. */ struct svec changed_ports; /* Ports that have changed. */ - struct linux_netdev_notifier port_notifier; + struct rtnetlink_notifier port_notifier; bool change_error; }; @@ -61,10 +61,11 @@ static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5); static int do_ioctl(const struct dpif *, int cmd, const void *arg); static int lookup_minor(const char *name, int *minor); static int finish_open(struct dpif *, const char *local_ifname); +static int get_openvswitch_major(void); static int create_minor(const char *name, int minor, struct dpif **dpifp); static int open_minor(int minor, struct dpif **dpifp); static int make_openvswitch_device(int minor, char **fnp); -static void dpif_linux_port_changed(const struct linux_netdev_change *, +static void dpif_linux_port_changed(const struct rtnetlink_change *, void *dpif); static struct dpif_linux * @@ -77,9 +78,16 @@ dpif_linux_cast(const struct dpif *dpif) static int dpif_linux_enumerate(struct svec *all_dps) { + int major; int error; int i; + /* Check that the Open vSwitch module is loaded. */ + major = get_openvswitch_major(); + if (major < 0) { + return -major; + } + error = 0; for (i = 0; i < ODP_MAX; i++) { struct dpif *dpif; @@ -104,7 +112,8 @@ dpif_linux_open(const char *name UNUSED, char *suffix, bool create, { int minor; - minor = !strncmp(name, "dp", 2) && isdigit(name[2]) ? atoi(name + 2) : -1; + minor = !strncmp(name, "dp", 2) + && isdigit((unsigned char)name[2]) ? atoi(name + 2) : -1; if (create) { if (minor >= 0) { return create_minor(suffix, minor, dpifp); @@ -161,7 +170,7 @@ static void dpif_linux_close(struct dpif *dpif_) { struct dpif_linux *dpif = dpif_linux_cast(dpif_); - linux_netdev_notifier_unregister(&dpif->port_notifier); + rtnetlink_notifier_unregister(&dpif->port_notifier); svec_destroy(&dpif->changed_ports); free(dpif->local_ifname); close(dpif->fd); @@ -294,7 +303,7 @@ dpif_linux_port_poll_wait(const struct dpif *dpif_) if (dpif->changed_ports.n || dpif->change_error) { poll_immediate_wake(); } else { - linux_netdev_notifier_wait(); + rtnetlink_notifier_wait(); } } @@ -410,7 +419,7 @@ dpif_linux_recv(struct dpif *dpif_, struct ofpbuf **bufp) return 0; } else { VLOG_WARN_RL(&error_rl, "%s: discarding message truncated " - "from %zu bytes to %d", + "from %"PRIu32" bytes to %d", dpif_name(dpif_), msg->length, retval); error = ERANGE; } @@ -471,7 +480,7 @@ const struct dpif_class dpif_linux_class = { }; static int get_openvswitch_major(void); -static int get_major(const char *target, int default_major); +static int get_major(const char *target); static int do_ioctl(const struct dpif *dpif_, int cmd, const void *arg) @@ -540,11 +549,18 @@ error: static int make_openvswitch_device(int minor, char **fnp) { - dev_t dev = makedev(get_openvswitch_major(), minor); const char dirname[] = "/dev/net"; + int major; + dev_t dev; struct stat s; char fn[128]; + major = get_openvswitch_major(); + if (major < 0) { + return -major; + } + dev = makedev(major, minor); + *fnp = NULL; sprintf(fn, "%s/dp%d", dirname, minor); if (!stat(fn, &s)) { @@ -553,7 +569,7 @@ make_openvswitch_device(int minor, char **fnp) fn); } else if (s.st_rdev != dev) { VLOG_WARN_RL(&error_rl, - "%s is device %u:%u instead of %u:%u, fixing", + "%s is device %u:%u but should be %u:%u, fixing", fn, major(s.st_rdev), minor(s.st_rdev), major(dev), minor(dev)); } else { @@ -596,20 +612,20 @@ success: return 0; } - +/* Return the major device number of the Open vSwitch device. If it + * cannot be determined, a negative errno is returned. */ static int get_openvswitch_major(void) { - static unsigned int openvswitch_major; - if (!openvswitch_major) { - enum { DEFAULT_MAJOR = 248 }; - openvswitch_major = get_major("openvswitch", DEFAULT_MAJOR); + static int openvswitch_major = -1; + if (openvswitch_major < 0) { + openvswitch_major = get_major("openvswitch"); } return openvswitch_major; } static int -get_major(const char *target, int default_major) +get_major(const char *target) { const char fn[] = "/proc/devices"; char line[128]; @@ -619,7 +635,7 @@ get_major(const char *target, int default_major) file = fopen(fn, "r"); if (!file) { VLOG_ERR("opening %s failed (%s)", fn, strerror(errno)); - goto error; + return -errno; } for (ln = 1; fgets(line, sizeof line, file); ln++) { @@ -645,11 +661,8 @@ get_major(const char *target, int default_major) } } - VLOG_ERR("%s: %s major not found (is the module loaded?), using " - "default major %d", fn, target, default_major); -error: - VLOG_INFO("using default major %d for %s", default_major, target); - return default_major; + VLOG_ERR("%s: %s major not found (is the module loaded?)", fn, target); + return -ENODEV; } static int @@ -698,8 +711,8 @@ open_minor(int minor, struct dpif **dpifp) fd = open(fn, O_RDONLY | O_NONBLOCK); if (fd >= 0) { struct dpif_linux *dpif = xmalloc(sizeof *dpif); - error = linux_netdev_notifier_register(&dpif->port_notifier, - dpif_linux_port_changed, dpif); + error = rtnetlink_notifier_register(&dpif->port_notifier, + dpif_linux_port_changed, dpif); if (!error) { char *name; @@ -727,7 +740,7 @@ open_minor(int minor, struct dpif **dpifp) } static void -dpif_linux_port_changed(const struct linux_netdev_change *change, void *dpif_) +dpif_linux_port_changed(const struct rtnetlink_change *change, void *dpif_) { struct dpif_linux *dpif = dpif_;