From: Ben Pfaff Date: Thu, 16 Jul 2009 18:54:37 +0000 (-0700) Subject: Merge citrix branch into master. X-Git-Tag: v0.90.3~3 X-Git-Url: http://git.onelab.eu/?p=sliver-openvswitch.git;a=commitdiff_plain;h=3b01baa3970139c3a195017ab1ea3e42761e3db2 Merge citrix branch into master. --- 3b01baa3970139c3a195017ab1ea3e42761e3db2 diff --cc lib/socket-util.c index e5b86e427,086a329ea..d53743487 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@@ -300,172 -299,24 +300,190 @@@ guess_netmask(uint32_t ip : htonl(0)); /* ??? */ } +/* Opens a non-blocking TCP socket and connects to 'target', which should be a + * string in the format "[:]", where is required and + * is optional, with 'default_port' assumed if is omitted. + * + * On success, returns 0 (indicating connection complete) or EAGAIN (indicating + * connection in progress), in which case the new file descriptor is stored + * into '*fdp'. On failure, returns a positive errno value other than EAGAIN + * and stores -1 into '*fdp'. + * + * If 'sinp' is non-null, then on success the target address is stored into + * '*sinp'. */ +int +tcp_open_active(const char *target_, uint16_t default_port, + struct sockaddr_in *sinp, int *fdp) +{ + char *target = xstrdup(target_); + char *save_ptr = NULL; + const char *host_name; + const char *port_string; + struct sockaddr_in sin; + int fd = -1; + int error; + + /* Defaults. */ + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(default_port); + + /* Tokenize. */ + host_name = strtok_r(target, ":", &save_ptr); + port_string = strtok_r(NULL, ":", &save_ptr); + if (!host_name) { + ovs_error(0, "%s: bad peer name format", target_); + error = EAFNOSUPPORT; + goto exit; + } + + /* Look up IP, port. */ + error = lookup_ip(host_name, &sin.sin_addr); + if (error) { + goto exit; + } + if (port_string && atoi(port_string)) { + sin.sin_port = htons(atoi(port_string)); + } + + /* Create non-blocking socket. */ + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + VLOG_ERR("%s: socket: %s", target_, strerror(errno)); + error = errno; + goto exit; + } + error = set_nonblocking(fd); + if (error) { + goto exit_close; + } + + /* Connect. */ + error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno; + if (error == EINPROGRESS) { + error = EAGAIN; + } else if (error && error != EAGAIN) { + goto exit_close; + } + + /* Success: error is 0 or EAGAIN. */ + goto exit; + +exit_close: + close(fd); +exit: + if (!error || error == EAGAIN) { + if (sinp) { + *sinp = sin; + } + *fdp = fd; + } else { + *fdp = -1; + } + free(target); + return error; +} + +/* Opens a non-blocking TCP socket, binds to 'target', and listens for incoming + * connections. 'target' should be a string in the format "[][:]", + * where both and are optional. If is omitted, it defaults + * to 'default_port'; if is omitted it defaults to the wildcard IP + * address. + * + * The socket will have SO_REUSEADDR turned on. + * + * On success, returns a non-negative file descriptor. On failure, returns a + * negative errno value. */ +int +tcp_open_passive(const char *target_, uint16_t default_port) +{ + char *target = xstrdup(target_); + char *string_ptr = target; + struct sockaddr_in sin; + const char *host_name; + const char *port_string; + int fd, error; + unsigned int yes = 1; + + /* Address defaults. */ + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = htons(default_port); + + /* Parse optional port number. */ + port_string = strsep(&string_ptr, ":"); + if (port_string && atoi(port_string)) { + sin.sin_port = htons(atoi(port_string)); + } + + /* Parse optional bind IP. */ + host_name = strsep(&string_ptr, ":"); + if (host_name && host_name[0]) { + error = lookup_ip(host_name, &sin.sin_addr); + if (error) { + goto exit; + } + } + + /* Create non-blocking socket, set SO_REUSEADDR. */ + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + error = errno; + VLOG_ERR("%s: socket: %s", target_, strerror(error)); + goto exit; + } + error = set_nonblocking(fd); + if (error) { + goto exit_close; + } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) { + error = errno; + VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target_, strerror(error)); + goto exit_close; + } + + /* Bind. */ + if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) { + error = errno; + VLOG_ERR("%s: bind: %s", target_, strerror(error)); + goto exit_close; + } + + /* Listen. */ + if (listen(fd, 10) < 0) { + error = errno; + VLOG_ERR("%s: listen: %s", target_, strerror(error)); + goto exit_close; + } + error = 0; + goto exit; + +exit_close: + close(fd); +exit: + free(target); + return error ? -error : fd; +} + + /* Returns a readable and writable fd for /dev/null, if successful, otherwise + * a negative errno value. The caller must not close the returned fd (because + * the same fd will be handed out to subsequent callers). */ + int + get_null_fd(void) + { + static int null_fd = -1; + if (null_fd < 0) { + null_fd = open("/dev/null", O_RDWR); + if (null_fd < 0) { + int error = errno; + VLOG_ERR("could not open /dev/null: %s", strerror(error)); + return -error; + } + } + return null_fd; + } + int read_fully(int fd, void *p_, size_t size, size_t *bytes_read) { diff --cc lib/socket-util.h index d80883897,3ba2c477b..febe5e735 --- a/lib/socket-util.h +++ b/lib/socket-util.h @@@ -32,11 -32,8 +32,12 @@@ int make_unix_socket(int style, bool no const char *bind_path, const char *connect_path); int get_unix_name_len(socklen_t sun_len); uint32_t guess_netmask(uint32_t ip); + int get_null_fd(void); +int tcp_open_active(const char *target, uint16_t default_port, + struct sockaddr_in *sinp, int *fdp); +int tcp_open_passive(const char *target, uint16_t default_port); + int read_fully(int fd, void *, size_t, size_t *bytes_read); int write_fully(int fd, const void *, size_t, size_t *bytes_written); diff --cc vswitchd/bridge.c index ab55658f6,b0b2a8f11..f977c2b8a --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@@ -275,31 -277,29 +277,33 @@@ bridge_get_ifaces(struct svec *svec void bridge_init(void) { - int retval; - int i; - - bond_init(); + struct svec dpif_names; + size_t i; + unixctl_command_register("fdb/show", bridge_unixctl_fdb_show); + - for (i = 0; i < DP_MAX; i++) { - struct dpif dpif; - char devname[16]; + dp_enumerate(&dpif_names); + for (i = 0; i < dpif_names.n; i++) { + const char *dpif_name = dpif_names.names[i]; + struct dpif *dpif; + int retval; - sprintf(devname, "dp%d", i); - retval = dpif_open(devname, &dpif); + retval = dpif_open(dpif_name, &dpif); if (!retval) { - char dpif_name[IF_NAMESIZE]; - if (dpif_get_name(&dpif, dpif_name, sizeof dpif_name) - || !cfg_has("bridge.%s.port", dpif_name)) { - dpif_delete(&dpif); + struct svec all_names; + size_t j; + + svec_init(&all_names); + dpif_get_all_names(dpif, &all_names); + for (j = 0; j < all_names.n; j++) { + if (cfg_has("bridge.%s.port", all_names.names[j])) { + goto found; + } } - dpif_close(&dpif); - } else if (retval != ENODEV) { - VLOG_ERR("failed to delete datapath dp%d: %s", - i, strerror(retval)); + dpif_delete(dpif); + found: + svec_destroy(&all_names); + dpif_close(dpif); } } @@@ -1067,12 -1106,16 +1097,17 @@@ bridge_reconfigure_controller(struct br int rate_limit, burst_limit; if (!strcmp(controller, "discover")) { + bool update_resolv_conf = true; + + if (cfg_has("%s.update-resolv.conf", pfx)) { + update_resolv_conf = cfg_get_bool(0, "%s.update-resolv.conf", + pfx); + } ofproto_set_discovery(br->ofproto, true, cfg_get_string(0, "%s.accept-regex", pfx), - cfg_get_bool(0, "%s.update-resolv.conf", - pfx)); + update_resolv_conf); } else { + char local_name[IF_NAMESIZE]; struct netdev *netdev; bool in_band; int error;