]>
git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_aspath.c
1 /* AS path management routines.
2 Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_aspath.h"
33 /* Attr. Flags and Attr. Type Code. */
34 #define AS_HEADER_SIZE 2
36 /* Two octet is used for AS value. */
37 #define AS_VALUE_SIZE sizeof (as_t)
39 /* AS segment octet length. */
40 #define ASSEGMENT_LEN(X) ((X)->length * AS_VALUE_SIZE + AS_HEADER_SIZE)
42 /* To fetch and store as segment value. */
50 /* Hash for aspath. This is the top level structure of AS path. */
53 static struct aspath
*
56 struct aspath
*aspath
;
58 aspath
= XMALLOC (MTYPE_AS_PATH
, sizeof (struct aspath
));
59 memset (aspath
, 0, sizeof (struct aspath
));
63 /* Free AS path structure. */
65 aspath_free (struct aspath
*aspath
)
70 XFREE (MTYPE_AS_SEG
, aspath
->data
);
72 XFREE (MTYPE_AS_STR
, aspath
->str
);
73 XFREE (MTYPE_AS_PATH
, aspath
);
76 /* Unintern aspath from AS path bucket. */
78 aspath_unintern (struct aspath
*aspath
)
85 if (aspath
->refcnt
== 0)
87 /* This aspath must exist in aspath hash table. */
88 ret
= hash_release (ashash
, aspath
);
94 /* Return the start or end delimiters for a particular Segment type */
95 #define AS_SEG_START 0
98 aspath_delimiter_char (u_char type
, u_char which
)
106 } aspath_delim_char
[] =
108 { AS_SET
, '{', '}' },
109 { AS_SEQUENCE
, ' ', ' ' },
110 { AS_CONFED_SET
, '[', ']' },
111 { AS_CONFED_SEQUENCE
, '(', ')' },
115 for (i
= 0; aspath_delim_char
[i
].type
!= 0; i
++)
117 if (aspath_delim_char
[i
].type
== type
)
119 if (which
== AS_SEG_START
)
120 return aspath_delim_char
[i
].start
;
121 else if (which
== AS_SEG_END
)
122 return aspath_delim_char
[i
].end
;
128 /* Convert aspath structure to string expression. */
130 aspath_make_str_count (struct aspath
*as
)
136 struct assegment
*assegment
;
137 int str_size
= ASPATH_STR_DEFAULT_LEN
;
145 str_buf
= XMALLOC (MTYPE_AS_STR
, 1);
151 /* Set default value. */
155 /* Set initial pointer. */
157 end
= pnt
+ as
->length
;
159 str_buf
= XMALLOC (MTYPE_AS_STR
, str_size
);
162 assegment
= (struct assegment
*) pnt
;
169 /* For fetch value. */
170 assegment
= (struct assegment
*) pnt
;
172 /* Check AS type validity. */
173 if ((assegment
->type
!= AS_SET
) &&
174 (assegment
->type
!= AS_SEQUENCE
) &&
175 (assegment
->type
!= AS_CONFED_SET
) &&
176 (assegment
->type
!= AS_CONFED_SEQUENCE
))
178 XFREE (MTYPE_AS_STR
, str_buf
);
182 /* Check AS length. */
183 if ((pnt
+ (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
) > end
)
185 XFREE (MTYPE_AS_STR
, str_buf
);
189 /* Buffer length check. */
190 estimate_len
= ((assegment
->length
* 6) + 4);
192 /* String length check. */
193 while (str_pnt
+ estimate_len
>= str_size
)
196 str_buf
= XREALLOC (MTYPE_AS_STR
, str_buf
, str_size
);
199 /* If assegment type is changed, print previous type's end
201 if (type
!= AS_SEQUENCE
)
202 str_buf
[str_pnt
++] = aspath_delimiter_char (type
, AS_SEG_END
);
204 str_buf
[str_pnt
++] = ' ';
206 if (assegment
->type
!= AS_SEQUENCE
)
207 str_buf
[str_pnt
++] = aspath_delimiter_char (assegment
->type
, AS_SEG_START
);
211 /* Increment count - ignoring CONFED SETS/SEQUENCES */
212 if (assegment
->type
!= AS_CONFED_SEQUENCE
213 && assegment
->type
!= AS_CONFED_SET
)
215 if (assegment
->type
== AS_SEQUENCE
)
216 count
+= assegment
->length
;
217 else if (assegment
->type
== AS_SET
)
221 for (i
= 0; i
< assegment
->length
; i
++)
227 if (assegment
->type
== AS_SET
228 || assegment
->type
== AS_CONFED_SET
)
229 str_buf
[str_pnt
++] = ',';
231 str_buf
[str_pnt
++] = ' ';
236 len
= sprintf (str_buf
+ str_pnt
, "%d", ntohs (assegment
->asval
[i
]));
240 type
= assegment
->type
;
241 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
244 if (assegment
->type
!= AS_SEQUENCE
)
245 str_buf
[str_pnt
++] = aspath_delimiter_char (assegment
->type
, AS_SEG_END
);
247 str_buf
[str_pnt
] = '\0';
254 /* Intern allocated AS path. */
256 aspath_intern (struct aspath
*aspath
)
260 /* Assert this AS path structure is not interned. */
261 assert (aspath
->refcnt
== 0);
263 /* Check AS path hash. */
264 find
= hash_get (ashash
, aspath
, hash_alloc_intern
);
267 aspath_free (aspath
);
272 find
->str
= aspath_make_str_count (find
);
277 /* Duplicate aspath structure. Created same aspath structure but
278 reference count and AS path string is cleared. */
280 aspath_dup (struct aspath
*aspath
)
284 new = XMALLOC (MTYPE_AS_PATH
, sizeof (struct aspath
));
285 memset (new, 0, sizeof (struct aspath
));
287 new->length
= aspath
->length
;
291 new->data
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
);
292 memcpy (new->data
, aspath
->data
, aspath
->length
);
297 /* new->str = aspath_make_str_count (aspath); */
303 aspath_hash_alloc (struct aspath
*arg
)
305 struct aspath
*aspath
;
307 /* New aspath strucutre is needed. */
308 aspath
= XMALLOC (MTYPE_AS_PATH
, sizeof (struct aspath
));
309 memset ((void *) aspath
, 0, sizeof (struct aspath
));
310 aspath
->length
= arg
->length
;
312 /* In case of IBGP connection aspath's length can be zero. */
315 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, arg
->length
);
316 memcpy (aspath
->data
, arg
->data
, arg
->length
);
321 /* Make AS path string. */
322 aspath
->str
= aspath_make_str_count (aspath
);
324 /* Malformed AS path value. */
327 aspath_free (aspath
);
334 /* AS path parse function. pnt is a pointer to byte stream and length
335 is length of byte stream. If there is same AS path in the the AS
336 path hash then return it else make new AS path structure. */
338 aspath_parse (caddr_t pnt
, int length
)
343 /* If length is odd it's malformed AS path. */
347 /* Looking up aspath hash entry. */
351 /* If already same aspath exist then return it. */
352 find
= hash_get (ashash
, &as
, aspath_hash_alloc
);
360 #define min(A,B) ((A) < (B) ? (A) : (B))
362 #define ASSEGMENT_SIZE(N) (AS_HEADER_SIZE + ((N) * AS_VALUE_SIZE))
365 aspath_aggregate_segment_copy (struct aspath
*aspath
, struct assegment
*seg
,
368 struct assegment
*newseg
;
372 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, ASSEGMENT_SIZE (i
));
373 newseg
= (struct assegment
*) aspath
->data
;
374 aspath
->length
= ASSEGMENT_SIZE (i
);
378 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
379 aspath
->length
+ ASSEGMENT_SIZE (i
));
380 newseg
= (struct assegment
*) (aspath
->data
+ aspath
->length
);
381 aspath
->length
+= ASSEGMENT_SIZE (i
);
384 newseg
->type
= seg
->type
;
386 memcpy (newseg
->asval
, seg
->asval
, (i
* AS_VALUE_SIZE
));
392 aspath_aggregate_as_set_add (struct aspath
*aspath
, struct assegment
*asset
,
397 /* If this is first AS set member, create new as-set segment. */
402 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, ASSEGMENT_SIZE (1));
403 asset
= (struct assegment
*) aspath
->data
;
404 aspath
->length
= ASSEGMENT_SIZE (1);
408 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
409 aspath
->length
+ ASSEGMENT_SIZE (1));
410 asset
= (struct assegment
*) (aspath
->data
+ aspath
->length
);
411 aspath
->length
+= ASSEGMENT_SIZE (1);
413 asset
->type
= AS_SET
;
415 asset
->asval
[0] = as
;
421 /* Check this AS value already exists or not. */
422 for (i
= 0; i
< asset
->length
; i
++)
423 if (asset
->asval
[i
] == as
)
426 offset
= (caddr_t
) asset
- (caddr_t
) aspath
->data
;
427 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
428 aspath
->length
+ AS_VALUE_SIZE
);
430 asset
= (struct assegment
*) (aspath
->data
+ offset
);
431 aspath
->length
+= AS_VALUE_SIZE
;
432 asset
->asval
[asset
->length
] = as
;
439 /* Modify as1 using as2 for aggregation. */
441 aspath_aggregate (struct aspath
*as1
, struct aspath
*as2
)
452 struct assegment
*seg1
;
453 struct assegment
*seg2
;
454 struct aspath
*aspath
;
455 struct assegment
*asset
;
462 end1
= as1
->data
+ as1
->length
;
464 end2
= as2
->data
+ as2
->length
;
466 seg1
= (struct assegment
*) cp1
;
467 seg2
= (struct assegment
*) cp2
;
469 /* First of all check common leading sequence. */
470 while ((cp1
< end1
) && (cp2
< end2
))
472 /* Check segment type. */
473 if (seg1
->type
!= seg2
->type
)
476 /* Minimum segment length. */
477 minlen
= min (seg1
->length
, seg2
->length
);
479 for (match
= 0; match
< minlen
; match
++)
480 if (seg1
->asval
[match
] != seg2
->asval
[match
])
486 aspath
= aspath_new();
487 aspath
= aspath_aggregate_segment_copy (aspath
, seg1
, match
);
490 if (match
!= minlen
|| match
!= seg1
->length
491 || seg1
->length
!= seg2
->length
)
494 cp1
+= ((seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
495 cp2
+= ((seg2
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
497 seg1
= (struct assegment
*) cp1
;
498 seg2
= (struct assegment
*) cp2
;
502 aspath
= aspath_new();
504 /* Make as-set using rest of all information. */
508 seg1
= (struct assegment
*) cp1
;
510 for (i
= match1
; i
< seg1
->length
; i
++)
511 asset
= aspath_aggregate_as_set_add (aspath
, asset
, seg1
->asval
[i
]);
514 cp1
+= ((seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
520 seg2
= (struct assegment
*) cp2
;
522 for (i
= match2
; i
< seg2
->length
; i
++)
523 asset
= aspath_aggregate_as_set_add (aspath
, asset
, seg2
->asval
[i
]);
526 cp2
+= ((seg2
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
532 /* When a BGP router receives an UPDATE with an MP_REACH_NLRI
533 attribute, check the leftmost AS number in the AS_PATH attribute is
534 or not the peer's AS number. */
536 aspath_firstas_check (struct aspath
*aspath
, as_t asno
)
539 struct assegment
*assegment
;
545 assegment
= (struct assegment
*) pnt
;
548 && assegment
->type
== AS_SEQUENCE
549 && assegment
->asval
[0] == htons (asno
))
555 /* AS path loop check. If aspath contains asno then return 1. */
557 aspath_loop_check (struct aspath
*aspath
, as_t asno
)
561 struct assegment
*assegment
;
568 end
= aspath
->data
+ aspath
->length
;
573 assegment
= (struct assegment
*) pnt
;
575 for (i
= 0; i
< assegment
->length
; i
++)
576 if (assegment
->asval
[i
] == htons (asno
))
579 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
584 /* When all of AS path is private AS return 1. */
586 aspath_private_as_check (struct aspath
*aspath
)
590 struct assegment
*assegment
;
595 if (aspath
->length
== 0)
599 end
= aspath
->data
+ aspath
->length
;
604 assegment
= (struct assegment
*) pnt
;
606 for (i
= 0; i
< assegment
->length
; i
++)
608 if (ntohs (assegment
->asval
[i
]) < BGP_PRIVATE_AS_MIN
609 || ntohs (assegment
->asval
[i
]) > BGP_PRIVATE_AS_MAX
)
612 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
617 /* Merge as1 to as2. as2 should be uninterned aspath. */
619 aspath_merge (struct aspath
*as1
, struct aspath
*as2
)
626 data
= XMALLOC (MTYPE_AS_SEG
, as1
->length
+ as2
->length
);
627 memcpy (data
, as1
->data
, as1
->length
);
628 memcpy (data
+ as1
->length
, as2
->data
, as2
->length
);
630 XFREE (MTYPE_AS_SEG
, as2
->data
);
632 as2
->length
+= as1
->length
;
633 as2
->count
+= as1
->count
;
637 /* Prepend as1 to as2. as2 should be uninterned aspath. */
639 aspath_prepend (struct aspath
*as1
, struct aspath
*as2
)
643 struct assegment
*seg1
= NULL
;
644 struct assegment
*seg2
= NULL
;
649 seg2
= (struct assegment
*) as2
->data
;
651 /* In case of as2 is empty AS. */
654 as2
->length
= as1
->length
;
655 as2
->data
= XMALLOC (MTYPE_AS_SEG
, as1
->length
);
656 as2
->count
= as1
->count
;
657 memcpy (as2
->data
, as1
->data
, as1
->length
);
661 /* assegment points last segment of as1. */
663 end
= as1
->data
+ as1
->length
;
666 seg1
= (struct assegment
*) pnt
;
667 pnt
+= (seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
670 /* In case of as1 is empty AS. */
674 /* Compare last segment type of as1 and first segment type of as2. */
675 if (seg1
->type
!= seg2
->type
)
676 return aspath_merge (as1
, as2
);
678 if (seg1
->type
== AS_SEQUENCE
)
681 struct assegment
*seg
= NULL
;
683 newdata
= XMALLOC (MTYPE_AS_SEG
,
684 as1
->length
+ as2
->length
- AS_HEADER_SIZE
);
685 memcpy (newdata
, as1
->data
, as1
->length
);
686 seg
= (struct assegment
*) (newdata
+ ((caddr_t
)seg1
- as1
->data
));
687 seg
->length
+= seg2
->length
;
688 memcpy (newdata
+ as1
->length
, as2
->data
+ AS_HEADER_SIZE
,
689 as2
->length
- AS_HEADER_SIZE
);
691 XFREE (MTYPE_AS_SEG
, as2
->data
);
693 as2
->length
+= (as1
->length
- AS_HEADER_SIZE
);
694 as2
->count
+= as1
->count
;
700 /* AS_SET merge code is needed at here. */
701 return aspath_merge (as1
, as2
);
707 /* Add specified AS to the leftmost of aspath. */
708 static struct aspath
*
709 aspath_add_one_as (struct aspath
*aspath
, as_t asno
, u_char type
)
711 struct assegment
*assegment
;
713 assegment
= (struct assegment
*) aspath
->data
;
715 /* In case of empty aspath. */
716 if (assegment
== NULL
|| assegment
->length
== 0)
718 aspath
->length
= AS_HEADER_SIZE
+ AS_VALUE_SIZE
;
721 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
, aspath
->length
);
723 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
);
725 assegment
= (struct assegment
*) aspath
->data
;
726 assegment
->type
= type
;
727 assegment
->length
= 1;
728 assegment
->asval
[0] = htons (asno
);
733 if (assegment
->type
== type
)
736 struct assegment
*newsegment
;
738 newdata
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
+ AS_VALUE_SIZE
);
739 newsegment
= (struct assegment
*) newdata
;
741 newsegment
->type
= type
;
742 newsegment
->length
= assegment
->length
+ 1;
743 newsegment
->asval
[0] = htons (asno
);
745 memcpy (newdata
+ AS_HEADER_SIZE
+ AS_VALUE_SIZE
,
746 aspath
->data
+ AS_HEADER_SIZE
,
747 aspath
->length
- AS_HEADER_SIZE
);
749 XFREE (MTYPE_AS_SEG
, aspath
->data
);
751 aspath
->data
= newdata
;
752 aspath
->length
+= AS_VALUE_SIZE
;
755 struct assegment
*newsegment
;
757 newdata
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
+ AS_VALUE_SIZE
+ AS_HEADER_SIZE
);
758 newsegment
= (struct assegment
*) newdata
;
760 newsegment
->type
= type
;
761 newsegment
->length
= 1;
762 newsegment
->asval
[0] = htons (asno
);
764 memcpy (newdata
+ AS_HEADER_SIZE
+ AS_VALUE_SIZE
,
768 XFREE (MTYPE_AS_SEG
, aspath
->data
);
770 aspath
->data
= newdata
;
771 aspath
->length
+= AS_HEADER_SIZE
+ AS_VALUE_SIZE
;
777 /* Add specified AS to the leftmost of aspath. */
779 aspath_add_seq (struct aspath
*aspath
, as_t asno
)
781 return aspath_add_one_as (aspath
, asno
, AS_SEQUENCE
);
784 /* Compare leftmost AS value for MED check. If as1's leftmost AS and
785 as2's leftmost AS is same return 1. */
787 aspath_cmp_left (struct aspath
*aspath1
, struct aspath
*aspath2
)
789 struct assegment
*seg1
;
790 struct assegment
*seg2
;
794 seg1
= (struct assegment
*) aspath1
->data
;
795 seg2
= (struct assegment
*) aspath2
->data
;
797 while (seg1
&& seg1
->length
798 && (seg1
->type
== AS_CONFED_SEQUENCE
|| seg1
->type
== AS_CONFED_SET
))
799 seg1
= (struct assegment
*) ((caddr_t
) seg1
+ ASSEGMENT_LEN (seg1
));
800 while (seg2
&& seg2
->length
801 && (seg2
->type
== AS_CONFED_SEQUENCE
|| seg2
->type
== AS_CONFED_SET
))
802 seg2
= (struct assegment
*) ((caddr_t
) seg2
+ ASSEGMENT_LEN (seg2
));
805 if (seg1
== NULL
|| seg1
->length
== 0 || seg1
->type
!= AS_SEQUENCE
)
807 as1
= seg1
->asval
[0];
809 if (seg2
== NULL
|| seg2
->length
== 0 || seg2
->type
!= AS_SEQUENCE
)
811 as2
= seg2
->asval
[0];
819 /* Compare leftmost AS value for MED check. If as1's leftmost AS and
820 as2's leftmost AS is same return 1. (confederation as-path
823 aspath_cmp_left_confed (struct aspath
*aspath1
, struct aspath
*aspath2
)
825 struct assegment
*seg1
;
826 struct assegment
*seg2
;
831 if (aspath1
->count
|| aspath2
->count
)
834 seg1
= (struct assegment
*) aspath1
->data
;
835 seg2
= (struct assegment
*) aspath2
->data
;
838 if (seg1
== NULL
|| seg1
->length
== 0 || seg1
->type
!= AS_CONFED_SEQUENCE
)
840 as1
= seg1
->asval
[0];
843 if (seg2
== NULL
|| seg2
->length
== 0 || seg2
->type
!= AS_CONFED_SEQUENCE
)
845 as2
= seg2
->asval
[0];
853 /* Delete first sequential AS_CONFED_SEQUENCE from aspath. */
855 aspath_delete_confed_seq (struct aspath
*aspath
)
858 struct assegment
*assegment
;
863 assegment
= (struct assegment
*) aspath
->data
;
867 if (assegment
->type
!= AS_CONFED_SEQUENCE
)
870 seglen
= ASSEGMENT_LEN (assegment
);
872 if (seglen
== aspath
->length
)
874 XFREE (MTYPE_AS_SEG
, aspath
->data
);
880 memcpy (aspath
->data
, aspath
->data
+ seglen
,
881 aspath
->length
- seglen
);
882 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
883 aspath
->length
- seglen
);
884 aspath
->length
-= seglen
;
887 assegment
= (struct assegment
*) aspath
->data
;
892 /* Add new AS number to the leftmost part of the aspath as
893 AS_CONFED_SEQUENCE. */
895 aspath_add_confed_seq (struct aspath
*aspath
, as_t asno
)
897 return aspath_add_one_as (aspath
, asno
, AS_CONFED_SEQUENCE
);
900 /* Add new as value to as path structure. */
902 aspath_as_add (struct aspath
*as
, as_t asno
)
906 struct assegment
*assegment
;
908 /* Increase as->data for new as value. */
909 as
->data
= XREALLOC (MTYPE_AS_SEG
, as
->data
, as
->length
+ 2);
913 end
= as
->data
+ as
->length
;
914 assegment
= (struct assegment
*) pnt
;
916 /* Last segment search procedure. */
917 while (pnt
+ 2 < end
)
919 assegment
= (struct assegment
*) pnt
;
921 /* We add 2 for segment_type and segment_length and segment
922 value assegment->length * 2. */
923 pnt
+= (AS_HEADER_SIZE
+ (assegment
->length
* AS_VALUE_SIZE
));
926 assegment
->asval
[assegment
->length
] = htons (asno
);
930 /* Add new as segment to the as path. */
932 aspath_segment_add (struct aspath
*as
, int type
)
934 struct assegment
*assegment
;
936 if (as
->data
== NULL
)
938 as
->data
= XMALLOC (MTYPE_AS_SEG
, 2);
939 assegment
= (struct assegment
*) as
->data
;
944 as
->data
= XREALLOC (MTYPE_AS_SEG
, as
->data
, as
->length
+ 2);
945 assegment
= (struct assegment
*) (as
->data
+ as
->length
);
949 assegment
->type
= type
;
950 assegment
->length
= 0;
956 return aspath_parse (NULL
, 0);
962 struct aspath
*aspath
;
964 aspath
= aspath_new ();
965 aspath
->str
= aspath_make_str_count (aspath
);
972 return ashash
->count
;
976 Theoretically, one as path can have:
978 One BGP packet size should be less than 4096.
979 One BGP attribute size should be less than 4096 - BGP header size.
980 One BGP aspath size should be less than 4096 - BGP header size -
981 BGP mandantry attribute size.
984 /* AS path string lexical token enum. */
990 as_token_confed_start
,
995 /* Return next token and point for string parse. */
997 aspath_gettoken (char *buf
, enum as_token
*token
, u_short
*asno
)
1002 while (isspace ((int) *p
))
1005 /* Check the end of the string and type specify characters
1013 *token
= as_token_set_start
;
1018 *token
= as_token_set_end
;
1023 *token
= as_token_confed_start
;
1028 *token
= as_token_confed_end
;
1034 /* Check actual AS value. */
1035 if (isdigit ((int) *p
))
1039 *token
= as_token_asval
;
1042 while (isdigit ((int) *p
))
1045 asval
+= (*p
- '0');
1052 /* There is no match then return unknown token. */
1053 *token
= as_token_unknown
;
1058 aspath_str2aspath (char *str
)
1060 enum as_token token
;
1063 struct aspath
*aspath
;
1066 aspath
= aspath_new ();
1068 /* We start default type as AS_SEQUENCE. */
1069 as_type
= AS_SEQUENCE
;
1072 while ((str
= aspath_gettoken (str
, &token
, &asno
)) != NULL
)
1076 case as_token_asval
:
1079 aspath_segment_add (aspath
, as_type
);
1082 aspath_as_add (aspath
, asno
);
1084 case as_token_set_start
:
1086 aspath_segment_add (aspath
, as_type
);
1089 case as_token_set_end
:
1090 as_type
= AS_SEQUENCE
;
1093 case as_token_confed_start
:
1094 as_type
= AS_CONFED_SEQUENCE
;
1095 aspath_segment_add (aspath
, as_type
);
1098 case as_token_confed_end
:
1099 as_type
= AS_SEQUENCE
;
1102 case as_token_unknown
:
1109 aspath
->str
= aspath_make_str_count (aspath
);
1114 /* Make hash value by raw aspath data. */
1116 aspath_key_make (struct aspath
*aspath
)
1118 unsigned int key
= 0;
1120 unsigned short *pnt
;
1122 length
= aspath
->length
/ 2;
1123 pnt
= (unsigned short *) aspath
->data
;
1134 /* If two aspath have same value then return 1 else return 0 */
1136 aspath_cmp (struct aspath
*as1
, struct aspath
*as2
)
1138 if (as1
->length
== as2
->length
1139 && !memcmp (as1
->data
, as2
->data
, as1
->length
))
1145 /* AS path hash initialize. */
1149 ashash
= hash_create_size (32767, aspath_key_make
, aspath_cmp
);
1152 /* return and as path value */
1154 aspath_print (struct aspath
*as
)
1159 /* Printing functions */
1161 aspath_print_vty (struct vty
*vty
, struct aspath
*as
)
1163 vty_out (vty
, "%s", as
->str
);
1167 aspath_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
1171 as
= (struct aspath
*) backet
->data
;
1173 vty_out (vty
, "[%p:%u] (%ld) ", backet
, backet
->key
, as
->refcnt
);
1174 vty_out (vty
, "%s%s", as
->str
, VTY_NEWLINE
);
1177 /* Print all aspath and hash information. This function is used from
1178 `show ip bgp paths' command. */
1180 aspath_print_all_vty (struct vty
*vty
)
1182 hash_iterate (ashash
,
1183 (void (*) (struct hash_backet
*, void *))
1184 aspath_show_all_iterator
,