summaryrefslogtreecommitdiffstats
path: root/nest/proto.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
commitbf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5 (patch)
tree59108f1bdc8f5192a27e9a40d72a7e950686dd8c /nest/proto.c
parent5e6f568115511e2bcf43c60dfdcbd7a35cb04b93 (diff)
downloadbird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.tar
bird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.zip
Implements BGP route refresh.
Diffstat (limited to 'nest/proto.c')
-rw-r--r--nest/proto.c67
1 files changed, 61 insertions, 6 deletions
diff --git a/nest/proto.c b/nest/proto.c
index c05db76..c531d86 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -73,6 +73,10 @@ proto_relink(struct proto *p)
rem_node(&p->n);
switch (p->core_state)
{
+ case FS_HUNGRY:
+ l = &inactive_proto_list;
+ break;
+ case FS_FEEDING:
case FS_HAPPY:
l = &active_proto_list;
break;
@@ -80,7 +84,7 @@ proto_relink(struct proto *p)
l = &flush_proto_list;
break;
default:
- l = &inactive_proto_list;
+ ASSERT(0);
}
proto_enqueue(l, p);
}
@@ -549,7 +553,7 @@ proto_feed_more(void *P)
}
static void
-proto_feed(void *P)
+proto_feed_initial(void *P)
{
struct proto *p = P;
@@ -577,16 +581,45 @@ proto_schedule_flush(struct proto *p)
}
static void
-proto_schedule_feed(struct proto *p)
+proto_schedule_feed(struct proto *p, int initial)
{
DBG("%s: Scheduling meal\n", p->name);
p->core_state = FS_FEEDING;
proto_relink(p);
- p->attn->hook = proto_feed;
+ p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
ev_schedule(p->attn);
}
/**
+ * proto_request_feeding - request feeding routes to the protocol
+ * @p: given protocol
+ *
+ * Sometimes it is needed to send again all routes to the
+ * protocol. This is called feeding and can be requested by this
+ * function. This would cause protocol core state transition
+ * to FS_FEEDING (during feeding) and when completed, it will
+ * switch back to FS_HAPPY. This function can be called even
+ * when feeding is already running, in that case it is restarted.
+ */
+void
+proto_request_feeding(struct proto *p)
+{
+ ASSERT(p->proto_state == PS_UP);
+
+ /* If we are already feeding, we want to restart it */
+ if (p->core_state == FS_FEEDING)
+ {
+ /* Unless feeding is in initial state */
+ if (p->attn->hook == proto_feed_initial)
+ return;
+
+ rt_feed_baby_abort(p);
+ }
+
+ proto_schedule_feed(p, 0);
+}
+
+/**
* proto_notify_state - notify core about protocol state change
* @p: protocol the state of which has changed
* @ps: the new status
@@ -635,7 +668,7 @@ proto_notify_state(struct proto *p, unsigned ps)
case PS_UP:
ASSERT(ops == PS_DOWN || ops == PS_START);
ASSERT(cs == FS_HUNGRY);
- proto_schedule_feed(p);
+ proto_schedule_feed(p, 1);
break;
case PS_STOP:
if ((cs = FS_FEEDING) || (cs == FS_HAPPY))
@@ -798,6 +831,7 @@ proto_xxable(char *pattern, int xx)
{
cli_msg(-9, "%s: disabled", p->name);
p->disabled = 1;
+ proto_rethink_goal(p);
}
break;
case 1:
@@ -807,6 +841,7 @@ proto_xxable(char *pattern, int xx)
{
cli_msg(-11, "%s: enabled", p->name);
p->disabled = 0;
+ proto_rethink_goal(p);
}
break;
case 2:
@@ -817,13 +852,33 @@ proto_xxable(char *pattern, int xx)
p->disabled = 1;
proto_rethink_goal(p);
p->disabled = 0;
+ proto_rethink_goal(p);
cli_msg(-12, "%s: restarted", p->name);
}
break;
+ case 3:
+ // FIXME change msg number
+ if (p->disabled)
+ cli_msg(-8, "%s: already disabled", p->name);
+ else if (p->reload_routes && p->reload_routes(p))
+ cli_msg(-12, "%s: reloading", p->name);
+ else
+ cli_msg(-12, "%s: reload failed", p->name);
+ break;
+ case 4:
+ // FIXME change msg number
+ if (p->disabled)
+ cli_msg(-8, "%s: already disabled", p->name);
+ else
+ {
+ proto_request_feeding(p);
+ cli_msg(-12, "%s: reexport failed", p->name);
+ }
+ break;
+
default:
ASSERT(0);
}
- proto_rethink_goal(p);
}
WALK_PROTO_LIST_END;
if (!cnt)