summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proto/bfd/bfd.c28
-rw-r--r--proto/bfd/bfd.h3
-rw-r--r--proto/bfd/packets.c3
3 files changed, 19 insertions, 15 deletions
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index 8dfca790..dac184c5 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -27,13 +27,13 @@
* related to the session and two timers (TX timer for periodic packets and hold
* timer for session timeout). These sessions are allocated from @session_slab
* and are accessible by two hash tables, @session_hash_id (by session ID) and
- * @session_hash_ip (by IP addresses of neighbors). Slab and both hashes are in
- * the main protocol structure &bfd_proto. The protocol logic related to BFD
- * sessions is implemented in internal functions bfd_session_*(), which are
- * expected to be called from the context of BFD thread, and external functions
- * bfd_add_session(), bfd_remove_session() and bfd_reconfigure_session(), which
- * form an interface to the BFD core for the rest and are expected to be called
- * from the context of main thread.
+ * @session_hash_ip (by IP addresses of neighbors and associated interfaces).
+ * Slab and both hashes are in the main protocol structure &bfd_proto. The
+ * protocol logic related to BFD sessions is implemented in internal functions
+ * bfd_session_*(), which are expected to be called from the context of BFD
+ * thread, and external functions bfd_add_session(), bfd_remove_session() and
+ * bfd_reconfigure_session(), which form an interface to the BFD core for the
+ * rest and are expected to be called from the context of main thread.
*
* Each BFD session has an associated BFD interface, represented by structure
* &bfd_iface. A BFD interface contains a socket used for TX (the one for RX is
@@ -108,10 +108,10 @@
#define HASH_ID_EQ(a,b) a == b
#define HASH_ID_FN(k) k
-#define HASH_IP_KEY(n) n->addr
+#define HASH_IP_KEY(n) n->addr, n->ifindex
#define HASH_IP_NEXT(n) n->next_ip
-#define HASH_IP_EQ(a,b) ipa_equal(a,b)
-#define HASH_IP_FN(k) ipa_hash(k)
+#define HASH_IP_EQ(a1,n1,a2,n2) ipa_equal(a1, a2) && n1 == n2
+#define HASH_IP_FN(a,n) ipa_hash(a) ^ u32_hash(n)
static list bfd_proto_list;
static list bfd_wait_list;
@@ -385,9 +385,9 @@ bfd_find_session_by_id(struct bfd_proto *p, u32 id)
}
struct bfd_session *
-bfd_find_session_by_addr(struct bfd_proto *p, ip_addr addr)
+bfd_find_session_by_addr(struct bfd_proto *p, ip_addr addr, uint ifindex)
{
- return HASH_FIND(p->session_hash_ip, HASH_IP, addr);
+ return HASH_FIND(p->session_hash_ip, HASH_IP, addr, ifindex);
}
static void
@@ -426,6 +426,7 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
struct bfd_session *s = sl_allocz(p->session_slab);
s->addr = addr;
s->ifa = ifa;
+ s->ifindex = iface ? iface->index : 0;
s->loc_id = bfd_get_free_id(p);
HASH_INSERT(p->session_hash_id, HASH_ID, s);
@@ -658,7 +659,8 @@ bfd_add_request(struct bfd_proto *p, struct bfd_request *req)
if (req->iface ? !cf->accept_direct : !cf->accept_multihop)
return 0;
- struct bfd_session *s = bfd_find_session_by_addr(p, req->addr);
+ uint ifindex = req->iface ? req->iface->index : 0;
+ struct bfd_session *s = bfd_find_session_by_addr(p, req->addr, ifindex);
u8 state, diag;
if (!s)
diff --git a/proto/bfd/bfd.h b/proto/bfd/bfd.h
index 83e2a991..91fdaa60 100644
--- a/proto/bfd/bfd.h
+++ b/proto/bfd/bfd.h
@@ -153,6 +153,7 @@ struct bfd_session
u8 detect_mult; /* Announced detect_mult, local option */
u8 rem_detect_mult; /* Last received detect_mult */
+ uint ifindex; /* Iface index, for hashing in bfd.session_hash_ip */
btime last_tx; /* Time of last sent periodic control packet */
btime last_rx; /* Time of last received valid control packet */
@@ -213,7 +214,7 @@ static inline void bfd_unlock_sessions(struct bfd_proto *p) { pthread_spin_unloc
/* bfd.c */
struct bfd_session * bfd_find_session_by_id(struct bfd_proto *p, u32 id);
-struct bfd_session * bfd_find_session_by_addr(struct bfd_proto *p, ip_addr addr);
+struct bfd_session * bfd_find_session_by_addr(struct bfd_proto *p, ip_addr addr, uint ifindex);
void bfd_session_process_ctl(struct bfd_session *s, u8 flags, u32 old_tx_int, u32 old_rx_int);
void bfd_show_sessions(struct proto *P);
diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c
index 703c6e28..7618e20f 100644
--- a/proto/bfd/packets.c
+++ b/proto/bfd/packets.c
@@ -366,7 +366,8 @@ bfd_rx_hook(sock *sk, uint len)
if (ps > BFD_STATE_DOWN)
DROP("invalid init state", ps);
- s = bfd_find_session_by_addr(p, sk->faddr);
+ uint ifindex = (sk->sport == BFD_CONTROL_PORT) ? sk->lifindex : 0;
+ s = bfd_find_session_by_addr(p, sk->faddr, ifindex);
/* FIXME: better session matching and message */
if (!s)