X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=python%2Fovs%2Fsocket_util.py;h=7dac5bb377932b61a610d57772c5756d5a0d31c1;hb=2b13d312fc4d6e5eb1d0e3004fa523bb0c0ba544;hp=a8e8d92e7d6ed5cfde4136fa0b777890efb94601;hpb=e0edde6fee279cdbbf3c179f5f50adaf0c7c7f1e;p=sliver-openvswitch.git diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py index a8e8d92e7..7dac5bb37 100644 --- a/python/ovs/socket_util.py +++ b/python/ovs/socket_util.py @@ -19,6 +19,7 @@ import socket import sys import ovs.fatal_signal +import ovs.poller import ovs.vlog vlog = ovs.vlog.Vlog("socket_util") @@ -69,24 +70,102 @@ def make_unix_socket(style, nonblock, bind_path, connect_path): return 0, sock except socket.error, e: sock.close() - if bind_path is not None: + if (bind_path is not None and + os.path.exists(bind_path)): ovs.fatal_signal.unlink_file_now(bind_path) - return get_exception_errno(e), None + eno = ovs.socket_util.get_exception_errno(e) + if (eno == "AF_UNIX path too long" and + os.uname()[0] == "Linux"): + short_connect_path = None + short_bind_path = None + connect_dirfd = None + bind_dirfd = None + # Try workaround using /proc/self/fd + if connect_path is not None: + dirname = os.path.dirname(connect_path) + basename = os.path.basename(connect_path) + try: + connect_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY) + except OSError, err: + return get_exception_errno(err), None + short_connect_path = "/proc/self/fd/%d/%s" % (connect_dirfd, basename) + + if bind_path is not None: + dirname = os.path.dirname(bind_path) + basename = os.path.basename(bind_path) + try: + bind_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY) + except OSError, err: + return get_exception_errno(err), None + short_bind_path = "/proc/self/fd/%d/%s" % (bind_dirfd, basename) + + try: + return make_unix_socket(style, nonblock, short_bind_path, short_connect_path) + finally: + if connect_dirfd is not None: + os.close(connect_dirfd) + if bind_dirfd is not None: + os.close(bind_dirfd) + else: + return get_exception_errno(e), None def check_connection_completion(sock): - p = select.poll() - p.register(sock, select.POLLOUT) - if len(p.poll(0)) == 1: - return get_socket_error(sock) + p = ovs.poller.SelectPoll() + p.register(sock, ovs.poller.POLLOUT) + pfds = p.poll(0) + if len(pfds) == 1: + revents = pfds[0][1] + if revents & ovs.poller.POLLERR: + try: + # The following should raise an exception. + socket.send("\0", socket.MSG_DONTWAIT) + + # (Here's where we end up if it didn't.) + # XXX rate-limit + vlog.err("poll return POLLERR but send succeeded") + return errno.EPROTO + except socket.error, e: + return get_exception_errno(e) + else: + return 0 else: return errno.EAGAIN -def get_socket_error(sock): - """Returns the errno value associated with 'socket' (0 if no error) and - resets the socket's error status.""" - return sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) +def inet_parse_active(target, default_port): + address = target.split(":") + host_name = address[0] + if not host_name: + raise ValueError("%s: bad peer name format" % target) + if len(address) >= 2: + port = int(address[1]) + elif default_port: + port = default_port + else: + raise ValueError("%s: port number must be specified" % target) + return (host_name, port) + + +def inet_open_active(style, target, default_port, dscp): + address = inet_parse_active(target, default_port) + try: + sock = socket.socket(socket.AF_INET, style, 0) + except socket.error, e: + return get_exception_errno(e), None + + try: + set_nonblocking(sock) + set_dscp(sock, dscp) + try: + sock.connect(address) + except socket.error, e: + if get_exception_errno(e) != errno.EINPROGRESS: + raise + return 0, sock + except socket.error, e: + sock.close() + return get_exception_errno(e), None def get_exception_errno(e): @@ -146,4 +225,11 @@ def set_nonblocking(sock): sock.setblocking(0) except socket.error, e: vlog.err("could not set nonblocking mode on socket: %s" - % os.strerror(get_socket_error(e))) + % os.strerror(get_exception_errno(e))) + + +def set_dscp(sock, dscp): + if dscp > 63: + raise ValueError("Invalid dscp %d" % dscp) + val = dscp << 2 + sock.setsockopt(socket.IPPROTO_IP, socket.IP_TOS, val)