#include "list.h"
#include "mac-learning.h"
#include "netdev.h"
+#include "nicira-ext.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
regex_t accept_controller_regex; /* Controller vconns to accept. */
const char *accept_controller_re; /* String version of regex. */
bool update_resolv_conf; /* Update /etc/resolv.conf? */
-
- /* Spanning tree protocol. */
- bool stp; /* Enable spanning tree protocol? */
};
struct half {
struct relay *controller_relay;
struct discovery *discovery;
struct switch_status *switch_status;
+ struct port_watcher *pw;
int i;
int retval;
list_push_back(&relays, &controller_relay->node);
/* Set up hooks. */
- if (s.stp) {
- struct port_watcher *pw;
- hooks[n_hooks++] = port_watcher_create(local_rconn, remote_rconn, &pw);
- hooks[n_hooks++] = stp_hook_create(&s, pw, local_rconn, remote_rconn);
- }
+ hooks[n_hooks++] = port_watcher_create(local_rconn, remote_rconn, &pw);
+ hooks[n_hooks++] = stp_hook_create(&s, pw, local_rconn, remote_rconn);
if (s.in_band) {
hooks[n_hooks++] = in_band_hook_create(&s, switch_status,
remote_rconn);
return false;
}
+static bool
+port_watcher_remote_packet_cb(struct relay *r, void *pw_)
+{
+ struct port_watcher *pw = pw_;
+ struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
+ struct ofp_header *oh = msg->data;
+
+ if (oh->type == OFPT_PORT_MOD
+ && msg->size >= sizeof(struct ofp_port_mod)) {
+ struct ofp_port_mod *opm = msg->data;
+ uint16_t port_no = ntohs(opm->desc.port_no);
+ int idx = port_no_to_pw_idx(port_no);
+ if (idx >= 0) {
+ struct ofp_phy_port *pw_opp = &pw->ports[idx];
+ if (pw_opp->port_no != htons(OFPP_NONE)) {
+ struct ofp_phy_port old = *pw_opp;
+ pw_opp->flags = ((pw_opp->flags & ~opm->mask)
+ | (opm->desc.flags & opm->mask));
+ call_pw_callbacks(pw, port_no, &old, pw_opp);
+ }
+ }
+ }
+ return false;
+}
+
static void
port_watcher_periodic_cb(void *pw_)
{
old = *p;
/* Update our idea of the flags. */
- p->flags = ntohl(flags);
+ p->flags = htonl((ntohl(p->flags) & ~mask) | (flags & mask));
call_pw_callbacks(pw, port_no, &old, p);
/* Change the flags in the datapath. */
pw->ports[i].port_no = htons(OFPP_NONE);
}
port_watcher_register_callback(pw, log_port_status, NULL);
- return make_hook(port_watcher_local_packet_cb, NULL,
+ return make_hook(port_watcher_local_packet_cb,
+ port_watcher_remote_packet_cb,
port_watcher_periodic_cb, NULL, pw);
}
\f
fail_open->remote_rconn = remote_rconn;
fail_open->lswitch = NULL;
fail_open->boot_deadline = time_now() + s->probe_interval * 3;
- if (s->stp) {
- fail_open->boot_deadline += STP_EXTRA_BOOT_TIME;
- }
+ fail_open->boot_deadline += STP_EXTRA_BOOT_TIME;
switch_status_register_category(ss, "fail-open",
fail_open_status_cb, fail_open);
return make_hook(fail_open_local_packet_cb, NULL,
struct rconn *rc = r->halves[HALF_REMOTE].rconn;
struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
struct switch_status_category *c;
- struct ofp_stats_request *osr;
- struct ofp_stats_reply *reply;
+ struct nicira_header *request;
+ struct nicira_header *reply;
struct status_reply sr;
- struct ofp_header *oh;
struct buffer *b;
int retval;
- oh = msg->data;
- if (oh->type != OFPT_STATS_REQUEST) {
- return false;
- }
- if (msg->size < sizeof(struct ofp_stats_request)) {
- VLOG_WARN_RL(&vrl, "packet too short (%zu bytes) for stats_request",
- msg->size);
+ if (msg->size < sizeof(struct nicira_header)) {
return false;
}
-
- osr = msg->data;
- if (osr->type != htons(OFPST_SWITCH)) {
+ request = msg->data;
+ if (request->header.type != OFPT_VENDOR
+ || request->vendor_id != htonl(NX_VENDOR_ID)
+ || request->subtype != htonl(NXT_STATUS_REQUEST)) {
return false;
}
- sr.request.string = (void *) (osr + 1);
- sr.request.length = msg->size - sizeof *osr;
+ sr.request.string = (void *) (request + 1);
+ sr.request.length = msg->size - sizeof *request;
ds_init(&sr.output);
for (c = ss->categories; c < &ss->categories[ss->n_categories]; c++) {
if (!memcmp(c->name, sr.request.string,
c->cb(&sr, c->aux);
}
}
- reply = make_openflow_xid((offsetof(struct ofp_stats_reply, body)
- + sr.output.length),
- OFPT_STATS_REPLY, osr->header.xid, &b);
- reply->type = htons(OFPST_SWITCH);
- reply->flags = 0;
- memcpy(reply->body, sr.output.string, sr.output.length);
+ reply = make_openflow_xid(sizeof *reply + sr.output.length,
+ OFPT_VENDOR, request->header.xid, &b);
+ reply->vendor_id = htonl(NX_VENDOR_ID);
+ reply->subtype = htonl(NXT_STATUS_REPLY);
+ memcpy(reply + 1, sr.output.string, sr.output.length);
retval = rconn_send(rc, b, NULL);
if (retval && retval != EAGAIN) {
VLOG_WARN("send failed (%s)", strerror(retval));