- kernel modules are renamed. openvswitch_mod.ko is now
openvswitch.ko and brcompat_mod.ko is now brcompat.ko.
- Increased the number of NXM registers to 8.
+ - Added ability to configure dscp setting for manager and controller
+ connections. By default, these connections have a DSCP value of
+ Internetwork Control (0xc0).
v1.6.0 - xx xxx xxxx
#define IPPROTO_NONE 59
#define IPPROTO_DSTOPTS 60
+/* All the IP options documented in Linux ip(7). */
+#define IP_ADD_MEMBERSHIP 0
+#define IP_DROP_MEMBERSHIP 1
+#define IP_HDRINCL 2
+#define IP_MTU 3
+#define IP_MTU_DISCOVER 4
+#define IP_MULTICAST_IF 5
+#define IP_MULTICAST_LOOP 6
+#define IP_MULTICAST_TTL 7
+#define IP_NODEFRAG 8
+#define IP_OPTIONS 9
+#define IP_PKTINFO 10
+#define IP_RECVERR 11
+#define IP_RECVOPTS 12
+#define IP_RECVTOS 13
+#define IP_RECVTTL 14
+#define IP_RETOPTS 15
+#define IP_ROUTER_ALERT 16
+#define IP_TOS 17
+#define IP_TTL 18
+
#define INADDR_ANY 0x00000000
#define INADDR_BROADCAST 0xffffffff
#define INADDR_NONE 0xffffffff
/* This is just the same as stream_open() except that it uses the default
* JSONRPC ports if none is specified. */
int
-jsonrpc_stream_open(const char *name, struct stream **streamp)
+jsonrpc_stream_open(const char *name, struct stream **streamp, uint8_t dscp)
{
return stream_open_with_default_ports(name, JSONRPC_TCP_PORT,
- JSONRPC_SSL_PORT, streamp);
+ JSONRPC_SSL_PORT, streamp,
+ dscp);
}
/* This is just the same as pstream_open() except that it uses the default
* JSONRPC ports if none is specified. */
int
-jsonrpc_pstream_open(const char *name, struct pstream **pstreamp)
+jsonrpc_pstream_open(const char *name, struct pstream **pstreamp, uint8_t dscp)
{
return pstream_open_with_default_ports(name, JSONRPC_TCP_PORT,
- JSONRPC_SSL_PORT, pstreamp);
+ JSONRPC_SSL_PORT, pstreamp, dscp);
}
/* Returns a new JSON-RPC stream that uses 'stream' for input and output. The
jsonrpc_session_disconnect(s);
if (!reconnect_is_passive(s->reconnect)) {
- error = jsonrpc_stream_open(name, &s->stream);
+ error = jsonrpc_stream_open(name, &s->stream,
+ reconnect_get_dscp(s->reconnect));
if (!error) {
reconnect_connecting(s->reconnect, time_msec());
}
} else {
- error = s->pstream ? 0 : jsonrpc_pstream_open(name, &s->pstream);
+ error = s->pstream ? 0 : jsonrpc_pstream_open(name, &s->pstream,
+ reconnect_get_dscp(s->reconnect));
if (!error) {
reconnect_listening(s->reconnect, time_msec());
}
{
reconnect_set_probe_interval(s->reconnect, probe_interval);
}
+
+void
+jsonrpc_session_set_dscp(struct jsonrpc_session *s,
+ uint8_t dscp)
+{
+ reconnect_set_dscp(s->reconnect, dscp);
+}
#include <stdbool.h>
#include <stddef.h>
+#include "openvswitch/types.h"
struct json;
struct jsonrpc_msg;
#define JSONRPC_TCP_PORT 6632
#define JSONRPC_SSL_PORT 6632
-int jsonrpc_stream_open(const char *name, struct stream **);
-int jsonrpc_pstream_open(const char *name, struct pstream **);
+int jsonrpc_stream_open(const char *name, struct stream **, uint8_t dscp);
+int jsonrpc_pstream_open(const char *name, struct pstream **, uint8_t dscp);
struct jsonrpc *jsonrpc_open(struct stream *);
void jsonrpc_close(struct jsonrpc *);
int max_backofF);
void jsonrpc_session_set_probe_interval(struct jsonrpc_session *,
int probe_interval);
+void jsonrpc_session_set_dscp(struct jsonrpc_session *,
+ uint8_t dscp);
#endif /* jsonrpc.h */
#include <linux/gen_stats.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
-#include <linux/ip.h>
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
* attempt to the next. */
ovs_be32 local_ip, remote_ip;
ovs_be16 remote_port;
+ uint8_t dscp;
/* Messages sent or received are copied to the monitor connections. */
#define MAX_MONITORS 8
* The new rconn is initially unconnected. Use rconn_connect() or
* rconn_connect_unreliably() to connect it. */
struct rconn *
-rconn_create(int probe_interval, int max_backoff)
+rconn_create(int probe_interval, int max_backoff, uint8_t dscp)
{
struct rconn *rc = xzalloc(sizeof *rc);
rc->total_time_connected = 0;
rconn_set_probe_interval(rc, probe_interval);
+ rconn_set_dscp(rc, dscp);
rc->n_monitors = 0;
return rc->max_backoff;
}
+void
+rconn_set_dscp(struct rconn *rc, uint8_t dscp)
+{
+ rc->dscp = dscp;
+}
+
void
rconn_set_probe_interval(struct rconn *rc, int probe_interval)
{
VLOG_INFO("%s: connecting...", rc->name);
}
rc->n_attempted_connections++;
- retval = vconn_open(rc->target, OFP10_VERSION, &rc->vconn);
+ retval = vconn_open(rc->target, OFP10_VERSION, &rc->vconn, rc->dscp);
if (!retval) {
rc->remote_ip = vconn_get_remote_ip(rc->vconn);
rc->local_ip = vconn_get_local_ip(rc->vconn);
struct vconn;
struct rconn_packet_counter;
-struct rconn *rconn_create(int inactivity_probe_interval, int max_backoff);
-
+struct rconn *rconn_create(int inactivity_probe_interval,
+ int max_backoff, uint8_t dscp);
+void rconn_set_dscp(struct rconn *rc, uint8_t dscp);
void rconn_set_max_backoff(struct rconn *, int max_backoff);
int rconn_get_max_backoff(const struct rconn *);
void rconn_set_probe_interval(struct rconn *, int inactivity_probe_interval);
bool passive;
enum vlog_level info; /* Used for informational messages. */
+ uint8_t dscp;
+
/* State. */
enum state state;
long long int state_entered;
return fsm->probe_interval;
}
+/* Returns the dscp value used for establishing the connection between the
+ * manager and the database. */
+uint8_t
+reconnect_get_dscp(const struct reconnect *fsm)
+{
+ return fsm->dscp;
+}
+
/* Limits the maximum number of times that 'fsm' will ask the client to try to
* reconnect to 'max_tries'. UINT_MAX (the default) means an unlimited number
* of tries.
fsm->probe_interval = probe_interval ? MAX(1000, probe_interval) : 0;
}
+/* Sets the dscp value to be used for establishing a connection between the
+ * manager and the database. */
+void
+reconnect_set_dscp(struct reconnect *fsm, uint8_t dscp)
+{
+ fsm->dscp = dscp;
+}
+
/* Returns true if 'fsm' is in passive mode, false if 'fsm' is in active mode
* (the default). */
bool
* revisited later.) */
#include <stdbool.h>
+#include "openvswitch/types.h"
struct reconnect *reconnect_create(long long int now);
void reconnect_destroy(struct reconnect *);
int reconnect_get_min_backoff(const struct reconnect *);
int reconnect_get_max_backoff(const struct reconnect *);
int reconnect_get_probe_interval(const struct reconnect *);
+uint8_t reconnect_get_dscp(const struct reconnect *);
void reconnect_set_max_tries(struct reconnect *, unsigned int max_tries);
unsigned int reconnect_get_max_tries(struct reconnect *);
void reconnect_set_backoff(struct reconnect *,
int min_backoff, int max_backoff);
void reconnect_set_probe_interval(struct reconnect *, int probe_interval);
+void reconnect_set_dscp(struct reconnect *, uint8_t dscp);
bool reconnect_is_passive(const struct reconnect *);
void reconnect_set_passive(struct reconnect *, bool passive,
* and stores -1 into '*fdp'.
*
* If 'sinp' is non-null, then on success the target address is stored into
- * '*sinp'. */
+ * '*sinp'.
+ *
+ * 'dscp' If not DSCP_INVALID, its value becomes the DSCP bits in the IP
+ * headers for the new connection. */
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;
goto exit_close;
}
+ /* The socket options set here ensure that the TOS bits are set during
+ * the connection establishment. If set after connect(), the handshake
+ * SYN frames will be sent with a TOS of 0. */
+ if (dscp != DSCP_INVALID) {
+ if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) {
+ VLOG_ERR("%s: socket: %s", target, strerror(errno));
+ error = errno;
+ goto exit;
+ }
+ }
+
/* Connect. */
error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
if (error == EINPROGRESS) {
* negative errno value.
*
* If 'sinp' is non-null, then on success the bound address is stored into
- * '*sinp'. */
+ * '*sinp'.
+ *
+ * 'dscp' If not DSCP_INVALID, its value becomes the DSCP bits in the IP
+ * headers for the new connection. */
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;
goto error;
}
+ /* The socket options set here ensure that the TOS bits are set during
+ * the connection establishment. If set after connect(), the handshake
+ * SYN frames will be sent with a TOS of 0. */
+ if (dscp != DSCP_INVALID) {
+ if (setsockopt(fd, IPPROTO_IP, IP_TOS, &dscp, sizeof dscp)) {
+ VLOG_ERR("%s: socket: %s", target, strerror(errno));
+ error = errno;
+ goto error;
+ }
+ }
+
/* Listen. */
if (style == SOCK_STREAM && listen(fd, 10) < 0) {
error = errno;
#include <netinet/in.h>
#include <stdbool.h>
#include "openvswitch/types.h"
+#include <netinet/ip.h>
int set_nonblocking(int fd);
int get_max_fds(void);
bool inet_parse_active(const char *target, uint16_t default_port,
struct sockaddr_in *sinp);
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);
bool inet_parse_passive(const char *target, int default_port,
struct sockaddr_in *sinp);
int inet_open_passive(int style, const char *target, int default_port,
- struct sockaddr_in *sinp);
+ struct sockaddr_in *sinp, uint8_t dscp);
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);
char *describe_fd(int fd);
+/* Default value of dscp bits for connection between controller and manager.
+ * Value of IPTOS_PREC_INTERNETCONTROL = 0xc0 which is defined
+ * in <netinet/ip.h> is used. */
+#define DSCP_DEFAULT IPTOS_PREC_INTERNETCONTROL
+
+/* Invalid dscp value. If the dscp value will not be used, the dscp value
+ * passed must be invalid. Set to 0xFF as the TOS bits passed can only be
+ * 6 bits. */
+#define DSCP_INVALID 0xFF
+
#endif /* socket-util.h */
void stream_init(struct stream *, const struct stream_class *,
int connect_status, const char *name);
void stream_set_remote_ip(struct stream *, ovs_be32 remote_ip);
+void stream_set_dscp(struct stream *, uint8_t dscp);
void stream_set_remote_port(struct stream *, ovs_be16 remote_port);
void stream_set_local_ip(struct stream *, ovs_be32 local_ip);
void stream_set_local_port(struct stream *, ovs_be16 local_port);
* messages but must not be modified.
*
* 'suffix' is a copy of 'name' following the colon and may be modified.
+ * 'dscp' is the DSCP value that the new connection should use in the IP
+ * packets it sends. (If no DSCP value should be set in the packet, dscp
+ * will be set to DSCP_INVALID. If no DSCP value is specified, DSCP_DEFAULT
+ * value will be applied.)
*
* Returns 0 if successful, otherwise a positive errno value. If
* successful, stores a pointer to the new connection in '*streamp'.
* If the connection cannot be completed immediately, it should return
* EAGAIN (not EINPROGRESS, as returned by the connect system call) and
* continue the connection in the background. */
- int (*open)(const char *name, char *suffix, struct stream **streamp);
+ int (*open)(const char *name, char *suffix, struct stream **streamp,
+ uint8_t dscp);
/* Closes 'stream' and frees associated memory. */
void (*close)(struct stream *stream);
* useful for error messages but must not be modified.
*
* 'suffix' is a copy of 'name' following the colon and may be modified.
+ * 'dscp' is the DSCP value that the new connection should use in the IP
+ * packets it sends. (If no DSCP value should be set in the packet, dscp
+ * will be set to DSCP_INVALID. If no DSCP value is specified, DSCP_DEFAULT
+ * value will be applied.)
*
* Returns 0 if successful, otherwise a positive errno value. If
* successful, stores a pointer to the new connection in '*pstreamp'.
* completed immediately, it should return EAGAIN (not EINPROGRESS, as
* returned by the connect system call) and continue the connection in the
* background. */
- int (*listen)(const char *name, char *suffix, struct pstream **pstreamp);
+ int (*listen)(const char *name, char *suffix, struct pstream **pstreamp,
+ uint8_t dscp);
/* Closes 'pstream' and frees associated memory. */
void (*close)(struct pstream *pstream);
static int
new_ssl_stream(const char *name, int fd, enum session_type type,
- enum ssl_state state, const struct sockaddr_in *remote,
- struct stream **streamp)
+ enum ssl_state state, const struct sockaddr_in *remote,
+ struct stream **streamp)
{
struct sockaddr_in local;
socklen_t local_len = sizeof local;
}
static int
-ssl_open(const char *name, char *suffix, struct stream **streamp)
+ssl_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
{
struct sockaddr_in sin;
int error, fd;
return error;
}
- error = inet_open_active(SOCK_STREAM, suffix, OFP_SSL_PORT, &sin, &fd);
+ error = inet_open_active(SOCK_STREAM, suffix, OFP_SSL_PORT, &sin, &fd,
+ dscp);
if (fd >= 0) {
int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING;
return new_ssl_stream(name, fd, CLIENT, state, &sin, streamp);
}
static int
-pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp)
+pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
+ uint8_t dscp)
{
struct pssl_pstream *pssl;
struct sockaddr_in sin;
return retval;
}
- fd = inet_open_passive(SOCK_STREAM, suffix, OFP_SSL_PORT, &sin);
+ fd = inet_open_passive(SOCK_STREAM, suffix, OFP_SSL_PORT, &sin, dscp);
if (fd < 0) {
return -fd;
}
sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin.sin_port));
}
return new_ssl_stream(name, new_fd, SERVER, STATE_SSL_CONNECTING, &sin,
- new_streamp);
+ new_streamp);
}
static void
static int
new_tcp_stream(const char *name, int fd, int connect_status,
- const struct sockaddr_in *remote, struct stream **streamp)
+ const struct sockaddr_in *remote, struct stream **streamp)
{
struct sockaddr_in local;
socklen_t local_len = sizeof local;
}
static int
-tcp_open(const char *name, char *suffix, struct stream **streamp)
+tcp_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
{
struct sockaddr_in sin;
int fd, error;
- error = inet_open_active(SOCK_STREAM, suffix, 0, &sin, &fd);
+ error = inet_open_active(SOCK_STREAM, suffix, 0, &sin, &fd, dscp);
if (fd >= 0) {
return new_tcp_stream(name, fd, error, &sin, streamp);
} else {
struct stream **streamp);
static int
-ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp)
+ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
+ uint8_t dscp)
{
struct sockaddr_in sin;
char bound_name[128];
int fd;
- fd = inet_open_passive(SOCK_STREAM, suffix, -1, &sin);
+ fd = inet_open_passive(SOCK_STREAM, suffix, -1, &sin, dscp);
if (fd < 0) {
return -fd;
}
/* Active UNIX socket. */
static int
-unix_open(const char *name, char *suffix, struct stream **streamp)
+unix_open(const char *name, char *suffix, struct stream **streamp,
+ uint8_t dscp OVS_UNUSED)
{
const char *connect_path = suffix;
int fd;
static int
punix_open(const char *name OVS_UNUSED, char *suffix,
- struct pstream **pstreamp)
+ struct pstream **pstreamp, uint8_t dscp OVS_UNUSED)
{
int fd, error;
* stores a pointer to the new connection in '*streamp', otherwise a null
* pointer. */
int
-stream_open(const char *name, struct stream **streamp)
+stream_open(const char *name, struct stream **streamp, uint8_t dscp)
{
const struct stream_class *class;
struct stream *stream;
/* Call class's "open" function. */
suffix_copy = xstrdup(strchr(name, ':') + 1);
- error = class->open(name, suffix_copy, &stream);
+ error = class->open(name, suffix_copy, &stream, dscp);
free(suffix_copy);
if (error) {
goto error;
* stores a pointer to the new connection in '*pstreamp', otherwise a null
* pointer. */
int
-pstream_open(const char *name, struct pstream **pstreamp)
+pstream_open(const char *name, struct pstream **pstreamp, uint8_t dscp)
{
const struct pstream_class *class;
struct pstream *pstream;
/* Call class's "open" function. */
suffix_copy = xstrdup(strchr(name, ':') + 1);
- error = class->listen(name, suffix_copy, &pstream);
+ error = class->listen(name, suffix_copy, &pstream, dscp);
free(suffix_copy);
if (error) {
goto error;
stream_open_with_default_ports(const char *name_,
uint16_t default_tcp_port,
uint16_t default_ssl_port,
- struct stream **streamp)
+ struct stream **streamp,
+ uint8_t dscp)
{
char *name;
int error;
} else {
name = xstrdup(name_);
}
- error = stream_open(name, streamp);
+ error = stream_open(name, streamp, dscp);
free(name);
return error;
pstream_open_with_default_ports(const char *name_,
uint16_t default_ptcp_port,
uint16_t default_pssl_port,
- struct pstream **pstreamp)
+ struct pstream **pstreamp,
+ uint8_t dscp)
{
char *name;
int error;
} else {
name = xstrdup(name_);
}
- error = pstream_open(name, pstreamp);
+ error = pstream_open(name, pstreamp, dscp);
free(name);
return error;
/* Bidirectional byte streams. */
int stream_verify_name(const char *name);
-int stream_open(const char *name, struct stream **);
+int stream_open(const char *name, struct stream **, uint8_t dscp);
int stream_open_block(int error, struct stream **);
void stream_close(struct stream *);
const char *stream_get_name(const struct stream *);
/* Passive streams: listeners for incoming stream connections. */
int pstream_verify_name(const char *name);
-int pstream_open(const char *name, struct pstream **);
+int pstream_open(const char *name, struct pstream **, uint8_t dscp);
const char *pstream_get_name(const struct pstream *);
void pstream_close(struct pstream *);
int pstream_accept(struct pstream *, struct stream **);
int stream_open_with_default_ports(const char *name,
uint16_t default_tcp_port,
uint16_t default_ssl_port,
- struct stream **);
+ struct stream **,
+ uint8_t dscp);
int pstream_open_with_default_ports(const char *name,
uint16_t default_ptcp_port,
uint16_t default_pssl_port,
- struct pstream **);
+ struct pstream **,
+ uint8_t dscp);
bool stream_parse_target_with_default_ports(const char *target,
uint16_t default_tcp_port,
uint16_t default_ssl_port,
program_name, (long int) getpid());
}
- error = pstream_open(punix_path, &listener);
+ error = pstream_open(punix_path, &listener, DSCP_INVALID);
if (error) {
ovs_error(error, "could not initialize control socket %s", punix_path);
goto exit;
abs_path = abs_file_name(ovs_rundir(), path);
unix_path = xasprintf("unix:%s", abs_path);
- error = stream_open_block(stream_open(unix_path, &stream), &stream);
+ error = stream_open_block(stream_open(unix_path, &stream, DSCP_DEFAULT),
+ &stream);
free(unix_path);
free(abs_path);
* useful for error messages but must not be modified.
*
* 'suffix' is a copy of 'name' following the colon and may be modified.
+ * 'dscp' is the DSCP value that the new connection should use in the IP
+ * packets it sends. (If no DSCP value should be set in the packet, dscp
+ * will be set to DSCP_INVALID. If no DSCP value is specified, DSCP_DEFAULT
+ * value will be applied.)
*
* Returns 0 if successful, otherwise a positive errno value. If
* successful, stores a pointer to the new connection in '*vconnp'.
* If the connection cannot be completed immediately, it should return
* EAGAIN (not EINPROGRESS, as returned by the connect system call) and
* continue the connection in the background. */
- int (*open)(const char *name, char *suffix, struct vconn **vconnp);
+ int (*open)(const char *name, char *suffix, struct vconn **vconnp,
+ uint8_t dscp);
/* Closes 'vconn' and frees associated memory. */
void (*close)(struct vconn *vconn);
* is useful for error messages but must not be modified.
*
* 'suffix' is a copy of 'name' following the colon and may be modified.
+ * 'dscp' is the DSCP value that the new connection should use in the IP
+ * packets it sends. (If no DSCP value should be set in the packet, dscp
+ * will be set to DSCP_INVALID. If no DSCP value is specified, DSCP_DEFAULT
+ * value will be applied.)
*
* Returns 0 if successful, otherwise a positive errno value. If
* successful, stores a pointer to the new connection in '*pvconnp'.
* completed immediately, it should return EAGAIN (not EINPROGRESS, as
* returned by the connect system call) and continue the connection in the
* background. */
- int (*listen)(const char *name, char *suffix, struct pvconn **pvconnp);
+ int (*listen)(const char *name, char *suffix, struct pvconn **pvconnp,
+ uint8_t dscp);
/* Closes 'pvconn' and frees associated memory. */
void (*close)(struct pvconn *pvconn);
* Returns 0 if successful, otherwise a positive errno value. */
static int
vconn_stream_open(const char *name, char *suffix OVS_UNUSED,
- struct vconn **vconnp)
+ struct vconn **vconnp, uint8_t dscp)
{
struct stream *stream;
int error;
error = stream_open_with_default_ports(name, OFP_TCP_PORT, OFP_SSL_PORT,
- &stream);
+ &stream, dscp);
if (!error) {
error = stream_connect(stream);
if (!error || error == EAGAIN) {
* implementation never fails.) */
static int
pvconn_pstream_listen(const char *name, char *suffix OVS_UNUSED,
- struct pvconn **pvconnp)
+ struct pvconn **pvconnp, uint8_t dscp)
{
struct pvconn_pstream *ps;
struct pstream *pstream;
int error;
error = pstream_open_with_default_ports(name, OFP_TCP_PORT, OFP_SSL_PORT,
- &pstream);
+ &pstream, dscp);
if (error) {
return error;
}
#include "random.h"
#include "util.h"
#include "vlog.h"
+#include "socket-util.h"
VLOG_DEFINE_THIS_MODULE(vconn);
* stores a pointer to the new connection in '*vconnp', otherwise a null
* pointer. */
int
-vconn_open(const char *name, int min_version, struct vconn **vconnp)
+vconn_open(const char *name, int min_version, struct vconn **vconnp,
+ uint8_t dscp)
{
struct vconn_class *class;
struct vconn *vconn;
/* Call class's "open" function. */
suffix_copy = xstrdup(strchr(name, ':') + 1);
- error = class->open(name, suffix_copy, &vconn);
+ error = class->open(name, suffix_copy, &vconn, dscp);
free(suffix_copy);
if (error) {
goto error;
fatal_signal_run();
- error = vconn_open(name, min_version, &vconn);
+ error = vconn_open(name, min_version, &vconn, DSCP_DEFAULT);
if (!error) {
while ((error = vconn_connect(vconn)) == EAGAIN) {
vconn_run(vconn);
* stores a pointer to the new connection in '*pvconnp', otherwise a null
* pointer. */
int
-pvconn_open(const char *name, struct pvconn **pvconnp)
+pvconn_open(const char *name, struct pvconn **pvconnp, uint8_t dscp)
{
struct pvconn_class *class;
struct pvconn *pvconn;
/* Call class's "open" function. */
suffix_copy = xstrdup(strchr(name, ':') + 1);
- error = class->listen(name, suffix_copy, &pvconn);
+ error = class->listen(name, suffix_copy, &pvconn, dscp);
free(suffix_copy);
if (error) {
goto error;
/* Active vconns: virtual connections to OpenFlow devices. */
int vconn_verify_name(const char *name);
-int vconn_open(const char *name, int min_version, struct vconn **);
+int vconn_open(const char *name, int min_version,
+ struct vconn **, uint8_t dscp);
void vconn_close(struct vconn *);
const char *vconn_get_name(const struct vconn *);
ovs_be32 vconn_get_remote_ip(const struct vconn *);
/* Passive vconns: virtual listeners for incoming OpenFlow connections. */
int pvconn_verify_name(const char *name);
-int pvconn_open(const char *name, struct pvconn **);
+int pvconn_open(const char *name, struct pvconn **, uint8_t dscp);
const char *pvconn_get_name(const struct pvconn *);
void pvconn_close(struct pvconn *);
int pvconn_accept(struct pvconn *, int min_version, struct vconn **);
int error;
int fd;
- error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd);
+ error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd,
+ DSCP_INVALID);
if (fd >= 0) {
c->fds[c->n_fds++] = fd;
} else {
int rate_limit; /* Max packet-in rate in packets per second. */
int burst_limit; /* Limit on accumulating packet credits. */
bool enable_async_msgs; /* Initially enable async messages? */
+ uint8_t dscp; /* DSCP Value for controller connection */
};
static void ofservice_reconfigure(struct ofservice *,
const struct ofproto_controller *);
-static int ofservice_create(struct connmgr *, const char *target);
+static int ofservice_create(struct connmgr *, const char *target, uint8_t dscp);
static void ofservice_destroy(struct connmgr *, struct ofservice *);
static struct ofservice *ofservice_lookup(struct connmgr *,
const char *target);
struct rconn *rconn;
char *name;
- rconn = rconn_create(ofservice->probe_interval, 0);
+ /* Passing default value for creation of the rconn */
+ rconn = rconn_create(ofservice->probe_interval, 0, ofservice->dscp);
name = ofconn_make_name(mgr, vconn_get_name(vconn));
rconn_connect_unreliably(rconn, vconn, name);
free(name);
\f
/* OpenFlow configuration. */
-static void add_controller(struct connmgr *, const char *target);
+static void add_controller(struct connmgr *, const char *target, uint8_t dscp);
static struct ofconn *find_controller_by_target(struct connmgr *,
const char *target);
static void update_fail_open(struct connmgr *);
if (!vconn_verify_name(c->target)) {
if (!find_controller_by_target(mgr, c->target)) {
- add_controller(mgr, c->target);
+ add_controller(mgr, c->target, c->dscp);
}
} else if (!pvconn_verify_name(c->target)) {
if (!ofservice_lookup(mgr, c->target)) {
- ofservice_create(mgr, c->target);
+ ofservice_create(mgr, c->target, c->dscp);
}
} else {
VLOG_WARN_RL(&rl, "%s: unsupported controller \"%s\"",
/* Creates a new controller for 'target' in 'mgr'. update_controller() needs
* to be called later to finish the new ofconn's configuration. */
static void
-add_controller(struct connmgr *mgr, const char *target)
+add_controller(struct connmgr *mgr, const char *target, uint8_t dscp)
{
char *name = ofconn_make_name(mgr, target);
struct ofconn *ofconn;
- ofconn = ofconn_create(mgr, rconn_create(5, 8), OFCONN_PRIMARY, true);
+ ofconn = ofconn_create(mgr, rconn_create(5, 8, dscp), OFCONN_PRIMARY, true);
ofconn->pktbuf = pktbuf_create();
rconn_connect(ofconn->rconn, target, name);
hmap_insert(&mgr->controllers, &ofconn->hmap_node, hash_string(target, 0));
struct pvconn *pvconn;
int error;
- error = pvconn_open(name, &pvconn);
+ error = pvconn_open(name, &pvconn, DSCP_INVALID);
if (!error) {
pvconns[n_pvconns++] = pvconn;
} else {
* ofservice_reconfigure() must be called to fully configure the new
* ofservice. */
static int
-ofservice_create(struct connmgr *mgr, const char *target)
+ofservice_create(struct connmgr *mgr, const char *target, uint8_t dscp)
{
struct ofservice *ofservice;
struct pvconn *pvconn;
int error;
- error = pvconn_open(target, &pvconn);
+ error = pvconn_open(target, &pvconn, dscp);
if (error) {
return error;
}
ofservice->rate_limit = c->rate_limit;
ofservice->burst_limit = c->burst_limit;
ofservice->enable_async_msgs = c->enable_async_msgs;
+ ofservice->dscp = c->dscp;
}
/* Finds and returns the ofservice within 'mgr' that has the given
/* OpenFlow packet-in rate-limiting. */
int rate_limit; /* Max packet-in rate in packets per second. */
int burst_limit; /* Limit on accumulating packet credits. */
+
+ uint8_t dscp; /* DSCP value for controller connection. */
};
#define DEFAULT_MFR_DESC "Nicira Networks, Inc."
};
static struct ovsdb_jsonrpc_remote *ovsdb_jsonrpc_server_add_remote(
- struct ovsdb_jsonrpc_server *, const char *name);
+ struct ovsdb_jsonrpc_server *, const char *name,
+ const struct ovsdb_jsonrpc_options *options
+);
static void ovsdb_jsonrpc_server_del_remote(struct shash_node *);
struct ovsdb_jsonrpc_server *
remote = shash_find_data(&svr->remotes, node->name);
if (!remote) {
- remote = ovsdb_jsonrpc_server_add_remote(svr, node->name);
+ remote = ovsdb_jsonrpc_server_add_remote(svr, node->name, options);
if (!remote) {
continue;
}
static struct ovsdb_jsonrpc_remote *
ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
- const char *name)
+ const char *name,
+ const struct ovsdb_jsonrpc_options *options)
{
struct ovsdb_jsonrpc_remote *remote;
struct pstream *listener;
int error;
- error = jsonrpc_pstream_open(name, &listener);
+ error = jsonrpc_pstream_open(name, &listener, options->dscp);
if (error && error != EAFNOSUPPORT) {
VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, strerror(error));
return NULL;
{
jsonrpc_session_set_max_backoff(session->js, options->max_backoff);
jsonrpc_session_set_probe_interval(session->js, options->probe_interval);
+ jsonrpc_session_set_dscp(session->js, options->dscp);
}
static void
struct ovsdb_jsonrpc_options {
int max_backoff; /* Maximum reconnection backoff, in msec. */
int probe_interval; /* Max idle time before probing, in msec. */
+ int dscp; /* Dscp value for manager connections */
};
struct ovsdb_jsonrpc_options *ovsdb_jsonrpc_default_options(void);
struct stream *stream;
int error;
- error = stream_open_block(jsonrpc_stream_open(server, &stream), &stream);
+ error = stream_open_block(jsonrpc_stream_open(server, &stream,
+ DSCP_DEFAULT), &stream);
if (error == EAFNOSUPPORT) {
struct pstream *pstream;
- error = jsonrpc_pstream_open(server, &pstream);
+ error = jsonrpc_pstream_open(server, &pstream, DSCP_DEFAULT);
if (error) {
ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
}
return &row->fields[column->index];
}
+/* This function is used to read the string-string key-values from a map.
+ * Returns the true if the 'key' is found and returns the "value" associated
+ * with the 'key' in 'stringp', else returns false. */
+static bool
+read_map_string_column(const struct ovsdb_row *row, const char *column_name,
+ const char **stringp, const char *key)
+{
+ const struct ovsdb_datum *datum;
+ union ovsdb_atom *atom_key = NULL, *atom_value = NULL;
+ size_t i;
+
+ datum = get_datum((struct ovsdb_row *) row, column_name, OVSDB_TYPE_STRING,
+ OVSDB_TYPE_STRING, UINT_MAX);
+
+ if (!datum) {
+ *stringp = NULL;
+ return false;
+ }
+
+ for (i = 0; i < datum->n; i++) {
+ atom_key = &datum->keys[i];
+ if (!strcmp(atom_key->string, key)){
+ atom_value = &datum->values[i];
+ break;
+ }
+ }
+
+ *stringp = atom_value ? atom_value->string : NULL;
+ return atom_value != NULL;
+}
+
static const union ovsdb_atom *
read_column(const struct ovsdb_row *row, const char *column_name,
enum ovsdb_atomic_type type)
{
const struct ovsdb_datum *datum;
- datum = get_datum((struct ovsdb_row *) row, column_name, type, OVSDB_TYPE_VOID, 1);
+ datum = get_datum((struct ovsdb_row *) row, column_name, type, OVSDB_TYPE_VOID,
+ 1);
return datum && datum->n ? datum->keys : NULL;
}
ovsdb_datum_sort_assert(datum, column->type.key.type);
}
+/* Get the other config for the manager from the database. */
+static void
+manager_get_other_config(const struct ovsdb_row *row,
+ struct ovsdb_jsonrpc_options *options)
+{
+ const char *temp_string;
+
+ /* Retrieve the configs and store in the options. */
+ if (read_map_string_column(row, "other_config", &temp_string, "dscp")) {
+ options->dscp = atoi(temp_string);
+ } else {
+ options->dscp = DSCP_DEFAULT;
+ }
+}
+
/* Adds a remote and options to 'remotes', based on the Manager table row in
* 'row'. */
static void
if (read_integer_column(row, "inactivity_probe", &probe_interval)) {
options->probe_interval = probe_interval;
}
+
+ manager_get_other_config(row, options);
}
static void
bool done;
int error;
- error = jsonrpc_pstream_open(argv[1], &pstream);
+ error = jsonrpc_pstream_open(argv[1], &pstream, DSCP_DEFAULT);
if (error) {
ovs_fatal(error, "could not listen on \"%s\"", argv[1]);
}
ovs_fatal(0, "not a valid JSON-RPC request: %s", string);
}
- error = stream_open_block(jsonrpc_stream_open(argv[1], &stream), &stream);
+ error = stream_open_block(jsonrpc_stream_open(argv[1], &stream,
+ DSCP_DEFAULT), &stream);
if (error) {
ovs_fatal(error, "could not open \"%s\"", argv[1]);
}
ovs_fatal(0, "not a JSON RPC-valid notification: %s", string);
}
- error = stream_open_block(jsonrpc_stream_open(argv[1], &stream), &stream);
+ error = stream_open_block(jsonrpc_stream_open(argv[1], &stream,
+ DSCP_DEFAULT), &stream);
if (error) {
ovs_fatal(error, "could not open \"%s\"", argv[1]);
}
}
target = argv[optind];
- sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL);
+ sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL, DSCP_INVALID);
if (sock < 0) {
ovs_fatal(0, "%s: failed to open (%s)", argv[1], strerror(-sock));
}
if (argc > 2) {
struct stream *stream;
- error = stream_open_block(jsonrpc_stream_open(argv[1], &stream),
- &stream);
+ error = stream_open_block(jsonrpc_stream_open(argv[1], &stream,
+ DSCP_DEFAULT), &stream);
if (error) {
ovs_fatal(error, "failed to connect to \"%s\"", argv[1]);
}
bind_path = xasprintf("fake-pvconn.%d", unix_count++);
fpv->pvconn_name = xasprintf("punix:%s", bind_path);
fpv->vconn_name = xasprintf("unix:%s", bind_path);
- CHECK_ERRNO(pstream_open(fpv->pvconn_name, &fpv->pstream), 0);
+ CHECK_ERRNO(pstream_open(fpv->pvconn_name, &fpv->pstream,
+ DSCP_DEFAULT), 0);
free(bind_path);
} else if (!strcmp(type, "tcp") || !strcmp(type, "ssl")) {
char *s, *port, *save_ptr = NULL;
char *open_name;
open_name = xasprintf("p%s:0:127.0.0.1", type);
- CHECK_ERRNO(pstream_open(open_name, &fpv->pstream), 0);
+ CHECK_ERRNO(pstream_open(open_name, &fpv->pstream, DSCP_DEFAULT), 0);
/* Extract bound port number from pstream name. */
s = xstrdup(pstream_get_name(fpv->pstream));
: EPROTO);
fpv_create(type, &fpv);
- CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn), 0);
+ CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
+ DSCP_DEFAULT), 0);
fpv_close(&fpv);
vconn_run(vconn);
CHECK_ERRNO(vconn_connect(vconn), expected_error);
: EPROTO);
fpv_create(type, &fpv);
- CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn), 0);
+ CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
+ DSCP_DEFAULT), 0);
vconn_run(vconn);
stream_close(fpv_accept(&fpv));
fpv_close(&fpv);
struct stream *stream;
fpv_create(type, &fpv);
- CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn), 0);
+ CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
+ DSCP_DEFAULT), 0);
vconn_run(vconn);
stream = fpv_accept(&fpv);
fpv_destroy(&fpv);
size_t n_sent;
fpv_create(type, &fpv);
- CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn), 0);
+ CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
+ DSCP_DEFAULT), 0);
vconn_run(vconn);
stream = fpv_accept(&fpv);
fpv_destroy(&fpv);
#include "util.h"
#include "vconn.h"
#include "vlog.h"
+#include "socket-util.h"
VLOG_DEFINE_THIS_MODULE(controller);
const char *name = argv[i];
struct vconn *vconn;
- retval = vconn_open(name, OFP10_VERSION, &vconn);
+ retval = vconn_open(name, OFP10_VERSION, &vconn, DSCP_DEFAULT);
if (!retval) {
if (n_switches >= MAX_SWITCHES) {
ovs_fatal(0, "max %d switch connections", n_switches);
continue;
} else if (retval == EAFNOSUPPORT) {
struct pvconn *pvconn;
- retval = pvconn_open(name, &pvconn);
+ retval = pvconn_open(name, &pvconn, DSCP_DEFAULT);
if (!retval) {
if (n_listeners >= MAX_LISTENERS) {
ovs_fatal(0, "max %d passive connections", n_listeners);
{
struct lswitch_config cfg;
- sw->rconn = rconn_create(60, 0);
+ sw->rconn = rconn_create(60, 0, DSCP_DEFAULT);
rconn_connect_unreliably(sw->rconn, vconn, NULL);
cfg.mode = (action_normal ? LSW_NORMAL
static void iface_refresh_stats(struct iface *);
static void iface_refresh_status(struct iface *);
static bool iface_is_synthetic(const struct iface *);
-
static void shash_from_ovs_idl_map(char **keys, char **values, size_t n,
struct shash *);
static void shash_to_ovs_idl_map(struct shash *,
bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c,
struct ofproto_controller *oc)
{
+ const char *config_str;
+
oc->target = c->target;
oc->max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8;
oc->probe_interval = c->inactivity_probe ? *c->inactivity_probe / 1000 : 5;
? *c->controller_burst_limit : 0);
oc->enable_async_msgs = (!c->enable_async_messages
|| *c->enable_async_messages);
+ config_str = ovsrec_controller_get_other_config_value(c, "dscp", NULL);
+ if (config_str) {
+ oc->dscp = atoi(config_str);
+ } else {
+ oc->dscp = DSCP_DEFAULT;
+ }
}
/* Configures the IP stack for 'br''s local interface properly according to the
{
return ovsdb_idl_row_is_synthetic(&iface->cfg->header_);
}
+
\f
/* Port mirroring. */
{"name": "Open_vSwitch",
"version": "6.8.0",
- "cksum": "1404093776 16263",
+ "cksum": "4106006492 16485",
"tables": {
"Open_vSwitch": {
"columns": {
"type": {"key": {"type": "integer",
"minInteger": 25},
"min": 0, "max": 1}},
+ "other_config": {
+ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"type": {"key": {"type": "string",
"enum": ["set", ["in-band", "out-of-band"]]},
"min": 0, "max": 1}},
+ "other_config": {
+ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
</column>
</group>
+ <group title="Connection Parameters">
+ <p>
+ Additional configuration for a connection between the controller
+ and the Open vSwitch.
+ </p>
+
+ <column name="other_config" key="dscp"
+ type='{"type": "integer"}'>
+ The Differentiated Service Code Point (DSCP) is specified in the IP
+ header. They are specified using 6 bits in the Type of Service (TOS)
+ field in the IP header. DSCP provides a mechanism to classify the
+ network traffic and provide the Quality of Service (QoS) on IP
+ networks.
+ The DSCP value passed is used when establishing the connection between
+ the controller and the Open vSwitch. The connection must be reset
+ for the new DSCP values to take effect. If no value is
+ specified, a default value of 192 is chosen for connection
+ establishment. Valid DSCP values must have their lower 2 bits set to 0.
+ </column>
+ </group>
+
+
<group title="Common Columns">
The overall purpose of these columns is described under <code>Common
Columns</code> at the beginning of this document.
<column name="external_ids"/>
+ <column name="other_config"/>
</group>
</table>
</column>
</group>
+ <group title="Connection Parameters">
+ <p>
+ Additional configuration for a connection between the manager
+ and the Open vSwitch Database.
+ </p>
+
+ <column name="other_config" key="dscp"
+ type='{"type": "integer"}'>
+ The Differentiated Service Code Point (DSCP) is specified in the IP
+ header. They are specified using 6 bits in the Type of Service (TOS)
+ field in the IP header. DSCP provides a mechanism to classify the
+ network traffic and provide the Quality of Service (QoS) on IP
+ networks.
+ The DSCP value passed when establishing the connection between
+ the manager and the Open vSwitch Database. The connection must be
+ reset for the new DSCP values to take effect. If no value is
+ specified, a default value of 192 is chosen for connection
+ establishment. Valid DSCP values must have their lower 2 bits set to 0.
+ </column>
+ </group>
+
<group title="Common Columns">
The overall purpose of these columns is described under <code>Common
Columns</code> at the beginning of this document.
<column name="external_ids"/>
+ <column name="other_config"/>
</group>
</table>