#include "list.h"
#include "mac-learning.h"
#include "netdev.h"
+#include "nicira-ext.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
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
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) {
+ if (msg->size < sizeof(struct nicira_header)) {
return false;
}
- if (msg->size < sizeof(struct ofp_stats_request)) {
- VLOG_WARN_RL(&vrl, "packet too short (%zu bytes) for stats_request",
- msg->size);
- 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));