X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fsocket-util.c;h=82a33c2077c9da0565e07fc4b1358f786af49d34;hb=44bac24ba5d22fe238bd96702707eb2029efec41;hp=12f04321beb9df16b6097f9be3295eec2ff683f8;hpb=041dc07fd21b6987ffbcc6a597eb9918d44ae841;p=openvswitch diff --git a/lib/socket-util.c b/lib/socket-util.c index 12f04321..82a33c20 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ #include #include "socket-util.h" #include +#include #include #include #include @@ -81,6 +82,21 @@ set_nonblocking(int fd) } } +static int +set_dscp(int fd, uint8_t dscp) +{ + if (dscp > 63) { + return EINVAL; + } + + dscp = dscp << 2; + if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) { + return errno; + } + + return 0; +} + static bool rlim_is_finite(rlim_t limit) { @@ -458,7 +474,7 @@ error: error = EPROTO; } if (bind_path) { - fatal_signal_remove_file_to_unlink(bind_path); + fatal_signal_unlink_file_now(bind_path); } close(fd); return -error; @@ -544,10 +560,14 @@ exit: * and stores -1 into '*fdp'. * * If 'sinp' is non-null, then on success the target address is stored into - * '*sinp'. */ + * '*sinp'. + * + * 'dscp' becomes the DSCP bits in the IP headers for the new connection. It + * should be in the range [0, 63] and will automatically be shifted to the + * appropriately place in the IP tos field. */ int inet_open_active(int style, const char *target, uint16_t default_port, - struct sockaddr_in *sinp, int *fdp) + struct sockaddr_in *sinp, int *fdp, uint8_t dscp) { struct sockaddr_in sin; int fd = -1; @@ -568,31 +588,33 @@ inet_open_active(int style, const char *target, uint16_t default_port, } error = set_nonblocking(fd); if (error) { - goto exit_close; + goto exit; + } + + /* The dscp bits must be configured before connect() to ensure that the TOS + * field is set during the connection establishment. If set after + * connect(), the handshake SYN frames will be sent with a TOS of 0. */ + error = set_dscp(fd, dscp); + if (error) { + VLOG_ERR("%s: socket: %s", target, strerror(error)); + goto exit; } /* 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; + } else if (fd >= 0) { + close(fd); } + *fdp = fd; return error; } @@ -663,10 +685,14 @@ exit: * negative errno value. * * If 'sinp' is non-null, then on success the bound address is stored into - * '*sinp'. */ + * '*sinp'. + * + * 'dscp' becomes the DSCP bits in the IP headers for the new connection. It + * should be in the range [0, 63] and will automatically be shifted to the + * appropriately place in the IP tos field. */ int inet_open_passive(int style, const char *target, int default_port, - struct sockaddr_in *sinp) + struct sockaddr_in *sinp, uint8_t dscp) { struct sockaddr_in sin; int fd = 0, error; @@ -701,6 +727,15 @@ inet_open_passive(int style, const char *target, int default_port, goto error; } + /* The dscp bits must be configured before connect() to ensure that the TOS + * field is set during the connection establishment. If set after + * connect(), the handshake SYN frames will be sent with a TOS of 0. */ + error = set_dscp(fd, dscp); + if (error) { + VLOG_ERR("%s: socket: %s", target, strerror(error)); + goto error; + } + /* Listen. */ if (style == SOCK_STREAM && listen(fd, 10) < 0) { error = errno;