Re: [mpls-linux-general] RES: Zebra LDP Crash (Discovered source of problem)
Status: Beta
Brought to you by:
jleu
|
From: James R. L. <jl...@ne...> - 2002-11-05 15:36:21
|
From what I've seen below, it looks like I need to do a host to network
conversion before storing anything in the zebra rib. The next release
will contain the fix.
I will also include the change for distributing static routes. In the
future I would like to have an access-list or a route-map control this, but
until I (or someone else) has time to code it up, I think it would be
usefull to be egress for static routes by default.
Thanks for you work!
> But I noticed that from the following static routes only one were propagated:
>
> 1.110.10.0/24
> 2.110.10.0/24
>
> The problem of this is that the prefix_match() function only works correctly
> when
> called with prefixes in network order. And it gets these to prefixes in host
> order
> and regrads the two routes as identical.
>
> Please find attched the interesting part of my debug session. I starts where the
> Router wants to export its routes (a session was just established) and
> ldp_label_mapping_initial_callback() is called the first time.
>
> Here is what I understood from the debug output:
>
> The functions ldp_label_mapping_initial_callback() goes through a list of FECs
> it knows via the Recognize_New_Fec () function from startup.
> It then tries to check whether these FECs have already been sent to the sessions
> partner. For this the function ldp_attr_find_upstream_state() usually returns
> NULL.
> This is also true when it comes to the route 1.110.10.0/24. But when it comes to
> the next route 2.110.10.0/24 it returns non NULL! This is because the function
> finds
> the FEC entry of 1.110.10.0/24 and thinks they are identical.
>
> At the end of the gdb session I executed the backtrace command.
>
> What do you think?
>
>
> ----------------------- Attached gdb session protocol -----------------------
> Breakpoint 5, ldp_label_mapping_initial_callback (timer=0x80b9ea8,
> extra=0x80b7bf8, g=0x80b1020) at ldp_label_mapping.c:444
> 444 if (ldp_policy_export_check(g->user_data, &fec, nh_addr,
> nh_session) ==
> (gdb) p/x fec
> $67 = {_refcnt = 0x0, _global = {lle_next = 0x0, lle_prev = 0x0}, _inlabel = {
> lle_next = 0x0, lle_prev = 0x0}, _outlabel = {lle_next = 0x0,
> lle_prev = 0x0}, _tree = {lle_next = 0x0, lle_prev = 0x0}, _addr = {
> lle_next = 0x0, lle_prev = 0x0}, _fec = {lle_next = 0x0, lle_prev = 0x0},
> _nh = {lle_next = 0x0, lle_prev = 0x0}, fs_root_us = {llh_first = 0x0,
> llh_last = 0x0}, fs_root_ds = {llh_first = 0x0, llh_last = 0x0}, prefix = {
> protocol = 0x2, u = {ipv6 = {0x0, 0xc, 0x2, 0x1, 0x0 <repeats 12 times>},
> ipv4 = 0x1020c00}}, prefix_len = 0x18, type = 0x1}
> (gdb) c
> Continuing.
>
> Breakpoint 5, ldp_label_mapping_initial_callback (timer=0x80b9ea8,
> extra=0x80b7bf8, g=0x80b1020) at ldp_label_mapping.c:444
> 444 if (ldp_policy_export_check(g->user_data, &fec, nh_addr,
> nh_session) ==
> (gdb) p/x fec
> $68 = {_refcnt = 0x0, _global = {lle_next = 0x0, lle_prev = 0x0}, _inlabel = {
> lle_next = 0x0, lle_prev = 0x0}, _outlabel = {lle_next = 0x0,
> lle_prev = 0x0}, _tree = {lle_next = 0x0, lle_prev = 0x0}, _addr = {
> lle_next = 0x0, lle_prev = 0x0}, _fec = {lle_next = 0x0, lle_prev = 0x0},
> _nh = {lle_next = 0x0, lle_prev = 0x0}, fs_root_us = {llh_first = 0x0,
> llh_last = 0x0}, fs_root_ds = {llh_first = 0x0, llh_last = 0x0}, prefix = {
> protocol = 0x2, u = {ipv6 = {0x0, 0xa, 0x6e, 0x1, 0x0 <repeats 12 times>},
> ipv4 = 0x16e0a00}}, prefix_len = 0x18, type = 0x1}
> (gdb) c
> Continuing.
> ldp_label_mapping_with_xc: enter
> ENTER: Prepare_Label_Mapping_Attributes
> EXIT: Prepare_Label_Mapping_Attributes
> ENTER: ldp_label_mapping_send
> OUT: In Label Added
> OUT: LPD Header : protocolVersion = 1
> OUT: pduLength = 33
> OUT: lsrAddress = a0a0964
> OUT: labelSpace = 0
> OUT: LABEL MAPPING MSG ***START***:
> OUT: baseMsg : uBit = 0
> OUT: msgType = 400
> OUT: msgLength = 23
> OUT: msgId = 8
> OUT: fecTlv:
> OUT: Tlv:
> OUT: BaseTlv: uBit = 0
> OUT: fBit = 0
> OUT: type = 100
> OUT: length = 7
> OUT: fecTlv->numberFecElements = 1
> OUT: elem 0 type is 2
> OUT: Fec Element : type = 2, addFam = 1, preLen = 24, address =
> 16e0a00
> OUT:
> OUT: fecTlv.wcElemExists = 0
> OUT: genLblTlv:
> OUT: Tlv:
> OUT: BaseTlv: uBit = 0
> OUT: fBit = 0
> OUT: type = 200
> OUT: length = 4
> OUT: genLbl data: label = 16
> OUT: Label mapping msg does not have atm label Tlv
> OUT: Label mapping msg does not have fr label Tlv
> OUT: Label mapping msg does not have hop count Tlv
> OUT: Label mapping msg does not have path vector Tlv
> OUT: Label mapping msg does not have label messageId Tlv
> OUT: Label mapping msg does not have LSPID Tlv
> OUT: Label mapping msg does not have traffic Tlv
> OUT: LABEL MAPPING MSG ***END***:
> OUT: Label Mapping Sent to 0a0a0d01:0 for 016e0a00/24
> EXIT: ldp_label_mapping_send
> ldp_label_mapping_with_xc: exit
>
> Breakpoint 5, ldp_label_mapping_initial_callback (timer=0x80b9ea8,
> extra=0x80b7bf8, g=0x80b1020) at ldp_label_mapping.c:444
> 444 if (ldp_policy_export_check(g->user_data, &fec, nh_addr,
> nh_session) ==
> (gdb) p/x fec
> $69 = {_refcnt = 0x0, _global = {lle_next = 0x0, lle_prev = 0x0}, _inlabel = {
> lle_next = 0x0, lle_prev = 0x0}, _outlabel = {lle_next = 0x0,
> lle_prev = 0x0}, _tree = {lle_next = 0x0, lle_prev = 0x0}, _addr = {
> lle_next = 0x0, lle_prev = 0x0}, _fec = {lle_next = 0x0, lle_prev = 0x0},
> _nh = {lle_next = 0x0, lle_prev = 0x0}, fs_root_us = {llh_first = 0x0,
> llh_last = 0x0}, fs_root_ds = {llh_first = 0x0, llh_last = 0x0}, prefix = {
> protocol = 0x2, u = {ipv6 = {0x0, 0xa, 0x6e, 0x2, 0x0 <repeats 12 times>},
> ipv4 = 0x26e0a00}}, prefix_len = 0x18, type = 0x1}
> (gdb) n
> 452 if ((us_attr = ldp_attr_find_upstream_state(g, s, &fec,
> (gdb) s
> ldp_attr_find_upstream_state (g=0x80b1020, s=0x80b7bf8, f=0xbffff850,
> state=LDP_LSP_STATE_MAP_SENT) at ldp_attr.c:172
> 172 ldp_attr_list *us_list = ldp_attr_find_upstream_all(g, s, f);
> (gdb) s
> ldp_attr_find_upstream_all (g=0x80b1020, s=0x80b7bf8, f=0xbffff850)
> at ldp_attr.c:574
> 574 LDP_ASSERT(s && f && g);
> (gdb) s
> 576 if ((fnode = _ldp_attr_get_fec2(g, f, LDP_FALSE)) == NULL) {
> (gdb) s
> _ldp_attr_get_fec2 (g=0x80b1020, f=0xbffff850, flag=LDP_FALSE)
> at ldp_attr.c:747
> 747 ldp_fec *fnode = NULL;
> (gdb) n
> 749 if (ldp_tree_get(g->fec_tree, f->prefix.u.ipv4, f->prefix_len,
> (gdb) s
> ldp_tree_get (tree=0x80b0b80, key=40765952, length=24, info=0xbffff7a8)
> at impl_tree.c:85
> 85 p.family = AF_INET;
> (gdb) p/x tree
> $70 = 0x80b0b80
> (gdb) p/x *tree
> Attempt to dereference a generic pointer.
> (gdb) list
> 80 void **info)
> 81 {
> 82 struct route_node *node;
> 83 struct prefix p;
> 84
> 85 p.family = AF_INET;
> 86 p.prefixlen = length;
> 87 p.u.prefix4.s_addr = key;
> 88
> 89 if ((node = route_node_lookup(tree,&p))) {
> (gdb) s
> 86 p.prefixlen = length;
> (gdb)
> 87 p.u.prefix4.s_addr = key;
> (gdb)
> 89 if ((node = route_node_lookup(tree,&p))) {
> (gdb)
> route_node_lookup (table=0x80b0b80, p=0xbffff76c) at table.c:300
> 300 node = table->top;
> (gdb) p/x *table
> $71 = {top = 0x80bb588}
> (gdb) s
> 302 while (node && node->p.prefixlen <= p->prefixlen &&
> (gdb) list -
> 292 #endif /* HAVE_IPV6 */
> 293
> 294 /* Lookup same prefix node. Return NULL when we can't find route. */
> 295 struct route_node *
> 296 route_node_lookup (struct route_table *table, struct prefix *p)
> 297 {
> 298 struct route_node *node;
> 299
> 300 node = table->top;
> 301
> (gdb) list
> 302 while (node && node->p.prefixlen <= p->prefixlen &&
> 303 prefix_match (&node->p, p))
> 304 {
> 305 if (node->p.prefixlen == p->prefixlen && node->info)
> 306 return route_lock_node (node);
> 307
> 308 node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
> 309 }
> 310
> 311 return NULL;
> (gdb) p/x node
> $72 = 0x80bb588
> (gdb) p/x *node
> $73 = {p = {family = 0x2, prefixlen = 0x18, u = {prefix = 0x0, prefix4 = {
> s_addr = 0x16e0a00}, lp = {id = {s_addr = 0x16e0a00}, adv_router = {
> s_addr = 0x0}}, val = {0x0, 0xa, 0x6e, 0x1, 0x0, 0x0, 0x0, 0x0}}},
> table = 0x80b0b80, parent = 0x0, link = {0x0, 0x0}, lock = 0x1,
> info = 0x80bb518, aggregate = 0x0}
> (gdb) s
> 303 prefix_match (&node->p, p))
> (gdb) p/x p
> $74 = 0xbffff76c
> (gdb) p/x *p
> $75 = {family = 0x2, prefixlen = 0x18, u = {prefix = 0x0, prefix4 = {
> s_addr = 0x26e0a00}, lp = {id = {s_addr = 0x26e0a00}, adv_router = {
> s_addr = 0xbffff7fc}}, val = {0x0, 0xa, 0x6e, 0x2, 0xfc, 0xf7, 0xff,
> 0xbf}}}
> (gdb) p/x &node->p
> $76 = 0x80bb588
> (gdb) p/x *&node->p
> $77 = {family = 0x2, prefixlen = 0x18, u = {prefix = 0x0, prefix4 = {
> s_addr = 0x16e0a00}, lp = {id = {s_addr = 0x16e0a00}, adv_router = {
> s_addr = 0x0}}, val = {0x0, 0xa, 0x6e, 0x1, 0x0, 0x0, 0x0, 0x0}}}
> (gdb) s
> prefix_match (n=0x80bb588, p=0xbffff76c) at prefix.c:75
> 75 u_char *np = (u_char *)&n->u.prefix;
> (gdb) list -
> 65 }
> 66
> 67 /* If n includes p prefix then return 1 else return 0. */
> 68 int
> 69 prefix_match (struct prefix *n, struct prefix *p)
> 70 {
> 71 int offset;
> 72 int shift;
> 73
> 74 /* Set both prefix's head pointer. */
> (gdb) list
> 75 u_char *np = (u_char *)&n->u.prefix;
> 76 u_char *pp = (u_char *)&p->u.prefix;
> 77
> 78 /* If n's prefix is longer than p's one return 0. */
> 79 if (n->prefixlen > p->prefixlen)
> 80 return 0;
> 81
> 82 offset = n->prefixlen / PNBBY;
> 83 shift = n->prefixlen % PNBBY;
> 84
> (gdb) n
> 76 u_char *pp = (u_char *)&p->u.prefix;
> (gdb) n
> 79 if (n->prefixlen > p->prefixlen)
> (gdb) p/x *np
> $78 = 0x0
> (gdb) p/x *pp
> $79 = 0x0
> (gdb) n
> 82 offset = n->prefixlen / PNBBY;
> (gdb) n
> 83 shift = n->prefixlen % PNBBY;
> (gdb) n
> 85 if (shift)
> (gdb) p offset
> $80 = 3
> (gdb) p shift
> $81 = 0
> (gdb) n
> 89 while (offset--)
> (gdb) n
> 90 if (np[offset] != pp[offset])
> (gdb) p np[offset]
> $82 = 110 'n'
> (gdb) n
> 92 return 1;
> (gdb) p np[0]
> $83 = 0 '\0'
> (gdb) p np[1]
> $84 = 10 '\n'
> (gdb) p np[2]
> $85 = 110 'n'
> (gdb) p np[3]
> $86 = 1 '\001'
> (gdb) p pp[0]
> $87 = 0 '\0'
> (gdb) p pp[1]
> $88 = 10 '\n'
> (gdb) p pp[2]
> $89 = 110 'n'
> (gdb) p pp[3]
> $90 = 2 '\002'
> (gdb)
> (gdb) bt
> #0 prefix_match (n=0x80bb588, p=0xbffff76c) at prefix.c:92
> #1 0x0807a572 in route_node_lookup (table=0x80b0b80, p=0xbffff76c)
> at table.c:303
> #2 0x0804af86 in ldp_tree_get (tree=0x80b0b80, key=40765952, length=24,
> info=0xbffff7a8) at impl_tree.c:89
> #3 0x08051e2f in _ldp_attr_get_fec2 (g=0x80b1020, f=0xbffff850,
> flag=LDP_FALSE) at ldp_attr.c:749
> #4 0x08051aa1 in ldp_attr_find_upstream_all (g=0x80b1020, s=0x80b7bf8,
> f=0xbffff850) at ldp_attr.c:576
> #5 0x08050f1b in ldp_attr_find_upstream_state (g=0x80b1020, s=0x80b7bf8,
> f=0xbffff850, state=LDP_LSP_STATE_MAP_SENT) at ldp_attr.c:172
> #6 0x0805db11 in ldp_label_mapping_initial_callback (timer=0x80b9ea8,
> extra=0x80b7bf8, g=0x80b1020) at ldp_label_mapping.c:452
> #7 0x0804ad09 in mpls_timer (thread=0xbffff9e4) at impl_timer.c:28
> #8 0x080787a2 in thread_call (thread=0xbffff9e4) at thread.c:647
> #9 0x0804c229 in main (argc=1, argv=0xbffffab4) at mpls_main.c:224
> (gdb)
>
>
> Kind regards,
> Georg Klug
>
>
> > Thanks for the fix to zebra. I will apply it to my tree.
> >
> > After creating the static routes did you check the contents of
> > mplsd:show ip route? If the routes do not show up in mplsd's routing table
> > there is no chance for LDP to operate on them. Also remember that LDP only
> > originates label mappings for directly connected routes (this can be changed
> > simply by changing the code in impl_policy.c:ldp_policy_egress_check()) it
> > should propogate label mappings for anything that matches the routing table.
> >
> > James R. Leu
> >
>
--
James R. Leu
|