AW: [mpls-linux-general] RES: Zebra LDP Crash (Discovered source of problem)
Status: Beta
Brought to you by:
jleu
|
From: Georg K. <gk...@gi...> - 2002-11-05 15:29:10
|
Hi Jim,
thanks for the hint. With the following patch:
--------------------------------------------------
diff -u impl_policy.c.orig impl_policy.c
--- impl_policy.c.orig Tue Nov 5 10:21:44 2002
+++ impl_policy.c Tue Nov 5 10:22:22 2002
@@ -29,7 +29,7 @@
ldp_prefix2zebra_prefix(route,&p);
if ((rn = route_node_lookup(rib_table_ipv4->table,&p))) {
rib = rn->info;
- if (rib->type == ZEBRA_ROUTE_CONNECT) {
+ if (rib->type == ZEBRA_ROUTE_CONNECT || rib->type == ZEBRA_ROUTE_STATIC) {
// || p.prefixlen == 32) {
result = LDP_TRUE;
}
----------------------------------------------------
the static routes were seen by the LDP, and also they were propagated! Thanks
a lot!
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
>
|