mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 01:31:55 +00:00
bfd: when all (not dummy) requests from a bfd session removed, timeout starts. If timeout ends without adding a request to that session, session is deleted. (Keeping empty session is done by having dummy request)
This commit is contained in:
parent
416a51ac92
commit
fee58fd886
@ -17,6 +17,7 @@ struct bfd_options {
|
||||
u32 min_rx_int;
|
||||
u32 min_tx_int;
|
||||
u32 idle_tx_int;
|
||||
u32 session_delete_timeout;
|
||||
u8 multiplier;
|
||||
u8 passive;
|
||||
u8 passive_set;
|
||||
|
@ -159,6 +159,7 @@ static void bfd_session_set_min_tx(struct bfd_session *s, u32 val);
|
||||
static struct bfd_iface *bfd_get_iface(struct bfd_proto *p, ip_addr local, struct iface *iface);
|
||||
static void bfd_free_iface(struct bfd_iface *ifa);
|
||||
static inline void bfd_notify_kick(struct bfd_proto *p);
|
||||
static void bfd_request_free(resource *r);
|
||||
|
||||
|
||||
/*
|
||||
@ -693,6 +694,22 @@ bfd_request_notify(struct bfd_request *req, u8 state, u8 remote, u8 diag)
|
||||
req->hook(req);
|
||||
}
|
||||
|
||||
void
|
||||
bfd_delete_dummy_request(timer *t)
|
||||
{
|
||||
struct bfd_session *s = t->data;
|
||||
struct bfd_request *req = s->dummy_request.req;
|
||||
s->dummy_request.req = NULL;
|
||||
if (list_length(&s->request_list) != 1)
|
||||
{
|
||||
log(L_WARN "BFD: Attempt to delete dummy request from session with % requests in total.", list_length(&s->request_list));
|
||||
return;
|
||||
}
|
||||
rfree(&req->r);
|
||||
}
|
||||
|
||||
static struct resclass bfd_request_class;
|
||||
|
||||
static int
|
||||
bfd_add_request(struct bfd_proto *p, struct bfd_request *req)
|
||||
{
|
||||
@ -712,7 +729,18 @@ bfd_add_request(struct bfd_proto *p, struct bfd_request *req)
|
||||
u8 loc_state, rem_state, diag;
|
||||
|
||||
if (!s)
|
||||
{
|
||||
s = bfd_add_session(p, req->addr, req->local, req->iface, &req->opts);
|
||||
// Create one dummy request in order to be able keep session some time after last real request will be removed
|
||||
struct bfd_request *dummy_request = ralloc(p->p.pool, &bfd_request_class);
|
||||
add_tail(&s->request_list, &dummy_request->n);
|
||||
dummy_request->session = s;
|
||||
|
||||
s->dummy_request.t = tm_new_init(p->p.pool, bfd_delete_dummy_request, s, 0, 0);
|
||||
s->dummy_request.req = dummy_request;
|
||||
s->dummy_request.p = p;
|
||||
} else
|
||||
tm_stop(s->dummy_request.t);
|
||||
|
||||
rem_node(&req->n);
|
||||
add_tail(&s->request_list, &req->n);
|
||||
@ -767,8 +795,6 @@ bfd_drop_requests(struct bfd_proto *p)
|
||||
HASH_WALK_END(p->session_hash_id);
|
||||
}
|
||||
|
||||
static struct resclass bfd_request_class;
|
||||
|
||||
struct bfd_request *
|
||||
bfd_request_session(pool *p, ip_addr addr, ip_addr local,
|
||||
struct iface *iface, struct iface *vrf,
|
||||
@ -821,8 +847,20 @@ bfd_request_free(resource *r)
|
||||
/* Remove the session if there is no request for it. Skip that if
|
||||
inside notify hooks, will be handled by bfd_notify_hook() itself */
|
||||
|
||||
if (s && EMPTY_LIST(s->request_list) && !s->notify_running)
|
||||
if (s && EMPTY_LIST(s->request_list))
|
||||
bfd_remove_session(s->ifa->bfd, s);
|
||||
else if (s && list_length(&s->request_list) == 1)
|
||||
{
|
||||
struct bfd_request *f_req = SKIP_BACK(struct bfd_request, n, HEAD(s->request_list));
|
||||
if (f_req != s->dummy_request.req)
|
||||
bug("Last bfd request is not the dummy one");
|
||||
if (!tm_active(s->dummy_request.t))
|
||||
{
|
||||
struct bfd_config *conf = (struct bfd_config *) (s->dummy_request.p->p.cf);
|
||||
btime time = (btime) conf->session_delete_timeout S;
|
||||
tm_start(s->dummy_request.t, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -986,14 +1024,9 @@ bfd_notify_hook(sock *sk, uint len UNUSED)
|
||||
diag = s->loc_diag;
|
||||
bfd_unlock_sessions(p);
|
||||
|
||||
s->notify_running = 1;
|
||||
WALK_LIST_DELSAFE(n, nn, s->request_list)
|
||||
bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), loc_state, rem_state, diag);
|
||||
s->notify_running = 0;
|
||||
|
||||
/* Remove the session if all requests were removed in notify hooks */
|
||||
if (EMPTY_LIST(s->request_list))
|
||||
bfd_remove_session(p, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -43,6 +43,7 @@ struct bfd_config
|
||||
list patt_list; /* List of iface configs (struct bfd_iface_config) */
|
||||
list neigh_list; /* List of configured neighbors (struct bfd_neighbor) */
|
||||
struct bfd_iface_config *multihop; /* Multihop pseudoiface config */
|
||||
u32 session_delete_timeout;
|
||||
u8 accept_ipv4;
|
||||
u8 accept_ipv6;
|
||||
u8 accept_direct;
|
||||
@ -124,6 +125,13 @@ struct bfd_iface
|
||||
u8 changed;
|
||||
};
|
||||
|
||||
struct dummy_request
|
||||
{
|
||||
struct bfd_request *req;
|
||||
struct bfd_proto *p; // to get actual timeout
|
||||
timer *t;
|
||||
};
|
||||
|
||||
struct bfd_session
|
||||
{
|
||||
node n;
|
||||
@ -165,8 +173,8 @@ struct bfd_session
|
||||
timer *hold_timer; /* Timer for session down detection time */
|
||||
|
||||
list request_list; /* List of client requests (struct bfd_request) */
|
||||
struct dummy_request dummy_request; /* Request and timer for delating removing session */
|
||||
btime last_state_change; /* Time of last state change */
|
||||
u8 notify_running; /* 1 if notify hooks are running */
|
||||
|
||||
u8 rx_csn_known; /* Received crypto sequence number is known */
|
||||
u32 rx_csn; /* Last received crypto sequence number */
|
||||
|
@ -24,7 +24,7 @@ CF_DECLS
|
||||
CF_KEYWORDS(BFD, MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE,
|
||||
INTERFACE, MULTIHOP, NEIGHBOR, DEV, LOCAL, AUTHENTICATION,
|
||||
NONE, SIMPLE, METICULOUS, KEYED, MD5, SHA1, IPV4, IPV6, DIRECT,
|
||||
STRICT, BIND)
|
||||
STRICT, BIND, SESSION, DELETE, TIMEOUT)
|
||||
|
||||
%type <iface> bfd_neigh_iface
|
||||
%type <a> bfd_neigh_local
|
||||
@ -42,6 +42,7 @@ bfd_proto_start: proto_start BFD
|
||||
init_list(&BFD_CFG->neigh_list);
|
||||
BFD_CFG->accept_ipv4 = BFD_CFG->accept_ipv6 = 1;
|
||||
BFD_CFG->accept_direct = BFD_CFG->accept_multihop = 1;
|
||||
BFD_CFG->session_delete_timeout = 30;
|
||||
};
|
||||
|
||||
bfd_proto_item:
|
||||
@ -51,6 +52,7 @@ bfd_proto_item:
|
||||
| MULTIHOP bfd_multihop
|
||||
| NEIGHBOR bfd_neighbor
|
||||
| STRICT BIND bool { BFD_CFG->strict_bind = $3; }
|
||||
| SESSION DELETE TIMEOUT expr { BFD_CFG->session_delete_timeout = $4; }
|
||||
;
|
||||
|
||||
bfd_proto_opts:
|
||||
|
Loading…
Reference in New Issue
Block a user