diff -ur mtr-0.81/ChangeLog mtr-0.81-mpls1/ChangeLog --- mtr-0.81/ChangeLog 2008-08-19 12:55:47.000000000 -0400 +++ mtr-0.81-mpls1/ChangeLog 2011-10-23 22:22:37.000000000 -0400 @@ -1,3 +1,7 @@ +2011-03-28 Mark Kamichoff + * Enable decoding of ICMP extensions for MPLS for curses and report + interfaces. Use the -e flag or press 'e' to enable it. + 2002-03-06 Cougar + If hop doesn't respond, draw its name in red (GTK) or bold (curses) diff -ur mtr-0.81/curses.c mtr-0.81-mpls1/curses.c --- mtr-0.81/curses.c 2008-10-10 14:51:25.000000000 -0400 +++ mtr-0.81-mpls1/curses.c 2011-10-23 22:22:37.000000000 -0400 @@ -111,6 +111,8 @@ return ActionReset; if (tolower(c) == 'd') return ActionDisplay; + if (tolower(c) == 'e') + return ActionMPLS; if (tolower(c) == 'n') return ActionDNS; if (c == '+') @@ -263,6 +265,7 @@ mvprintw(2, 0, "Command:\n" ); printw(" ?|h help\n" ); printw(" d switching display mode\n" ); + printw(" e toggle MPLS information on/off\n" ); printw(" n toggle DNS on/off\n" ); printw(" o str set the columns to display, default str='LRS N BAWV'\n" ); printw(" j toggle latency(LS NABWV)/jitter(DR AGJMXI) stats\n" ); @@ -288,11 +291,12 @@ { int max; int at; + struct mplslen *mpls, *mplss; ip_t *addr, *addrs; int y, x; char *name; - int i, j; + int i, j, k; int hd_len; char buf[1024]; @@ -301,6 +305,7 @@ for(at = net_min () + display_offset; at < max; at++) { printw("%2d. ", at + 1); addr = net_addr(at); + mpls = net_mpls(at); if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) { name = dns_lookup(addr); @@ -339,9 +344,20 @@ buf[hd_len] = 0; printw("%s", buf); + for (k=0; k < mpls->labels && enablempls; k++) { + if((k+1 < mpls->labels) || (mpls->labels == 1)) { + /* if we have more labels */ + printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); + } else { + /* bottom label */ + printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); + } + } + /* Multi path by Min */ for (i=0; i < MAXPATH; i++ ) { addrs = net_addrs(at, i); + mplss = net_mplss(at, i); if ( addrcmp( (void *) addrs, (void *) addr, af ) == 0 ) continue; if ( addrcmp( (void *) addrs, (void *) &unspec_addr, af ) == 0 ) break; @@ -352,6 +368,9 @@ } else { printw("\n %s", strlongip( addrs ) ); } + for (k=0; k < mplss->labels && enablempls; k++) { + printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]); + } attroff(A_BOLD); } diff -ur mtr-0.81/display.h mtr-0.81-mpls1/display.h --- mtr-0.81/display.h 2008-10-10 14:48:24.000000000 -0400 +++ mtr-0.81-mpls1/display.h 2011-10-23 22:22:37.000000000 -0400 @@ -21,7 +21,7 @@ /* Don't put a trailing comma in enumeration lists. Some compilers (notably the one on Irix 5.2) do not like that. -- REW */ enum { ActionNone, ActionQuit, ActionReset, ActionDisplay, - ActionClear, ActionPause, ActionResume, ActionDNS, + ActionClear, ActionPause, ActionResume, ActionMPLS, ActionDNS, ActionScrollDown, ActionScrollUp }; enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit, DisplayRaw, DisplayXML, DisplayCSV, DisplayTXT}; diff -ur mtr-0.81/mtr.8 mtr-0.81-mpls1/mtr.8 --- mtr-0.81/mtr.8 2008-09-18 08:40:09.000000000 -0400 +++ mtr-0.81-mpls1/mtr.8 2011-10-23 22:22:37.000000000 -0400 @@ -8,7 +8,7 @@ .SH SYNOPSIS .B mtr [\c -.B \-hvrctglspniu46\c +.B \-hvrctglspeniu46\c ] [\c .B \-\-help\c @@ -35,6 +35,9 @@ .B \-\-raw\c ] [\c +.B \-\-mpls\c +] +[\c .B \-\-no-dns\c ] [\c @@ -162,6 +165,16 @@ interface (if available). .TP +.B \-e +.TP +.B \-\-mpls +.br +Use this option to tell +.B mtr +to display information from ICMP extensions for MPLS (RFC 4950) +that are encoded in the response packets. + +.TP .B \-n .TP .B \-\-no-dns diff -ur mtr-0.81/mtr.c mtr-0.81-mpls1/mtr.c --- mtr-0.81/mtr.c 2009-05-12 06:05:13.000000000 -0400 +++ mtr-0.81-mpls1/mtr.c 2011-10-23 22:22:37.000000000 -0400 @@ -60,6 +60,7 @@ char *InterfaceAddress = NULL; char LocalHostname[128]; int dns = 1; +int enablempls = 0; int cpacketsize = 64; /* default packet size */ int bitpattern = 0; int tos = 0; @@ -141,6 +142,7 @@ overload psize<0, ->rand(min,max) */ { "bitpattern", 1, 0, 'b' },/* overload b>255, ->rand(0,255) */ { "tos", 1, 0, 'Q' }, /* typeof service (0,255) */ + { "mpls", 0, 0, 'e' }, { "no-dns", 0, 0, 'n' }, { "address", 1, 0, 'a' }, { "first-ttl", 1, 0, 'f' }, /* -f & -m are borrowed from traceroute */ @@ -155,7 +157,7 @@ while(1) { /* added f:m:o: byMin */ opt = getopt_long(argc, argv, - "vhrwxtglpo:i:c:s:b:Q:na:f:m:u46", long_options, NULL); + "vhrwxtglpo:i:c:s:b:Q:ena:f:m:u46", long_options, NULL); if(opt == -1) break; @@ -199,6 +201,9 @@ case 'a': InterfaceAddress = optarg; break; + case 'e': + enablempls = 1; + break; case 'n': dns = 0; break; @@ -377,7 +382,7 @@ if (PrintHelp) { printf("usage: %s [-hvrwctglspniu46] [--help] [--version] [--report]\n" "\t\t[--report-wide] [--report-cycles=COUNT] [--curses] [--gtk]\n" - "\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */ + "\t\t[--raw] [--split] [--mpls] [--no-dns] [--address interface]\n" /* BL */ "\t\t[--psize=bytes/-s bytes]\n" /* ok */ "\t\t[--report-wide|-w] [-u]\n" /* rew */ "\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]); diff -ur mtr-0.81/mtr.h mtr-0.81-mpls1/mtr.h --- mtr-0.81/mtr.h 2008-10-10 14:49:48.000000000 -0400 +++ mtr-0.81-mpls1/mtr.h 2011-10-23 22:22:37.000000000 -0400 @@ -58,6 +58,7 @@ typedef struct in_addr ip_t; #endif +extern int enablempls; extern int dns; extern int use_dns; diff -ur mtr-0.81/net.c mtr-0.81-mpls1/net.c --- mtr-0.81/net.c 2010-07-13 02:10:33.000000000 -0400 +++ mtr-0.81-mpls1/net.c 2011-10-23 22:22:37.000000000 -0400 @@ -122,6 +122,8 @@ int transit; int saved[SAVED_PINGS]; int saved_seq_offset; + struct mplslen mpls; + struct mplslen mplss[MAXPATH]; }; @@ -434,7 +436,7 @@ /* We got a return on something we sent out. Record the address and time. */ -void net_process_ping(int seq, void * addr, struct timeval now) +void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval now) { int index; int totusec; @@ -467,10 +469,12 @@ (void *) &unspec_addr, af ) == 0 ) { /* should be out of if as addr can change */ addrcpy( (void *) &(host[index].addr), addrcopy, af ); + host[index].mpls = mpls; display_rawhost(index, (void *) &(host[index].addr)); /* multi paths by Min */ addrcpy( (void *) &(host[index].addrs[0]), addrcopy, af ); + host[index].mplss[0] = mpls; } else { for( i=0; i 160) + decodempls(num, packet, &mpls, 156); + break; #ifdef ENABLE_IPV6 case AF_INET6: @@ -632,6 +645,10 @@ header = (struct ICMPHeader *) ( packet + sizeof (struct ICMPHeader) + sizeof (struct ip6_hdr) ); + + if(num > 140) + decodempls(num, packet, &mpls, 136); + break; #endif } @@ -656,6 +673,10 @@ udpheader = (struct UDPHeader *)(packet + sizeof (struct IPHeader) + sizeof (struct ICMPHeader) + sizeof (struct IPHeader)); + + if(num > 160) + decodempls(num, packet, &mpls, 156); + break; #ifdef ENABLE_IPV6 case AF_INET6: @@ -665,6 +686,10 @@ udpheader = (struct UDPHeader *) ( packet + sizeof (struct ICMPHeader) + sizeof (struct ip6_hdr) ); + + if(num > 140) + decodempls(num, packet, &mpls, 136); + break; #endif } @@ -674,7 +699,7 @@ } if (sequence) - net_process_ping(sequence, (void *)fromaddress, now); + net_process_ping (sequence, mpls, (void *) fromaddress, now); } @@ -689,6 +714,15 @@ return (ip_t *)&(host[at].addrs[i]); } +void *net_mpls(int at) +{ + return (struct mplslen *)&(host[at].mplss); +} + +void *net_mplss(int at, int i) +{ + return (struct mplslen *)&(host[at].mplss[i]); +} int net_loss(int at) { @@ -1261,3 +1295,42 @@ #endif } } + +/* Decode MPLS */ +void decodempls(int num, char *packet, struct mplslen *mpls, int offset) { + + int i; + unsigned int ext_ver, ext_res, ext_chk, obj_hdr_len; + u_char obj_hdr_class, obj_hdr_type; + + /* loosely derived from the traceroute-nanog.c + * decoding by Jorge Boncompte */ + ext_ver = packet[offset]>>4; + ext_res = (packet[offset]&15)+ packet[offset+1]; + ext_chk = ((unsigned int)packet[offset+2]<<8)+packet[offset+3]; + + /* Check for ICMP extension header */ + if (ext_ver == 2 && ext_res == 0 && ext_chk != 0 && num >= (offset+6)) { + obj_hdr_len = ((int)packet[offset+4]<<8)+packet[offset+5]; + obj_hdr_class = packet[offset+6]; + obj_hdr_type = packet[offset+7]; + + /* make sure we have an MPLS extension */ + if (obj_hdr_len >= 8 && obj_hdr_class == 1 && obj_hdr_type == 1) { + /* how many labels do we have? will be at least 1 */ + mpls->labels = (obj_hdr_len-4)/4; + + /* save all label objects */ + for(i=0; (ilabels) && (i < MAXLABELS) && (num >= (offset+8)+(i*4)); i++) { + + /* piece together the 20 byte label value */ + mpls->label[i] = ((unsigned long) (packet[(offset+8)+(i*4)] << 12 & 0xff000) + + (unsigned int) (packet[(offset+9)+(i*4)] << 4 & 0xff0) + + (packet[(offset+10)+(i*4)] >> 4 & 0xf)); + mpls->exp[i] = (packet[(offset+10)+(i*4)] >> 1) & 0x7; + mpls->s[i] = (packet[(offset+10)+(i*4)] & 0x1); /* should be 1 if only one label */ + mpls->ttl[i] = packet[(offset+11)+(i*4)]; + } + } + } +} diff -ur mtr-0.81/net.h mtr-0.81-mpls1/net.h --- mtr-0.81/net.h 2008-10-10 14:50:04.000000000 -0400 +++ mtr-0.81-mpls1/net.h 2011-10-23 22:22:37.000000000 -0400 @@ -40,6 +40,8 @@ int net_min(void); int net_last(int at); ip_t * net_addr(int at); +void * net_mpls(int at); +void * net_mplss(int, int); int net_loss(int at); int net_drop(int at); int net_last(int at); @@ -86,6 +88,7 @@ #define MAXPACKET 4470 /* largest test packet size */ #define MINPACKET 28 /* 20 bytes IP header and 8 bytes ICMP or UDP */ +#define MAXLABELS 8 /* http://kb.juniper.net/KB2190 (+ 3 just in case) */ /* stuff used by display such as report, curses... --Min */ #define MAXFLD 20 /* max stats fields to display */ @@ -119,3 +122,14 @@ extern char available_options[]; ip_t unspec_addr; + +/* MPLS label object */ +struct mplslen { + unsigned long label[MAXLABELS]; /* label value */ + uint8 exp[MAXLABELS]; /* experimental bits */ + uint8 ttl[MAXLABELS]; /* MPLS TTL */ + char s[MAXLABELS]; /* bottom of stack */ + char labels; /* how many labels did we get? */ +}; + +void decodempls(int, char *, struct mplslen *, int); diff -ur mtr-0.81/report.c mtr-0.81-mpls1/report.c --- mtr-0.81/report.c 2010-05-31 11:53:21.000000000 -0400 +++ mtr-0.81-mpls1/report.c 2011-10-23 22:22:37.000000000 -0400 @@ -52,7 +52,8 @@ void report_close(void) { - int i, j, at, max, z, w; + int i, j, k, at, max, z, w; + struct mplslen *mpls, *mplss; ip_t *addr; ip_t *addr2 = NULL; char name[81]; @@ -102,6 +103,7 @@ at = net_min(); for(; at < max; at++) { addr = net_addr(at); + mpls = net_mpls(at); if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) == 0 ) { sprintf(name, "???"); } else { @@ -138,24 +140,47 @@ * This feature show 'loadbalances' on routes */ - /* z is starting at 1 because addrs[0] is the same that addr */ + /* z is starting at 1 because addrs[0] is the same that addr */ for (z = 1; z < MAXPATH ; z++) { - addr2 = net_addrs(at, z); - int found = 0; - if ((addrcmp ((void *) &unspec_addr, (void *) addr2, af)) == 0) - break; + addr2 = net_addrs(at, z); + mplss = net_mplss(at, z); + int found = 0; + if ((addrcmp ((void *) &unspec_addr, (void *) addr2, af)) == 0) + break; for (w = 0; w < z; w++) /* Thales -- Ok... checking if there are ips repeated on same hop */ - if ((addrcmp ((void *) addr2, (void *) net_addrs (at,w), af)) == 0) { - found = 1; - break; - } - if (!found) { - if (z == 1) + if ((addrcmp ((void *) addr2, (void *) net_addrs (at,w), af)) == 0) { + found = 1; + break; + } + + if (!found) { + + if (mpls->labels && z == 1 && enablempls) { + for (k=0; k < mpls->labels; k++) { + printf(" | |+-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); + } + } + + if (z == 1) { printf (" | `|-- %s\n", strlongip(addr2)); - else + for (k=0; k < mplss->labels && enablempls; k++) { + printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]); + } + } else { printf (" | |-- %s\n", strlongip(addr2)); - } + for (k=0; k < mplss->labels && enablempls; k++) { + printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]); + } + } + } + } + + /* No multipath */ + if(mpls->labels && z == 1 && enablempls) { + for (k=0; k < mpls->labels; k++) { + printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); + } } } } diff -ur mtr-0.81/select.c mtr-0.81-mpls1/select.c --- mtr-0.81/select.c 2011-06-27 12:11:17.000000000 -0400 +++ mtr-0.81-mpls1/select.c 2011-10-23 22:22:37.000000000 -0400 @@ -189,6 +189,10 @@ case ActionResume: paused=0; break; + case ActionMPLS: + enablempls = !enablempls; + display_clear(); + break; case ActionDNS: if (dns) { use_dns = !use_dns; Only in mtr-0.81-mpls1: select.c.orig