/* Data structures for export journal */
static void rt_free_hostcache(struct rtable_private *tab);
+static void rt_hcu_uncork(void *_tab);
static void rt_update_hostcache(void *tab);
static void rt_next_hop_update(void *_tab);
static void rt_nhu_uncork(void *_tab);
hc->tab = RT_PUB(tab);
tab->hcu_event = ev_new_init(tab->rp, rt_update_hostcache, tab);
- tab->hcu_uncork_event = ev_new_init(tab->rp, rt_update_hostcache, tab);
+ tab->hcu_uncork_event = ev_new_init(tab->rp, rt_hcu_uncork, tab);
tab->hostcache = hc;
ev_send_loop(tab->loop, tab->hcu_event);
return old_src != new_src;
}
+static void
+rt_hcu_uncork(void *_tab)
+{
+ RT_LOCKED((rtable *) _tab, tab)
+ ev_send_loop(tab->loop, tab->hcu_event);
+}
+
static void
rt_update_hostcache(void *data)
{
bgp_close(p);
}
+ rfree(p->uncork_do_ev);
+
p->neigh = NULL;
BGP_TRACE(D_EVENTS, "Down");
bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len)
{
proto_notify_state(&p->p, PS_STOP);
- p->uncork_ev->data = NULL;
+
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
p->last_rx_update = 0;
p->event = ev_new_init(p->p.pool, bgp_decision, p);
- p->uncork_ev = ev_new_init(p->p.pool, bgp_uncork, p);
+ p->uncork_main_ev = ev_new_init(p->p.pool, bgp_uncork_main, p);
+ p->uncork_do_ev = ev_new_init(p->p.pool, bgp_do_uncork, p);
p->startup_timer = tm_new_init(p->p.pool, bgp_startup_timeout, p, 0, 0);
p->gr_timer = tm_new_init(p->p.pool, bgp_graceful_restart_timeout, p, 0, 0);
struct bgp_listen_request listen; /* Shared listening socket */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
struct birdsock *postponed_sk; /* Postponed incoming socket for dynamic BGP */
- event *uncork_ev; /* Uncork event in case of congestion */
+ event *uncork_main_ev; /* Uncork event for mainloop */
+ event *uncork_do_ev; /* Uncork event to actually uncork */
struct bgp_stats stats; /* BGP statistics */
btime last_established; /* Last time of enter/leave of established state */
btime last_rx_update; /* Last time of RX update */
void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk);
int bgp_rx(struct birdsock *sk, uint size);
-void bgp_uncork(void *vp);
+void bgp_uncork_main(void *vp);
+void bgp_do_uncork(void *vp);
const char * bgp_error_dsc(unsigned code, unsigned subcode);
void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
}
void
-bgp_uncork(void *vp)
+bgp_do_uncork(void *vp)
{
- /* The uncork event is run from &main_birdloop and there is no useful way how
- * to assign the target loop to it, thus we have to lock it ourselves. */
-
struct bgp_proto *p = vp;
- if (!p)
- return;
-
- birdloop_enter(p->p.loop);
+ ASSERT_DIE(birdloop_inside(p->p.loop));
+ ASSERT_DIE(p->p.active_loops--);
- if (p && p->conn && (p->conn->state == BS_ESTABLISHED) && !p->conn->sk->rx_hook)
+ if (p->p.proto_state == PS_DOWN)
+ ev_send_loop(p->p.loop, p->p.event);
+ else if (p->conn && (p->conn->state == BS_ESTABLISHED) && !p->conn->sk->rx_hook)
{
struct birdsock *sk = p->conn->sk;
ASSERT_DIE(sk->rpos > sk->rbuf);
bgp_rx(sk, sk->rpos - sk->rbuf);
BGP_TRACE(D_PACKETS, "Uncorked");
}
+}
- birdloop_leave(p->p.loop);
+void
+bgp_uncork_main(void *vp)
+{
+ /* The uncork event is run from &main_birdloop and there is no useful way how
+ * to assign the target loop to it, thus we have to lock it ourselves. */
+
+ struct bgp_proto *p = vp;
+ ev_send_loop(p->p.loop, p->uncork_do_ev);
}
/**
{
if ((conn->state == BS_CLOSE) || (conn->sk != sk))
return 0;
- if ((conn->state == BS_ESTABLISHED) && rt_cork_check(conn->bgp->uncork_ev))
+ if ((conn->state == BS_ESTABLISHED) && rt_cork_check(conn->bgp->uncork_main_ev))
{
sk_pause_rx(p->p.loop, sk);
+ p->p.active_loops++;
BGP_TRACE(D_PACKETS, "Corked");
break;
}