summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Zubkov <green@qrator.net>2024-02-07 19:11:10 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2024-02-07 19:11:10 +0100
commit574d7eb241a60622b0573ab1460cb23d968ba1cc (patch)
treeb17bc117bad5762d520ae91d003c44137918368c
parent0b52f7c01f55707b25eebd0a66c48eafe06fe455 (diff)
BGP: Allow multiple EBGP neighbors with the same peer.
We can distinguish BGP sessions if at least one side uses a different IP address. Extend olock mechanism to handle local IP as a part of key, with optional wildcard, so BGP sessions could local IP in the olock and not block themselves.
-rw-r--r--lib/ip.h4
-rw-r--r--nest/locks.c5
-rw-r--r--nest/locks.h3
-rw-r--r--proto/bgp/bgp.c1
4 files changed, 10 insertions, 3 deletions
diff --git a/lib/ip.h b/lib/ip.h
index f2650d3f..8dd925ed 100644
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -176,6 +176,10 @@ static inline ip6_addr ip6_not(ip6_addr a)
#define ipa_xor(x,y) ip6_xor(x,y)
#define ipa_not(x) ip6_not(x)
+/* Compare addresses when zero address works like a wildcard */
+static inline int ipa_equal_wildcard(ip_addr x, ip_addr y)
+{ return ipa_zero(x) || ipa_zero(y) || ipa_equal(x, y); }
+
/*
* A zero address is either a token for invalid/unused, or the prefix of default
diff --git a/nest/locks.c b/nest/locks.c
index 812a6534..637f2c15 100644
--- a/nest/locks.c
+++ b/nest/locks.c
@@ -48,7 +48,8 @@ olock_same(struct object_lock *x, struct object_lock *y)
x->vrf == y->vrf &&
x->port == y->port &&
x->inst == y->inst &&
- ipa_equal(x->addr, y->addr);
+ ipa_equal(x->addr, y->addr) &&
+ ipa_equal_wildcard(x->addr_local, y->addr_local);
}
static void
@@ -91,7 +92,7 @@ olock_dump(resource *r)
struct object_lock *l = (struct object_lock *) r;
static char *olock_states[] = { "free", "locked", "waiting", "event" };
- debug("(%d:%s:%I:%d:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->port, l->inst, olock_states[l->state]);
+ debug("(%d:%s:%I:%I:%d:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->addr_local, l->port, l->inst, olock_states[l->state]);
if (!EMPTY_LIST(l->waiters))
debug(" [wanted]\n");
}
diff --git a/nest/locks.h b/nest/locks.h
index 37026c68..1686e6ec 100644
--- a/nest/locks.h
+++ b/nest/locks.h
@@ -25,7 +25,8 @@
struct object_lock {
resource r;
- ip_addr addr; /* Identification of a object: IP address */
+ ip_addr addr; /* Identification of a object: IP address (strict compare) */
+ ip_addr addr_local; /* ... another IP address (allow zero IP wildcard) */
uint type; /* ... object type (OBJLOCK_xxx) */
uint port; /* ... port number */
uint inst; /* ... instance ID */
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index cd57c32b..e97b45e6 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1616,6 +1616,7 @@ bgp_start(struct proto *P)
struct object_lock *lock;
lock = p->lock = olock_new(P->pool);
lock->addr = p->remote_ip;
+ lock->addr_local = p->cf->local_ip;
lock->port = p->cf->remote_port;
lock->iface = p->cf->iface;
lock->vrf = p->cf->iface ? NULL : p->p.vrf;