static void parse_options(int argc, char *argv[], struct settings *);
static void usage(void) NO_RETURN;
-static struct vconn *open_passive_vconn(const char *name);
-static struct vconn *accept_vconn(struct vconn *vconn);
+static struct pvconn *open_passive_vconn(const char *name);
+static struct vconn *accept_vconn(struct pvconn *pvconn);
static struct relay *relay_create(struct rconn *local, struct rconn *remote,
bool is_mgmt_conn);
-static struct relay *relay_accept(const struct settings *, struct vconn *);
+static struct relay *relay_accept(const struct settings *, struct pvconn *);
static void relay_run(struct relay *, const struct hook[], size_t n_hooks);
static void relay_wait(struct relay *);
static void relay_destroy(struct relay *);
struct hook hooks[8];
size_t n_hooks = 0;
- struct vconn *monitor;
+ struct pvconn *monitor;
- struct vconn *listeners[MAX_MGMT];
+ struct pvconn *listeners[MAX_MGMT];
size_t n_listeners;
struct rconn *local_rconn, *remote_rconn;
relay_wait(r);
}
for (i = 0; i < n_listeners; i++) {
- vconn_accept_wait(listeners[i]);
+ pvconn_wait(listeners[i]);
}
if (monitor) {
- vconn_accept_wait(monitor);
+ pvconn_wait(monitor);
}
for (i = 0; i < n_hooks; i++) {
if (hooks[i].wait_cb) {
return 0;
}
-static struct vconn *
-open_passive_vconn(const char *name)
+static struct pvconn *
+open_passive_vconn(const char *name)
{
- struct vconn *vconn;
+ struct pvconn *pvconn;
int retval;
- retval = vconn_open(name, &vconn);
+ retval = pvconn_open(name, &pvconn);
if (retval && retval != EAGAIN) {
fatal(retval, "opening %s", name);
}
- if (!vconn_is_passive(vconn)) {
- fatal(0, "%s is not a passive vconn", name);
- }
- return vconn;
+ return pvconn;
}
static struct vconn *
-accept_vconn(struct vconn *vconn)
+accept_vconn(struct pvconn *pvconn)
{
struct vconn *new;
int retval;
- retval = vconn_accept(vconn, &new);
+ retval = pvconn_accept(pvconn, &new);
if (retval && retval != EAGAIN) {
VLOG_WARN_RL(&vrl, "accept failed (%s)", strerror(retval));
}
/* OpenFlow message relaying. */
static struct relay *
-relay_accept(const struct settings *s, struct vconn *listen_vconn)
+relay_accept(const struct settings *s, struct pvconn *pvconn)
{
struct vconn *new_remote, *new_local;
char *nl_name_without_subscription;
struct rconn *r1, *r2;
int retval;
- new_remote = accept_vconn(listen_vconn);
+ new_remote = accept_vconn(pvconn);
if (!new_remote) {
return NULL;
}
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