Change the secchan "hook" mechanism to be easier to add new callbacks.

This commit is contained in:
Ben Pfaff committed 2008-10-27 12:58:27 -07:00
1 parent 9abe7b6f19
commit de5caa4906
16 files changed
+203 -105

No files matched your search

+13 -5
View File
@@ -131,9 +131,18 @@ fail_open_status_cb(struct status_reply *sr, void *fail_open_)
status_reply_put(sr, "max-idle=%d", s->max_idle);
}
struct hook
fail_open_hook_create(const struct settings *s, struct switch_status *ss,
struct rconn *local_rconn, struct rconn *remote_rconn)
static struct hook_class fail_open_hook_class = {
fail_open_local_packet_cb, /* local_packet_cb */
NULL, /* remote_packet_cb */
fail_open_periodic_cb, /* periodic_cb */
fail_open_wait_cb, /* wait_cb */
NULL, /* closing_cb */
};
void
fail_open_start(struct secchan *secchan, const struct settings *s,
struct switch_status *ss,
struct rconn *local_rconn, struct rconn *remote_rconn)
{
struct fail_open_data *fail_open = xmalloc(sizeof *fail_open);
fail_open->s = s;
@@ -146,6 +155,5 @@ fail_open_hook_create(const struct settings *s, struct switch_status *ss,
}
switch_status_register_category(ss, "fail-open",
fail_open_status_cb, fail_open);
return make_hook(fail_open_local_packet_cb, NULL,
fail_open_periodic_cb, fail_open_wait_cb, fail_open);
add_hook(secchan, &fail_open_hook_class, fail_open);
}
+5 -5
View File
@@ -34,13 +34,13 @@
#ifndef FAIL_OPEN_H
#define FAIL_OPEN_H 1
struct rconn;
struct secchan;
struct settings;
struct switch_status;
struct rconn;
struct hook fail_open_hook_create(const struct settings *,
struct switch_status *,
struct rconn *local,
struct rconn *remote);
void fail_open_start(struct secchan *, const struct settings *,
struct switch_status *,
struct rconn *local, struct rconn *remote);
#endif /* fail-open.h */
+13 -4
View File
@@ -284,9 +284,18 @@ in_band_local_port_cb(const struct ofp_phy_port *port, void *in_band_)
}
}
struct hook
in_band_hook_create(const struct settings *s, struct switch_status *ss,
struct port_watcher *pw, struct rconn *remote)
static struct hook_class in_band_hook_class = {
in_band_local_packet_cb, /* local_packet_cb */
NULL, /* remote_packet_cb */
NULL, /* periodic_cb */
NULL, /* wait_cb */
NULL, /* closing_cb */
};
void
in_band_start(struct secchan *secchan,
const struct settings *s, struct switch_status *ss,
struct port_watcher *pw, struct rconn *remote)
{
struct in_band_data *in_band;
@@ -298,5 +307,5 @@ in_band_hook_create(const struct settings *s, struct switch_status *ss,
switch_status_register_category(ss, "in-band", in_band_status_cb, in_band);
port_watcher_register_local_port_callback(pw, in_band_local_port_cb,
in_band);
return make_hook(in_band_local_packet_cb, NULL, NULL, NULL, in_band);
add_hook(secchan, &in_band_hook_class, in_band);
}
+4 -4
View File
@@ -36,12 +36,12 @@
struct port_watcher;
struct rconn;
struct secchan;
struct settings;
struct switch_status;
struct hook in_band_hook_create(const struct settings *,
struct switch_status *,
struct port_watcher *,
struct rconn *remote);
void in_band_start(struct secchan *, const struct settings *,
struct switch_status *, struct port_watcher *,
struct rconn *remote);
#endif /* in-band.h */
+13 -7
View File
@@ -475,9 +475,18 @@ port_watcher_is_ready(const struct port_watcher *pw)
return pw->got_feature_reply;
}
struct hook
port_watcher_create(struct rconn *local_rconn, struct rconn *remote_rconn,
struct port_watcher **pwp)
static struct hook_class port_watcher_hook_class = {
port_watcher_local_packet_cb, /* local_packet_cb */
port_watcher_remote_packet_cb, /* remote_packet_cb */
port_watcher_periodic_cb, /* periodic_cb */
port_watcher_wait_cb, /* wait_cb */
NULL, /* closing_cb */
};
void
port_watcher_start(struct secchan *secchan,
struct rconn *local_rconn, struct rconn *remote_rconn,
struct port_watcher **pwp)
{
struct port_watcher *pw;
@@ -488,8 +497,5 @@ port_watcher_create(struct rconn *local_rconn, struct rconn *remote_rconn,
port_array_init(&pw->ports);
pw->local_port_name[0] = '\0';
port_watcher_register_callback(pw, log_port_status, NULL);
return make_hook(port_watcher_local_packet_cb,
port_watcher_remote_packet_cb,
port_watcher_periodic_cb,
port_watcher_wait_cb, pw);
add_hook(secchan, &port_watcher_hook_class, pw);
}
+4 -3
View File
@@ -40,10 +40,11 @@
struct ofp_phy_port;
struct port_watcher;
struct secchan;
struct hook port_watcher_create(struct rconn *local,
struct rconn *remote,
struct port_watcher **);
void port_watcher_start(struct secchan *,
struct rconn *local, struct rconn *remote,
struct port_watcher **);
bool port_watcher_is_ready(const struct port_watcher *);
uint32_t port_watcher_get_config(const struct port_watcher *,
uint16_t port_no);
+13 -5
View File
@@ -227,9 +227,18 @@ rate_limit_wait_cb(void *rl_)
}
}
struct hook
rate_limit_hook_create(const struct settings *s, struct switch_status *ss,
struct rconn *local, struct rconn *remote)
static struct hook_class rate_limit_hook_class = {
rate_limit_local_packet_cb, /* local_packet_cb */
NULL, /* remote_packet_cb */
rate_limit_periodic_cb, /* periodic_cb */
rate_limit_wait_cb, /* wait_cb */
NULL, /* closing_cb */
};
void
rate_limit_start(struct secchan *secchan, const struct settings *s,
struct switch_status *ss,
struct rconn *local, struct rconn *remote)
{
struct rate_limiter *rl;
size_t i;
@@ -244,6 +253,5 @@ rate_limit_hook_create(const struct settings *s, struct switch_status *ss,
rl->tokens = s->rate_limit * 100;
switch_status_register_category(ss, "rate-limit",
rate_limit_status_cb, rl);
return make_hook(rate_limit_local_packet_cb, NULL, rate_limit_periodic_cb,
rate_limit_wait_cb, rl);
add_hook(secchan, &rate_limit_hook_class, rl);
}
+4 -4
View File
@@ -35,12 +35,12 @@
#define RATELIMIT_H 1
struct rconn;
struct secchan;
struct settings;
struct switch_status;
struct hook rate_limit_hook_create(const struct settings *,
struct switch_status *,
struct rconn *local,
struct rconn *remote);
void rate_limit_start(struct secchan *, const struct settings *,
struct switch_status *,
struct rconn *local, struct rconn *remote);
#endif /* ratelimit.h */
+80 -43
View File
@@ -70,6 +70,16 @@
#include "vlog.h"
#define THIS_MODULE VLM_secchan
struct hook {
const struct hook_class *class;
void *aux;
};
struct secchan {
struct hook *hooks;
size_t n_hooks, allocated_hooks;
};
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60);
static void parse_options(int argc, char *argv[], struct settings *);
@@ -81,7 +91,7 @@ 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 pvconn *);
static void relay_run(struct relay *, const struct hook[], size_t n_hooks);
static void relay_run(struct relay *, struct secchan *);
static void relay_wait(struct relay *);
static void relay_destroy(struct relay *);
@@ -92,8 +102,7 @@ main(int argc, char *argv[])
struct list relays = LIST_INITIALIZER(&relays);
struct hook hooks[8];
size_t n_hooks = 0;
struct secchan secchan;
struct pvconn *monitor;
@@ -115,6 +124,10 @@ main(int argc, char *argv[])
parse_options(argc, argv, &s);
signal(SIGPIPE, SIG_IGN);
secchan.hooks = NULL;
secchan.n_hooks = 0;
secchan.allocated_hooks = 0;
/* Start listening for management and monitoring connections. */
n_listeners = 0;
for (i = 0; i < s.n_listeners; i++) {
@@ -123,7 +136,7 @@ main(int argc, char *argv[])
monitor = s.monitor_name ? open_passive_vconn(s.monitor_name) : NULL;
/* Initialize switch status hook. */
hooks[n_hooks++] = switch_status_hook_create(&s, &switch_status);
switch_status_start(&secchan, &s, &switch_status);
/* Start listening for vlogconf requests. */
retval = vlog_server_listen(NULL, NULL);
@@ -159,27 +172,25 @@ main(int argc, char *argv[])
list_push_back(&relays, &controller_relay->node);
/* Set up hooks. */
hooks[n_hooks++] = port_watcher_create(local_rconn, remote_rconn, &pw);
port_watcher_start(&secchan, local_rconn, remote_rconn, &pw);
discovery = s.discovery ? discovery_init(&s, pw, switch_status) : NULL;
#ifdef SUPPORT_SNAT
hooks[n_hooks++] = snat_hook_create(pw);
snat_start(&secchan, pw);
#endif
if (s.enable_stp) {
hooks[n_hooks++] = stp_hook_create(&s, pw, local_rconn, remote_rconn);
stp_start(&secchan, &s, pw, local_rconn, remote_rconn);
}
if (s.in_band) {
hooks[n_hooks++] = in_band_hook_create(&s, switch_status, pw,
remote_rconn);
in_band_start(&secchan, &s, switch_status, pw, remote_rconn);
}
if (s.fail_mode == FAIL_OPEN) {
hooks[n_hooks++] = fail_open_hook_create(&s, switch_status,
local_rconn, remote_rconn);
fail_open_start(&secchan, &s, switch_status,
local_rconn, remote_rconn);
}
if (s.rate_limit) {
hooks[n_hooks++] = rate_limit_hook_create(&s, switch_status,
local_rconn, remote_rconn);
rate_limit_start(&secchan, &s, switch_status,
local_rconn, remote_rconn);
}
assert(n_hooks <= ARRAY_SIZE(hooks));
for (;;) {
struct relay *r, *n;
@@ -187,7 +198,7 @@ main(int argc, char *argv[])
/* Do work. */
LIST_FOR_EACH_SAFE (r, n, struct relay, node, &relays) {
relay_run(r, hooks, n_hooks);
relay_run(r, &secchan);
}
for (i = 0; i < n_listeners; i++) {
for (;;) {
@@ -204,9 +215,9 @@ main(int argc, char *argv[])
rconn_add_monitor(local_rconn, new);
}
}
for (i = 0; i < n_hooks; i++) {
if (hooks[i].periodic_cb) {
hooks[i].periodic_cb(hooks[i].aux);
for (i = 0; i < secchan.n_hooks; i++) {
if (secchan.hooks[i].class->periodic_cb) {
secchan.hooks[i].class->periodic_cb(secchan.hooks[i].aux);
}
}
if (s.discovery) {
@@ -233,9 +244,9 @@ main(int argc, char *argv[])
if (monitor) {
pvconn_wait(monitor);
}
for (i = 0; i < n_hooks; i++) {
if (hooks[i].wait_cb) {
hooks[i].wait_cb(hooks[i].aux);
for (i = 0; i < secchan.n_hooks; i++) {
if (secchan.hooks[i].class->wait_cb) {
secchan.hooks[i].class->wait_cb(secchan.hooks[i].aux);
}
}
if (discovery) {
@@ -273,20 +284,20 @@ accept_vconn(struct pvconn *pvconn)
return new;
}
struct hook
make_hook(bool (*local_packet_cb)(struct relay *, void *aux),
bool (*remote_packet_cb)(struct relay *, void *aux),
void (*periodic_cb)(void *aux),
void (*wait_cb)(void *aux),
void *aux)
void
add_hook(struct secchan *secchan, const struct hook_class *class, void *aux)
{
struct hook h;
h.packet_cb[HALF_LOCAL] = local_packet_cb;
h.packet_cb[HALF_REMOTE] = remote_packet_cb;
h.periodic_cb = periodic_cb;
h.wait_cb = wait_cb;
h.aux = aux;
return h;
struct hook *hook;
if (secchan->n_hooks >= secchan->allocated_hooks) {
secchan->allocated_hooks = secchan->allocated_hooks * 2 + 1;
secchan->hooks = xrealloc(secchan->hooks,
(sizeof *secchan->hooks
* secchan->allocated_hooks));
}
hook = &secchan->hooks[secchan->n_hooks++];
hook->class = class;
hook->aux = aux;
}
struct ofp_packet_in *
@@ -381,8 +392,34 @@ relay_create(struct rconn *local, struct rconn *remote, bool is_mgmt_conn)
return r;
}
static bool
call_local_packet_cbs(struct secchan *secchan, struct relay *r)
{
const struct hook *h;
for (h = secchan->hooks; h < &secchan->hooks[secchan->n_hooks]; h++) {
bool (*cb)(struct relay *, void *aux) = h->class->local_packet_cb;
if (cb && (cb)(r, h->aux)) {
return true;
}
}
return false;
}
static bool
call_remote_packet_cbs(struct secchan *secchan, struct relay *r)
{
const struct hook *h;
for (h = secchan->hooks; h < &secchan->hooks[secchan->n_hooks]; h++) {
bool (*cb)(struct relay *, void *aux) = h->class->remote_packet_cb;
if (cb && (cb)(r, h->aux)) {
return true;
}
}
return false;
}
static void
relay_run(struct relay *r, const struct hook hooks[], size_t n_hooks)
relay_run(struct relay *r, struct secchan *secchan)
{
int iteration;
int i;
@@ -401,14 +438,14 @@ relay_run(struct relay *r, const struct hook hooks[], size_t n_hooks)
if (!this->rxbuf) {
this->rxbuf = rconn_recv(this->rconn);
if (this->rxbuf && (i == HALF_REMOTE || !r->is_mgmt_conn)) {
const struct hook *h;
for (h = hooks; h < &hooks[n_hooks]; h++) {
if (h->packet_cb[i] && h->packet_cb[i](r, h->aux)) {
ofpbuf_delete(this->rxbuf);
this->rxbuf = NULL;
progress = true;
break;
}
if (i == HALF_LOCAL
? call_local_packet_cbs(secchan, r)
: call_remote_packet_cbs(secchan, r))
{
ofpbuf_delete(this->rxbuf);
this->rxbuf = NULL;
progress = true;
break;
}
}
}
+8 -8
View File
@@ -40,6 +40,8 @@
#include "list.h"
#include "packets.h"
struct secchan;
/* Behavior when the connection to the controller fails. */
enum fail_mode {
FAIL_OPEN, /* Act as learning switch. */
@@ -97,18 +99,16 @@ struct relay {
bool is_mgmt_conn;
};
struct hook {
bool (*packet_cb[2])(struct relay *, void *aux);
struct hook_class {
bool (*local_packet_cb)(struct relay *, void *aux);
bool (*remote_packet_cb)(struct relay *, void *aux);
void (*periodic_cb)(void *aux);
void (*wait_cb)(void *aux);
void *aux;
void (*closing_cb)(struct relay *, void *aux);
};
struct hook make_hook(bool (*local_packet_cb)(struct relay *, void *),
bool (*remote_packet_cb)(struct relay *, void *),
void (*periodic_cb)(void *),
void (*wait_cb)(void *),
void *aux);
void add_hook(struct secchan *, const struct hook_class *, void *);
struct ofp_packet_in *get_ofp_packet_in(struct relay *);
bool get_ofp_packet_eth_header(struct relay *, struct ofp_packet_in **,
struct eth_header **);
+11 -3
View File
@@ -265,8 +265,16 @@ snat_port_changed_cb(uint16_t port_no,
}
}
struct hook
snat_hook_create(struct port_watcher *pw)
static struct hook_class snat_hook_class = {
NULL, /* local_packet_cb */
snat_remote_packet_cb, /* remote_packet_cb */
NULL, /* periodic_cb */
NULL, /* wait_cb */
NULL, /* closing_cb */
};
void
snat_start(struct secchan *secchan, struct port_watcher *pw)
{
int ret;
struct snat_data *snat;
@@ -281,5 +289,5 @@ snat_hook_create(struct port_watcher *pw)
list_init(&snat->port_list);
port_watcher_register_callback(pw, snat_port_changed_cb, snat);
return make_hook(NULL, snat_remote_packet_cb, NULL, NULL, snat);
add_hook(secchan, &snat_hook_class, snat);
}
+2 -1
View File
@@ -37,7 +37,8 @@
#include "secchan.h"
struct port_watcher;
struct secchan;
struct hook snat_hook_create(struct port_watcher *pw);
void snat_start(struct secchan *, struct port_watcher *);
#endif /* snat.h */
+12 -3
View File
@@ -165,8 +165,17 @@ switch_status_cb(struct status_reply *sr, void *ss_)
status_reply_put(sr, "pid=%ld", (long int) getpid());
}
struct hook
switch_status_hook_create(const struct settings *s, struct switch_status **ssp)
static struct hook_class switch_status_hook_class = {
NULL, /* local_packet_cb */
switch_status_remote_packet_cb, /* remote_packet_cb */
NULL, /* periodic_cb */
NULL, /* wait_cb */
NULL, /* closing_cb */
};
void
switch_status_start(struct secchan *secchan, const struct settings *s,
struct switch_status **ssp)
{
struct switch_status *ss = xcalloc(1, sizeof *ss);
ss->s = s;
@@ -175,7 +184,7 @@ switch_status_hook_create(const struct settings *s, struct switch_status **ssp)
config_status_cb, (void *) s);
switch_status_register_category(ss, "switch", switch_status_cb, ss);
*ssp = ss;
return make_hook(NULL, switch_status_remote_packet_cb, NULL, NULL, ss);
add_hook(secchan, &switch_status_hook_class, ss);
}
void
+4 -3
View File
@@ -36,11 +36,12 @@
#include "secchan.h"
struct switch_status;
struct secchan;
struct status_reply;
struct switch_status;
struct hook switch_status_hook_create(const struct settings *,
struct switch_status **);
void switch_status_start(struct secchan *, const struct settings *,
struct switch_status **);
void switch_status_register_category(struct switch_status *,
const char *category,
void (*cb)(struct status_reply *,
+13 -5
View File
@@ -286,9 +286,18 @@ stp_local_port_changed_cb(const struct ofp_phy_port *port, void *stp_)
}
}
struct hook
stp_hook_create(const struct settings *s, struct port_watcher *pw,
struct rconn *local, struct rconn *remote)
static struct hook_class stp_hook_class = {
stp_local_packet_cb, /* local_packet_cb */
NULL, /* remote_packet_cb */
stp_periodic_cb, /* periodic_cb */
stp_wait_cb, /* wait_cb */
NULL, /* closing_cb */
};
void
stp_start(struct secchan *secchan, const struct settings *s,
struct port_watcher *pw,
struct rconn *local, struct rconn *remote)
{
uint8_t dpid[ETH_ADDR_LEN];
struct stp_data *stp;
@@ -304,6 +313,5 @@ stp_hook_create(const struct settings *s, struct port_watcher *pw,
port_watcher_register_callback(pw, stp_port_changed_cb, stp);
port_watcher_register_local_port_callback(pw, stp_local_port_changed_cb,
stp);
return make_hook(stp_local_packet_cb, NULL,
stp_periodic_cb, stp_wait_cb, stp);
add_hook(secchan, &stp_hook_class, stp);
}
+4 -2
View File
@@ -40,9 +40,11 @@
struct port_watcher;
struct rconn;
struct secchan;
struct settings;
struct hook stp_hook_create(const struct settings *s, struct port_watcher *pw,
struct rconn *local, struct rconn *remote);
void stp_start(struct secchan *, const struct settings *,
struct port_watcher *,
struct rconn *local, struct rconn *remote);
#endif /* stp-secchan.h */