On Sat, Jan 08, 2011 at 08:24:18PM +0100, Marcel Wiget wrote:
> On Jan 8, 2011, at 4:20 PM, Claudio Jeker wrote:
>
> > provide a diff for this soon. Btw. I would be interested in the ldpd -dv
> > output of the failures you get when the JUNOS has RFC 3479 enabled or when
> > a different transport addr is used.
>
> This time I removed the statement 'set protocols ldp transport-address
> interface' from junos and get the following ldpd -dv output (I added the
> output of src.sin_addr to the log_debug msg, diff further down). 192.168.100.3
> is the routers loopback address. Openbsd has a route to that loopback. The
> router does send the LDP hello's from the interface IP address, but initiates
> the TCP session from its loopback. Let me know if you need more details.
>
The problem here is the ospfd heritage of ldpd. The neighbor structures
are bound to interfaces and the lookup is done on them. This fails as soon
as the connection comes from a not directly attached interface.
Here is a diff that should solve this issue (just lightly tested). It
moves the neighbor structures away from per interface lists to a global
neighbor tree. This should also help with implementing target session,
etc.
--
:wq Claudio
Index: hello.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/hello.c,v
retrieving revision 1.8
diff -u -p -r1.8 hello.c
--- hello.c 8 Jan 2011 14:50:29 -0000 1.8
+++ hello.c 9 Jan 2011 10:56:56 -0000
@@ -122,7 +122,7 @@ recv_hello(struct iface *iface, struct i
return;
}
- nbr = nbr_find_ldpid(iface, ldp.lsr_id, ldp.lspace_id);
+ nbr = nbr_find_ldpid(ldp.lsr_id, ldp.lspace_id);
if (!nbr) {
nbr = nbr_new(ldp.lsr_id, ldp.lspace_id, iface);
Index: interface.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/interface.c,v
retrieving revision 1.6
diff -u -p -r1.6 interface.c
--- interface.c 19 May 2010 15:28:51 -0000 1.6
+++ interface.c 9 Jan 2011 10:58:26 -0000
@@ -133,7 +133,6 @@ if_new(struct kif *kif, struct kif_addr
iface->state = IF_STA_DOWN;
- LIST_INIT(&iface->nbr_list);
LIST_INIT(&iface->lde_nbr_list);
strlcpy(iface->name, kif->ifname, sizeof(iface->name));
@@ -170,14 +169,8 @@ if_new(struct kif *kif, struct kif_addr
void
if_del(struct iface *iface)
{
- struct nbr *nbr = NULL;
-
log_debug("if_del: interface %s", iface->name);
- /* clear lists etc */
- while ((nbr = LIST_FIRST(&iface->nbr_list)) != NULL)
- nbr_del(nbr);
-
if (evtimer_pending(&iface->hello_timer, NULL))
evtimer_del(&iface->hello_timer);
@@ -267,7 +260,6 @@ if_act_start(struct iface *iface)
int
if_act_reset(struct iface *iface)
{
-/* struct nbr *nbr = NULL; */
struct in_addr addr;
inet_aton(AllRouters, &addr);
@@ -275,14 +267,6 @@ if_act_reset(struct iface *iface)
log_warnx("if_act_reset: error leaving group %s, "
"interface %s", inet_ntoa(addr), iface->name);
}
-/*
- LIST_FOREACH(nbr, &iface->nbr_list, entry) {
- if (nbr_fsm(nbr, NBR_EVT_KILL_NBR)) {
- log_debug("if_act_reset: error killing neighbor %s",
- inet_ntoa(nbr->id));
- }
- }
-*/
return (0);
}
@@ -291,7 +275,6 @@ if_to_ctl(struct iface *iface)
{
static struct ctl_iface ictl;
struct timeval tv, now, res;
- struct nbr *nbr;
memcpy(ictl.name, iface->name, sizeof(ictl.name));
memcpy(&ictl.addr, &iface->addr, sizeof(ictl.addr));
@@ -300,8 +283,6 @@ if_to_ctl(struct iface *iface)
ictl.ifindex = iface->ifindex;
ictl.state = iface->state;
ictl.mtu = iface->mtu;
- ictl.nbr_cnt = 0;
- ictl.adj_cnt = 0;
ictl.baudrate = iface->baudrate;
ictl.holdtime = iface->holdtime;
ictl.hello_interval = iface->hello_interval;
@@ -323,9 +304,6 @@ if_to_ctl(struct iface *iface)
ictl.uptime = now.tv_sec - iface->uptime;
} else
ictl.uptime = 0;
-
- LIST_FOREACH(nbr, &iface->nbr_list, entry)
- ictl.nbr_cnt++;
return (&ictl);
}
Index: ldpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpd.h,v
retrieving revision 1.27
diff -u -p -r1.27 ldpd.h
--- ldpd.h 7 Oct 2010 12:02:23 -0000 1.27
+++ ldpd.h 9 Jan 2011 10:33:06 -0000
@@ -199,7 +199,6 @@ struct iface {
LIST_ENTRY(iface) entry;
struct event hello_timer;
- LIST_HEAD(, nbr) nbr_list;
LIST_HEAD(, lde_nbr) lde_nbr_list;
char name[IF_NAMESIZE];
Index: ldpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpe.c,v
retrieving revision 1.13
diff -u -p -r1.13 ldpe.c
--- ldpe.c 26 Oct 2010 12:03:11 -0000 1.13
+++ ldpe.c 9 Jan 2011 11:20:13 -0000
@@ -160,7 +160,6 @@ ldpe(struct ldpd_conf *xconf, int pipe_p
fatal("can't drop privileges");
event_init();
- nbr_init(NBR_HASHSIZE);
/* setup signal handler */
signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
@@ -497,23 +496,4 @@ ldpe_iface_ctl(struct ctl_conn *c, unsig
0, 0, -1, ictl, sizeof(struct ctl_iface));
}
}
-}
-
-void
-ldpe_nbr_ctl(struct ctl_conn *c)
-{
- struct iface *iface;
- struct nbr *nbr;
- struct ctl_nbr *nctl;
-
- LIST_FOREACH(iface, &leconf->iface_list, entry) {
- LIST_FOREACH(nbr, &iface->nbr_list, entry) {
- nctl = nbr_to_ctl(nbr);
- imsg_compose_event(&c->iev,
- IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
- sizeof(struct ctl_nbr));
- }
- }
-
- imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
}
Index: ldpe.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldpe.h,v
retrieving revision 1.13
diff -u -p -r1.13 ldpe.h
--- ldpe.h 4 Nov 2010 09:52:16 -0000 1.13
+++ ldpe.h 9 Jan 2011 11:20:22 -0000
@@ -35,7 +35,7 @@ struct mapping_entry {
};
struct nbr {
- LIST_ENTRY(nbr) entry, hash;
+ RB_ENTRY(nbr) id_tree, addr_tree, pid_tree;
struct evbuf wbuf;
struct event rev;
struct event inactivity_timer;
@@ -119,7 +119,6 @@ int ldpe_imsg_compose_lde(int, u_int32
u_int32_t ldpe_router_id(void);
void ldpe_fib_update(int);
void ldpe_iface_ctl(struct ctl_conn *, unsigned int);
-void ldpe_nbr_ctl(struct ctl_conn *);
/* interface.c */
int if_fsm(struct iface *, enum iface_event);
@@ -144,12 +143,11 @@ int if_set_tos(int, int);
int if_set_reuse(int, int);
/* neighbor.c */
-void nbr_init(u_int32_t);
struct nbr *nbr_new(u_int32_t, u_int16_t, struct iface *);
void nbr_del(struct nbr *);
-struct nbr *nbr_find_ip(struct iface *, u_int32_t);
-struct nbr *nbr_find_ldpid(struct iface *, u_int32_t, u_int16_t);
+struct nbr *nbr_find_ip(u_int32_t);
+struct nbr *nbr_find_ldpid(u_int32_t, u_int16_t);
struct nbr *nbr_find_peerid(u_int32_t);
int nbr_fsm(struct nbr *, enum nbr_event);
@@ -180,6 +178,7 @@ void nbr_mapping_list_clr(struct
nbr
struct mapping_head *);
struct ctl_nbr *nbr_to_ctl(struct nbr *);
+void ldpe_nbr_ctl(struct ctl_conn *);
/* packet.c */
int gen_ldp_hdr(struct ibuf *, struct iface *, u_int16_t);
Index: neighbor.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/neighbor.c,v
retrieving revision 1.22
diff -u -p -r1.22 neighbor.c
--- neighbor.c 26 Oct 2010 12:22:35 -0000 1.22
+++ neighbor.c 9 Jan 2011 11:16:19 -0000
@@ -37,6 +37,7 @@
#include "ldpd.h"
#include "ldp.h"
#include "ldpe.h"
+#include "control.h"
#include "log.h"
#include "lde.h"
@@ -44,15 +45,43 @@ int nbr_establish_connection(struct nbr
void nbr_send_labelmappings(struct nbr *);
int nbr_act_session_operational(struct nbr *);
-LIST_HEAD(nbr_head, nbr);
+static __inline int nbr_id_compare(struct nbr *, struct nbr *);
+static __inline int nbr_addr_compare(struct nbr *, struct nbr *);
+static __inline int nbr_pid_compare(struct nbr *, struct nbr *);
-struct nbr_table {
- struct nbr_head *hashtbl;
- u_int32_t hashmask;
-} nbrtable;
+RB_HEAD(nbr_id_head, nbr);
+RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
+RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
+RB_HEAD(nbr_addr_head, nbr);
+RB_PROTOTYPE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
+RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
+RB_HEAD(nbr_pid_head, nbr);
+RB_PROTOTYPE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
+RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
-#define NBR_HASH(x) \
- &nbrtable.hashtbl[(x) & nbrtable.hashmask]
+static __inline int
+nbr_id_compare(struct nbr *a, struct nbr *b)
+{
+ if (ntohl(a->id.s_addr) - ntohl(b->id.s_addr) == 0)
+ return (a->lspace - b->lspace);
+ return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr));
+}
+
+static __inline int
+nbr_addr_compare(struct nbr *a, struct nbr *b)
+{
+ return (ntohl(a->addr.s_addr) - ntohl(b->addr.s_addr));
+}
+
+static __inline int
+nbr_pid_compare(struct nbr *a, struct nbr *b)
+{
+ return (a->peerid - b->peerid);
+}
+
+struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id);
+struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr);
+struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid);
u_int32_t peercnt = NBR_CNTSTART;
@@ -206,27 +235,9 @@ nbr_fsm(struct nbr *nbr, enum nbr_event
return (ret);
}
-void
-nbr_init(u_int32_t hashsize)
-{
- u_int32_t hs, i;
-
- for (hs = 1; hs < hashsize; hs <<= 1)
- ;
- nbrtable.hashtbl = calloc(hs, sizeof(struct nbr_head));
- if (nbrtable.hashtbl == NULL)
- fatal("nbr_init");
-
- for (i = 0; i < hs; i++)
- LIST_INIT(&nbrtable.hashtbl[i]);
-
- nbrtable.hashmask = hs - 1;
-}
-
struct nbr *
nbr_new(u_int32_t nbr_id, u_int16_t lspace, struct iface *iface)
{
- struct nbr_head *head;
struct nbr *nbr;
if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
@@ -237,17 +248,19 @@ nbr_new(u_int32_t nbr_id, u_int16_t lspa
nbr->state = NBR_STA_DOWN;
nbr->id.s_addr = nbr_id;
nbr->lspace = lspace;
+ nbr->iface = iface;
/* get next unused peerid */
while (nbr_find_peerid(++peercnt))
;
nbr->peerid = peercnt;
- head = NBR_HASH(nbr->peerid);
- LIST_INSERT_HEAD(head, nbr, hash);
- /* add to peer list */
- nbr->iface = iface;
- LIST_INSERT_HEAD(&iface->nbr_list, nbr, entry);
+ if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL)
+ fatalx("nbr_new: RB_INSERT(nbrs_by_pid) failed");
+ if (RB_INSERT(nbr_addr_head, &nbrs_by_addr, nbr) != NULL)
+ fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed");
+ if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL)
+ fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
TAILQ_INIT(&nbr->mapping_list);
TAILQ_INIT(&nbr->withdraw_list);
@@ -280,8 +293,9 @@ nbr_del(struct nbr *nbr)
nbr_mapping_list_clr(nbr, &nbr->mapping_list);
- LIST_REMOVE(nbr, entry);
- LIST_REMOVE(nbr, hash);
+ RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
+ RB_REMOVE(nbr_addr_head, &nbrs_by_addr, nbr);
+ RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);
free(nbr->rbuf);
free(nbr);
@@ -290,43 +304,26 @@ nbr_del(struct nbr *nbr)
struct nbr *
nbr_find_peerid(u_int32_t peerid)
{
- struct nbr_head *head;
- struct nbr *nbr;
-
- head = NBR_HASH(peerid);
-
- LIST_FOREACH(nbr, head, hash) {
- if (nbr->peerid == peerid)
- return (nbr);
- }
-
- return (NULL);
+ struct nbr n;
+ n.peerid = peerid;
+ return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n));
}
struct nbr *
-nbr_find_ip(struct iface *iface, u_int32_t rtr_id)
+nbr_find_ip(u_int32_t addr)
{
- struct nbr *nbr;
-
- LIST_FOREACH(nbr, &iface->nbr_list, entry) {
- if (nbr->addr.s_addr == rtr_id)
- return (nbr);
- }
-
- return (NULL);
+ struct nbr n;
+ n.addr.s_addr = addr;
+ return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n));
}
struct nbr *
-nbr_find_ldpid(struct iface *iface, u_int32_t rtr_id, u_int16_t lspace)
+nbr_find_ldpid(u_int32_t rtr_id, u_int16_t lspace)
{
- struct nbr *nbr;
-
- LIST_FOREACH(nbr, &iface->nbr_list, entry) {
- if (nbr->id.s_addr == rtr_id && nbr->lspace == lspace)
- return (nbr);
- }
-
- return (NULL);
+ struct nbr n;
+ n.id.s_addr = rtr_id;
+ n.lspace = lspace;
+ return (RB_FIND(nbr_id_head, &nbrs_by_id, &n));
}
/* timers */
@@ -628,4 +625,18 @@ nbr_to_ctl(struct nbr *nbr)
nctl.uptime = 0;
return (&nctl);
+}
+
+void
+ldpe_nbr_ctl(struct ctl_conn *c)
+{
+ struct nbr *nbr;
+ struct ctl_nbr *nctl;
+
+ RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
+ nctl = nbr_to_ctl(nbr);
+ imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
+ sizeof(struct ctl_nbr));
+ }
+ imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
}
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/packet.c,v
retrieving revision 1.13
diff -u -p -r1.13 packet.c
--- packet.c 4 Nov 2010 09:52:16 -0000 1.13
+++ packet.c 9 Jan 2011 11:19:58 -0000
@@ -42,7 +42,6 @@
int ldp_hdr_sanity_check(struct ldp_hdr *, u_int16_t,
const struct iface *);
struct iface *find_iface(struct ldpd_conf *, unsigned int, struct in_addr);
-struct iface *session_find_iface(struct ldpd_conf *, struct in_addr);
ssize_t session_get_pdu(struct ibuf_read *, char **);
static int msgcnt = 0;
@@ -60,7 +59,8 @@ gen_ldp_hdr(struct ibuf *buf, struct ifa
ldp_hdr.length = htons(size);
ldp_hdr.lsr_id = ldpe_router_id();
- ldp_hdr.lspace_id = iface->lspace_id;
+ if (iface)
+ ldp_hdr.lspace_id = iface->lspace_id;
return (ibuf_add(buf, &ldp_hdr, LDP_HDR_SIZE));
}
@@ -253,8 +253,6 @@ void
session_accept(int fd, short event, void *bula)
{
struct sockaddr_in src;
- struct ldpd_conf *xconf = bula;
- struct iface *iface;
struct nbr *nbr = NULL;
int newfd;
socklen_t len = sizeof(src);
@@ -271,18 +269,12 @@ session_accept(int fd, short event, void
session_socket_blockmode(newfd, BM_NONBLOCK);
- if ((iface = session_find_iface(xconf, src.sin_addr)) == NULL) {
- log_debug("sess_recv_packet: cannot find a matching interface");
- close(newfd);
- return;
- }
-
- nbr = nbr_find_ip(iface, src.sin_addr.s_addr);
+ nbr = nbr_find_ip(src.sin_addr.s_addr);
if (nbr == NULL) {
struct ibuf *buf;
/* If there is no neighbor matching there is no
Hello adjacency: try to send notification */
- buf = send_notification(S_NO_HELLO, iface, 0, 0);
+ buf = send_notification(S_NO_HELLO, NULL, 0, 0);
write(newfd, buf->buf, buf->wpos);
ibuf_free(buf);
close(newfd);
@@ -460,31 +452,6 @@ session_close(struct nbr *nbr)
evtimer_del(&nbr->keepalive_timeout);
close(nbr->fd);
-}
-
-struct iface *
-session_find_iface(struct ldpd_conf *xconf, struct in_addr src)
-{
- struct iface *iface = NULL;
-
- /* returned interface needs to be active */
- LIST_FOREACH(iface, &xconf->iface_list, entry) {
- switch (iface->type) {
- case IF_TYPE_POINTOPOINT:
- if (iface->dst.s_addr == src.s_addr &&
- !iface->passive)
- return (iface);
- break;
- default:
- if ((iface->addr.s_addr & iface->mask.s_addr) ==
- (src.s_addr & iface->mask.s_addr) &&
- !iface->passive)
- return (iface);
- break;
- }
- }
-
- return (NULL);
}
ssize_t