/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 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.
#include "fail-open.h"
#include "in-band.h"
#include "odp-util.h"
+#include "ofp-actions.h"
#include "ofp-util.h"
#include "ofpbuf.h"
#include "ofproto-provider.h"
#include "pktbuf.h"
#include "rconn.h"
#include "shash.h"
+#include "simap.h"
#include "stream.h"
#include "timeval.h"
#include "vconn.h"
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);
}
}
+/* Adds some memory usage statistics for 'mgr' into 'usage', for use with
+ * memory_report(). */
+void
+connmgr_get_memory_usage(const struct connmgr *mgr, struct simap *usage)
+{
+ const struct ofconn *ofconn;
+ unsigned int packets = 0;
+ unsigned int ofconns = 0;
+
+ LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
+ int i;
+
+ ofconns++;
+
+ packets += rconn_count_txqlen(ofconn->rconn);
+ for (i = 0; i < N_SCHEDULERS; i++) {
+ packets += pinsched_count_txqlen(ofconn->schedulers[i]);
+ }
+ packets += pktbuf_count_packets(ofconn->pktbuf);
+ }
+ simap_increase(usage, "ofconns", ofconns);
+ simap_increase(usage, "packets", packets);
+}
+
/* Returns the ofproto that owns 'ofconn''s connmgr. */
struct ofproto *
ofconn_get_ofproto(const struct ofconn *ofconn)
\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);
+ VLOG_INFO("%s: added primary controller \"%s\"",
+ mgr->name, 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);
+ VLOG_INFO("%s: added service controller \"%s\"",
+ mgr->name, c->target);
+ ofservice_create(mgr, c->target, c->dscp);
}
} else {
VLOG_WARN_RL(&rl, "%s: unsupported controller \"%s\"",
/* Delete controllers that are no longer configured.
* Update configuration of all now-existing controllers. */
HMAP_FOR_EACH_SAFE (ofconn, next_ofconn, hmap_node, &mgr->controllers) {
+ const char *target = ofconn_get_target(ofconn);
struct ofproto_controller *c;
- c = shash_find_data(&new_controllers, ofconn_get_target(ofconn));
+ c = shash_find_data(&new_controllers, target);
if (!c) {
+ VLOG_INFO("%s: removed primary controller \"%s\"",
+ mgr->name, target);
ofconn_destroy(ofconn);
} else {
ofconn_reconfigure(ofconn, c);
/* Delete services that are no longer configured.
* Update configuration of all now-existing services. */
HMAP_FOR_EACH_SAFE (ofservice, next_ofservice, node, &mgr->services) {
+ const char *target = pvconn_get_name(ofservice->pvconn);
struct ofproto_controller *c;
- c = shash_find_data(&new_controllers,
- pvconn_get_name(ofservice->pvconn));
+ c = shash_find_data(&new_controllers, target);
if (!c) {
+ VLOG_INFO("%s: removed service controller \"%s\"",
+ mgr->name, target);
ofservice_destroy(mgr, ofservice);
} else {
ofservice_reconfigure(ofservice, c);
/* 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, 0);
if (!error) {
pvconns[n_pvconns++] = pvconn;
} else {
rconn_set_probe_interval(ofconn->rconn, probe_interval);
ofconn_set_rate_limit(ofconn, c->rate_limit, c->burst_limit);
+
+ /* If dscp value changed reconnect. */
+ if (c->dscp != rconn_get_dscp(ofconn->rconn)) {
+ rconn_set_dscp(ofconn->rconn, c->dscp);
+ rconn_reconnect(ofconn->rconn);
+ }
}
/* Returns true if it makes sense for 'ofconn' to receive and process OpenFlow
struct rconn_packet_counter *counter)
{
update_openflow_length(msg);
- if (rconn_send(ofconn->rconn, msg, counter)) {
- ofpbuf_delete(msg);
- }
+ rconn_send(ofconn->rconn, msg, counter);
}
\f
/* Sending asynchronous messages. */
-static void schedule_packet_in(struct ofconn *, struct ofputil_packet_in,
- const struct flow *);
+static void schedule_packet_in(struct ofconn *, struct ofputil_packet_in);
/* Sends an OFPT_PORT_STATUS message with 'opp' and 'reason' to appropriate
* controllers managed by 'mgr'. */
void
-connmgr_send_port_status(struct connmgr *mgr, const struct ofp_phy_port *opp,
- uint8_t reason)
+connmgr_send_port_status(struct connmgr *mgr,
+ const struct ofputil_phy_port *pp, uint8_t reason)
{
/* XXX Should limit the number of queued port status change messages. */
+ struct ofputil_port_status ps;
struct ofconn *ofconn;
+ ps.reason = reason;
+ ps.desc = *pp;
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
if (ofconn_receives_async_msg(ofconn, OAM_PORT_STATUS, reason)) {
- struct ofp_port_status *ops;
- struct ofpbuf *b;
+ struct ofpbuf *msg;
- ops = make_openflow_xid(sizeof *ops, OFPT_PORT_STATUS, 0, &b);
- ops->reason = reason;
- ops->desc = *opp;
- ofconn_send(ofconn, b, NULL);
+ msg = ofputil_encode_port_status(&ps, ofconn->protocol);
+ ofconn_send(ofconn, msg, NULL);
}
}
}
}
/* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as
- * necessary according to their individual configurations. */
+ * necessary according to their individual configurations.
+ *
+ * The caller doesn't need to fill in pin->buffer_id or pin->total_len. */
void
connmgr_send_packet_in(struct connmgr *mgr,
- const struct ofputil_packet_in *pin,
- const struct flow *flow)
+ const struct ofputil_packet_in *pin)
{
struct ofconn *ofconn;
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
if (ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, pin->reason)
&& ofconn->controller_id == pin->controller_id) {
- schedule_packet_in(ofconn, *pin, flow);
+ schedule_packet_in(ofconn, *pin);
}
}
}
ofconn->packet_in_counter, 100);
}
-/* Takes 'pin', whose packet has the flow specified by 'flow', composes an
- * OpenFlow packet-in message from it, and passes it to 'ofconn''s packet
- * scheduler for sending. */
+/* Takes 'pin', composes an OpenFlow packet-in message from it, and passes it
+ * to 'ofconn''s packet scheduler for sending. */
static void
-schedule_packet_in(struct ofconn *ofconn, struct ofputil_packet_in pin,
- const struct flow *flow)
+schedule_packet_in(struct ofconn *ofconn, struct ofputil_packet_in pin)
{
struct connmgr *mgr = ofconn->connmgr;
+ pin.total_len = pin.packet_len;
+
/* Get OpenFlow buffer_id. */
if (pin.reason == OFPR_ACTION) {
pin.buffer_id = UINT32_MAX;
pin.buffer_id = UINT32_MAX;
} else {
pin.buffer_id = pktbuf_save(ofconn->pktbuf, pin.packet, pin.packet_len,
- flow->in_port);
+ pin.fmd.in_port);
}
/* Figure out how much of the packet to send. */
pin.send_len = pin.packet_len;
} else {
/* Caller should have initialized 'send_len' to 'max_len' specified in
- * struct ofp_action_output. */
+ * output action. */
}
if (pin.buffer_id != UINT32_MAX) {
pin.send_len = MIN(pin.send_len, ofconn->miss_send_len);
* immediately call into do_send_packet_in() or it might buffer it for a
* while (until a later call to pinsched_run()). */
pinsched_send(ofconn->schedulers[pin.reason == OFPR_NO_MATCH ? 0 : 1],
- flow->in_port,
+ pin.fmd.in_port,
ofputil_encode_packet_in(&pin, ofconn->packet_in_format),
do_send_packet_in, ofconn);
}
}
return false;
}
-
-/* Sends 'packet' to each controller connected to 'mgr'. Takes ownership of
- * 'packet'. */
-void
-connmgr_broadcast(struct connmgr *mgr, struct ofpbuf *packet)
-{
- struct ofconn *ofconn, *prev;
-
- prev = NULL;
- LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
- if (prev) {
- ofconn_send_reply(ofconn, ofpbuf_clone(packet));
- }
- if (rconn_is_connected(ofconn->rconn)) {
- prev = ofconn;
- }
- }
- if (prev) {
- ofconn_send_reply(prev, packet);
- } else {
- ofpbuf_delete(packet);
- }
-}
\f
/* In-band configuration. */
* traffic until a controller has been defined and it tells us to do so. */
if (!connmgr_has_controllers(mgr)
&& mgr->fail_mode == OFPROTO_FAIL_STANDALONE) {
- union ofp_action action;
+ struct ofpbuf ofpacts;
struct cls_rule rule;
- memset(&action, 0, sizeof action);
- action.type = htons(OFPAT10_OUTPUT);
- action.output.len = htons(sizeof action);
- action.output.port = htons(OFPP_NORMAL);
+ ofpbuf_init(&ofpacts, OFPACT_OUTPUT_SIZE);
+ ofpact_put_OUTPUT(&ofpacts)->port = OFPP_NORMAL;
+ ofpact_pad(&ofpacts);
+
cls_rule_init_catchall(&rule, 0);
- ofproto_add_flow(mgr->ofproto, &rule, &action, 1);
+ ofproto_add_flow(mgr->ofproto, &rule, ofpacts.data, ofpacts.size);
+
+ ofpbuf_uninit(&ofpacts);
}
}
\f
* 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