This should help flushing the tx buffers as soon as possible.
void
bgp_tx_resend(struct bgp_proto *p, struct bgp_channel *bc)
{
- BGP_PTX_LOCK(bc->tx, c);
-
- ASSERT_DIE(bc->tx_keep);
uint seen = 0;
-
- HASH_WALK(c->prefix_hash, next, px)
{
- if (!px->cur)
+ BGP_PTX_LOCK(bc->tx, c);
+
+ ASSERT_DIE(bc->tx_keep);
+
+ HASH_WALK(c->prefix_hash, next, px)
{
- ASSERT_DIE(px->last);
- struct bgp_bucket *last = px->last;
+ if (!px->cur)
+ {
+ ASSERT_DIE(px->last);
+ struct bgp_bucket *last = px->last;
- /* Remove the last reference, we wanna resend the route */
- px->last->px_uc--;
- px->last = NULL;
+ /* Remove the last reference, we wanna resend the route */
+ px->last->px_uc--;
+ px->last = NULL;
- /* And send it once again */
- seen += bgp_update_prefix(c, px, last);
+ /* And send it once again */
+ seen += bgp_update_prefix(c, px, last);
+ }
}
- }
- HASH_WALK_END;
+ HASH_WALK_END;
- if (bc->c.debug & D_EVENTS)
- log(L_TRACE "%s.%s: TX resending %u routes",
- bc->c.proto->name, bc->c.name, seen);
+ if (bc->c.debug & D_EVENTS)
+ log(L_TRACE "%s.%s: TX resending %u routes",
+ bc->c.proto->name, bc->c.name, seen);
+ }
if (seen)
bgp_schedule_packet(p->conn, bc, PKT_UPDATE);
}
conn->hold_timer = NULL;
rfree(conn->send_hold_timer);
conn->send_hold_timer = NULL;
- rfree(conn->tx_ev);
- conn->tx_ev = NULL;
sk_close(conn->sk);
conn->sk = NULL;
DBG("BGP: Keepalive timer\n");
bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE);
-
- /* Kick TX a bit faster */
- if (ev_active(conn->tx_ev))
- ev_run(conn->tx_ev);
}
void
conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0);
conn->keepalive_timer = tm_new_init(p->p.pool, bgp_keepalive_timeout, conn, 0, 0);
conn->send_hold_timer = tm_new_init(p->p.pool, bgp_send_hold_timeout, conn, 0, 0);
-
- conn->tx_ev = ev_new_init(p->p.pool, bgp_kick_tx, conn);
}
static void
tm_remains(p->conn->hold_timer), p->conn->hold_time);
cli_msg(-1006, " Keepalive timer: %t/%u",
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time);
- cli_msg(-1006, " TX pending: %d bytes%s",
- p->conn->sk->tpos - p->conn->sk->ttx,
- ev_active(p->conn->tx_ev) ? " (refill scheduled)" : "");
+ cli_msg(-1006, " TX pending: %d bytes",
+ p->conn->sk->tpos - p->conn->sk->ttx);
cli_msg(-1006, " Send hold timer: %t/%u",
tm_remains(p->conn->send_hold_timer), p->conn->send_hold_time);
}
timer *hold_timer;
timer *keepalive_timer;
timer *send_hold_timer;
- event *tx_ev;
u32 packets_to_send; /* Bitmap of packet types to be sent */
u32 channels_to_send; /* Bitmap of channels with packets to be sent */
u8 last_channel; /* Channel used last time for TX */
const struct bgp_af_desc *bgp_get_af_desc(u32 afi);
const struct bgp_af_caps *bgp_find_af_caps(struct bgp_caps *caps, u32 afi);
void bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type);
-void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk);
int bgp_rx(struct birdsock *sk, uint size);
void bgp_do_uncork(callback *);
conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session);
bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE);
- bgp_start_timer(p, conn->hold_timer, conn->hold_time);
- bgp_start_timer(p, conn->send_hold_timer, conn->send_hold_time);
- bgp_conn_enter_openconfirm_state(conn);
+ if (conn->sk)
+ {
+ bgp_start_timer(p, conn->hold_timer, conn->hold_time);
+ bgp_start_timer(p, conn->send_hold_timer, conn->send_hold_time);
+ bgp_conn_enter_openconfirm_state(conn);
+ }
}
return 0;
}
+static void bgp_tx_deferred(struct deferred_call *dc);
+struct bgp_tx_deferred_call {
+ struct deferred_call dc;
+ struct bgp_conn *conn;
+};
+
/**
* bgp_schedule_packet - schedule a packet for transmission
* @conn: connection
else
BGP_TRACE(D_PACKETS, "Scheduling packet type %d", type);
+ bool was_active = conn->channels_to_send || conn->packets_to_send;
+
if (c)
{
if (! conn->channels_to_send)
else
conn->packets_to_send |= 1 << type;
- if ((conn->sk->tpos == conn->sk->tbuf) && !ev_active(conn->tx_ev))
- proto_send_event(&p->p, conn->tx_ev);
+ if (was_active || (conn->sk->tpos != conn->sk->tbuf))
+ return;
+ else if ((type == PKT_KEEPALIVE) || (this_birdloop != p->p.loop))
+ while (bgp_fire_tx(conn) > 0)
+ ;
+ else
+ {
+ struct bgp_tx_deferred_call btdc = {
+ .dc.hook = bgp_tx_deferred,
+ .conn = conn,
+ };
+ defer_call(&btdc.dc, sizeof btdc);
+ }
}
-void
-bgp_kick_tx(void *vconn)
-{
- struct bgp_conn *conn = vconn;
+static void
+bgp_tx_deferred(struct deferred_call *dc)
+{
+ struct bgp_conn *conn = SKIP_BACK(struct bgp_tx_deferred_call, dc, dc)->conn;
DBG("BGP: kicking TX\n");
while (bgp_fire_tx(conn) > 0)
- MAYBE_DEFER_TASK(proto_event_list(&conn->bgp->p), conn->tx_ev,
- "BGP TX for %s", conn->bgp->p.name);
+ ;
}
void
DBG("BGP: TX hook\n");
while (bgp_fire_tx(conn) > 0)
- MAYBE_DEFER_TASK(proto_event_list(&conn->bgp->p), conn->tx_ev,
- "BGP TX for %s", conn->bgp->p.name);
+ ;
}