I had some trouble first applying the patch, several lines lacked a space at
the beginning of lines, e.g. line 33. Fixed those lines lacking a space
manually and finally applied it. I'm sure there's a smarter way doing this
;-)
With the patch I can now use the loopback address on the router or the
interface address, so it works:
on junos (so it uses the loopback):
deactivate protocols ldp transport-address
# ldpctl show ne
ID State Address Iface Uptime
192.168.100.2 OPERATIONAL/ACTIVE 192.168.91.2 em1 00:00:18
(connected to another openbsd)
192.168.100.3 OPERATIONAL/ACTIVE 192.168.100.3 em2 00:00:07
(connected to junos device)
#
when changing junos back to the interface address:
protocols ldp transport-address
ob1:mwiget$ ldpctl show ne
ID State Address Iface Uptime
192.168.100.2 OPERATIONAL/ACTIVE 192.168.91.2 em1 00:00:22
192.168.100.3 OPERATIONAL/ACTIVE 192.168.93.3 em2 00:00:21
ob1:mwiget$
thanks!
On Jan 9, 2011, at 2:44 PM, Claudio Jeker wrote:
> 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