Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions main/gr_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ void gr_register_api_handler(struct gr_api_handler *);

struct gr_module {
const char *name;
int init_prio;
const char *depends_on;
void (*init)(struct event_base *);
int fini_prio;
void (*fini)(struct event_base *);
void (*init_dp)(void);
void (*fini_dp)(void);
Expand Down
101 changes: 86 additions & 15 deletions main/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,90 @@ const struct gr_api_handler *lookup_api_handler(const struct gr_api_request *req
static STAILQ_HEAD(, gr_module) modules = STAILQ_HEAD_INITIALIZER(modules);

void gr_register_module(struct gr_module *mod) {
struct gr_module *m;

if (mod->name == NULL)
ABORT("module with no name: %p", mod);

STAILQ_FOREACH (m, &modules, entries) {
if (strcmp(mod->name, m->name) == 0)
ABORT("duplicate module name: '%s'", mod->name);
}

STAILQ_INSERT_TAIL(&modules, mod, entries);
}

static int module_init_prio_order(const void *a, const void *b) {
const struct gr_module *const *mod_a = a;
const struct gr_module *const *mod_b = b;
return (*mod_a)->init_prio - (*mod_b)->init_prio;
static void topo_sort(struct gr_module **mods) {
// Create an adjacency matrix representing all edges
const size_t len = gr_vec_len(mods);
bool *adj_matrix = calloc(len * len, sizeof(bool));
if (adj_matrix == NULL)
ABORT("cannot allocate memory");

for (unsigned i = 0; i < len; i++) {
if (mods[i]->depends_on == NULL)
continue;

for (unsigned j = 0; j < len; j++) {
if (strcmp(mods[j]->name, mods[i]->depends_on) == 0) {
adj_matrix[j * len + i] = true;
break;
}
}
}

// Calculate in-degree of each vertex
int *in_degree = calloc(len, sizeof(int));
if (in_degree == NULL)
ABORT("cannot allocate memory");

for (unsigned i = 0; i < len; i++) {
for (unsigned j = 0; j < len; j++) {
if (adj_matrix[i * len + j]) {
in_degree[j]++;
}
}
}

// Kahn's algorithm for topological sort
unsigned front = 0, rear = 0;
unsigned *queue = calloc(len, sizeof(unsigned));
if (queue == NULL)
ABORT("cannot allocate memory");

for (unsigned i = 0; i < len; i++) {
if (in_degree[i] == 0) {
queue[rear++] = i;
}
}

struct gr_module **sorted = calloc(len, sizeof(struct gr_module *));
if (sorted == NULL)
ABORT("cannot allocate memory");

unsigned i = 0;
while (front < rear) {
unsigned u = queue[front++];
sorted[i++] = mods[u];

// Reduce in-degree of neighbours
for (unsigned v = 0; v < len; v++) {
if (adj_matrix[u * len + v]) {
in_degree[v]--;
if (in_degree[v] == 0) {
queue[rear++] = v;
}
}
}
}

// Copy the sorted modules back to the original array
memcpy(mods, sorted, len * sizeof(struct gr_module *));

free(sorted);
free(queue);
free(in_degree);
free(adj_matrix);
}

void modules_init(struct event_base *ev_base) {
Expand All @@ -72,24 +147,18 @@ void modules_init(struct event_base *ev_base) {
if (mods == NULL)
ABORT("failed to alloc module array");

qsort(mods, gr_vec_len(mods), sizeof(struct gr_module *), module_init_prio_order);
topo_sort(mods);

gr_vec_foreach (mod, mods) {
if (mod->init != NULL) {
LOG(DEBUG, "%s prio %i", mod->name, mod->init_prio);
LOG(DEBUG, "'%s' (depends on '%s')", mod->name, mod->depends_on ?: "");
mod->init(ev_base);
}
}

gr_vec_free(mods);
}

static int module_fini_prio_order(const void *a, const void *b) {
const struct gr_module *const *mod_a = a;
const struct gr_module *const *mod_b = b;
return (*mod_a)->fini_prio - (*mod_b)->fini_prio;
}

void modules_fini(struct event_base *ev_base) {
struct gr_module *mod, **mods = NULL;

Expand All @@ -99,11 +168,13 @@ void modules_fini(struct event_base *ev_base) {
if (mods == NULL)
ABORT("failed to alloc module array");

qsort(mods, gr_vec_len(mods), sizeof(struct gr_module *), module_fini_prio_order);
topo_sort(mods);

gr_vec_foreach (mod, mods) {
// call fini() functions in reverse topological order
for (int i = gr_vec_len(mods) - 1; i >= 0; i--) {
mod = mods[i];
if (mod->fini != NULL) {
LOG(DEBUG, "%s prio %i", mod->name, mod->fini_prio);
LOG(DEBUG, "'%s' (depends on '%s')", mod->name, mod->depends_on ?: "");
mod->fini(ev_base);
}
}
Expand Down
1 change: 1 addition & 0 deletions modules/infra/control/control_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ static void control_output_fini(struct event_base *) {

static struct gr_module control_output_module = {
.name = "control_output",
.depends_on = "graph",
.init = control_output_init,
.fini = control_output_fini,
};
Expand Down
3 changes: 1 addition & 2 deletions modules/infra/control/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,9 @@ static void graph_fini(struct event_base *) {

static struct gr_module graph_module = {
.name = "graph",
.depends_on = "iface",
.init = graph_init,
.init_prio = -999,
.fini = graph_fini,
.fini_prio = -999,
};

RTE_INIT(control_graph_init) {
Expand Down
2 changes: 1 addition & 1 deletion modules/infra/control/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ static void iface_fini(struct event_base *) {

static struct gr_module iface_module = {
.name = "iface",
.depends_on = "iface port",
.init = iface_init,
.fini = iface_fini,
.fini_prio = 1000,
};

static void iface_event_debug(uint32_t event, const void *obj) {
Expand Down
1 change: 0 additions & 1 deletion modules/infra/control/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ static struct gr_module loopback_module = {
.name = "iface loopback",
.init = loopback_module_init,
.fini = loopback_module_fini,
.fini_prio = 1000,
};

RTE_INIT(loopback_constructor) {
Expand Down
1 change: 0 additions & 1 deletion modules/infra/control/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ static struct gr_module module = {
.name = "nexthop",
.init = nh_init,
.fini = nh_fini,
.fini_prio = 20000,
};

RTE_INIT(init) {
Expand Down
1 change: 0 additions & 1 deletion modules/infra/control/vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ static struct gr_module vlan_module = {
.name = "vlan",
.init = vlan_init,
.fini = vlan_fini,
.fini_prio = 1000,
};

static void port_event(uint32_t event, const void *obj) {
Expand Down
2 changes: 1 addition & 1 deletion modules/infra/control/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ static void worker_fini(struct event_base *) {

static struct gr_module worker_module = {
.name = "worker",
.depends_on = "control_output",
.init = worker_init,
.fini = worker_fini,
.fini_prio = -1000,
};

RTE_INIT(control_infra_init) {
Expand Down
1 change: 0 additions & 1 deletion modules/ip/control/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ static struct gr_module addr_module = {
.name = "ipv4 address",
.init = addr_init,
.fini = addr_fini,
.fini_prio = 2000,
};

static struct gr_event_subscription iface_pre_rm_subscription = {
Expand Down
1 change: 1 addition & 0 deletions modules/ip/control/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ static struct gr_api_handler nh4_list_handler = {

static struct gr_module nh4_module = {
.name = "ipv4 nexthop",
.depends_on = "graph",
.init = nh4_init,
};

Expand Down
1 change: 0 additions & 1 deletion modules/ip/control/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ static struct gr_module route4_module = {
.name = "ipv4 route",
.init = route4_init,
.fini = route4_fini,
.fini_prio = 10000,
};

RTE_INIT(control_ip_init) {
Expand Down
1 change: 0 additions & 1 deletion modules/ip/datapath/fib4.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ static struct gr_module module = {
.name = "fib4",
.init = fib4_init,
.fini = fib4_fini,
.fini_prio = 10000,
};

RTE_INIT(init) {
Expand Down
1 change: 0 additions & 1 deletion modules/ip6/control/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ static struct gr_module addr6_module = {
.name = "ipv6 address",
.init = addr6_init,
.fini = addr6_fini,
.fini_prio = 2000,
};

static struct gr_event_subscription iface_event_subscription = {
Expand Down
1 change: 1 addition & 0 deletions modules/ip6/control/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ static struct gr_api_handler nh6_list_handler = {

static struct gr_module nh6_module = {
.name = "ipv6 nexthop",
.depends_on = "graph",
.init = nh6_init,
};

Expand Down
1 change: 0 additions & 1 deletion modules/ip6/control/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ static struct gr_module route6_module = {
.name = "ipv6 route",
.init = route6_init,
.fini = route6_fini,
.fini_prio = 10000,
};

RTE_INIT(control_ip_init) {
Expand Down
2 changes: 1 addition & 1 deletion modules/ip6/control/router_advert.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ static void ra_fini(struct event_base * /*ev_base*/) {

static struct gr_module ra_module = {
.name = "ipv6 router advertisement",
.depends_on = "graph",
.init = ra_init,
.fini = ra_fini,
.fini_prio = 20000,
};

static struct gr_api_handler ra_set_handler = {
Expand Down
1 change: 0 additions & 1 deletion modules/ip6/datapath/fib6.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ static struct gr_module module = {
.name = "fib6",
.init = fib6_init,
.fini = fib6_fini,
.fini_prio = 10000,
};

RTE_INIT(init) {
Expand Down
1 change: 0 additions & 1 deletion modules/ipip/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ static struct gr_module ipip_module = {
.name = "ipip",
.init = ipip_init,
.fini = ipip_fini,
.fini_prio = 1000,
};

RTE_INIT(ipip_constructor) {
Expand Down
1 change: 0 additions & 1 deletion modules/srv6/control_headend.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,6 @@ static struct gr_module srv6_headend_module = {
.name = "srv6_headend",
.init = srv6_init,
.fini = srv6_fini,
.fini_prio = 1000,
};

RTE_INIT(srv6_constructor) {
Expand Down
1 change: 0 additions & 1 deletion modules/srv6/control_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ static struct gr_module srv6_local_module = {
.name = "srv6_local",
.init = srv6_init,
.fini = srv6_fini,
.fini_prio = 1000,
};

RTE_INIT(srv6_constructor) {
Expand Down