Change the secchan "hook" mechanism to be easier to add new callbacks.
authorBen Pfaff <blp@nicira.com>
Fri, 24 Oct 2008 21:25:10 +0000 (14:25 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 27 Oct 2008 19:58:27 +0000 (12:58 -0700)
16 files changed:
secchan/fail-open.c
secchan/fail-open.h
secchan/in-band.c
secchan/in-band.h
secchan/port-watcher.c
secchan/port-watcher.h
secchan/ratelimit.c
secchan/ratelimit.h
secchan/secchan.c
secchan/secchan.h
secchan/snat.c
secchan/snat.h
secchan/status.c
secchan/status.h
secchan/stp-secchan.c
secchan/stp-secchan.h

index 8440efaaf828c2664a1d4a3e92ae2f2f9604f0ad..06e1c31ee5e8a883a851923129fdf0d5f2623269 100644 (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);
 }
index ed69c88555716947b977747df1a415057ac9074d..69a3b31027953af9f70f8056ce537281fb5bbebb 100644 (file)
 #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 */
index 141f23516345845c694affbcdfffe41c147ed1b1..e925fa562d285c29a1e25e8f7c5e7ebb7724ac3a 100644 (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);
 }
index 573914e9ce4a065053b3c34622b45abcfd7abe39..b4d21ab9f15158f976abaf29a08d0032d79cf03e 100644 (file)
 
 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 */
index 33f420557d1ac14a5f575f972479ddad663ff967..8ab8ded82a51b053958f0ac242d6010399304cb1 100644 (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);
 }
index e5758bb605a467455a216fecb34a15e329935a6e..904e545a85617f7fa11df100b49262e535b586c2 100644 (file)
 
 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);
index ee25f16b5c3167a1218a9e3aa2b2c0d18f196848..5f0da2df63f7e55e7a8b2ab82959e08424aed2bb 100644 (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);
 }
index e3a3f8f5f899da3be6eea343b1a8098f02bc7ad1..e29125451ca0e663ba5b3f9384681d8093462f3a 100644 (file)
 #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 */
index e40183f28144a0f571fd8113460de2f8436f6d83..1d28eaae6b03a81219e73fb921f00f2f52c0cf8c 100644 (file)
 #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;
                     }
                 }
             }
index 0345fa3fcfa4367f1b567a19f7464d7efbcd748a..0a398adc5dd2f0c337608958897d9c838a572d1a 100644 (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 **);
index 1869887ef5d1e0481e5a4f5194cb81eece4c31fb..9d7306c4fb0febc8c74762e421ea978553354a59 100644 (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);
 }
index 935b3223dc02de5162d0b9d57e1bf8cecdd3b323..8f71b151ca37860b210b53aad103a9c728711f17 100644 (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 */
index 99c22aa0b07b44ab9a24056aa01074d8497f7de4..be4f86bf9fd2563fdcff3627c6eeee0c68c5674c 100644 (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
index 14bffa675fabce94d122293388c60d6d128e56e8..68793effdf55a51b23470c7d747efefe3ccaec73 100644 (file)
 
 #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 *,
index de3e1b7826e80a00db898229e1510c0c0ce9bf47..306f05fba44311936aeb8cd7f0609edb6b3517bd 100644 (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);
 }
index 98a7a4ddd36f5ddd9ac2ce7aa36afa3a4fe13bf7..ac4076f4a2e8ccd63e4067d76185956c3a303046 100644 (file)
 
 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 */