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

Reply via email to