]>
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
;
141 int confed_count
= 0;
146 str_buf
= XMALLOC (MTYPE_AS_STR
, 1);
149 as
->confed_count
= confed_count
;
153 /* Set default value. */
157 /* Set initial pointer. */
159 end
= pnt
+ as
->length
;
161 str_buf
= XMALLOC (MTYPE_AS_STR
, str_size
);
164 assegment
= (struct assegment
*) pnt
;
171 /* For fetch value. */
172 assegment
= (struct assegment
*) pnt
;
174 /* Check AS type validity. */
175 if ((assegment
->type
!= AS_SET
) &&
176 (assegment
->type
!= AS_SEQUENCE
) &&
177 (assegment
->type
!= AS_CONFED_SET
) &&
178 (assegment
->type
!= AS_CONFED_SEQUENCE
))
180 XFREE (MTYPE_AS_STR
, str_buf
);
184 /* Check AS length. */
185 if ((pnt
+ (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
) > end
)
187 XFREE (MTYPE_AS_STR
, str_buf
);
191 /* Buffer length check. */
192 estimate_len
= ((assegment
->length
* 6) + 4);
194 /* String length check. */
195 while (str_pnt
+ estimate_len
>= str_size
)
198 str_buf
= XREALLOC (MTYPE_AS_STR
, str_buf
, str_size
);
201 /* If assegment type is changed, print previous type's end
203 if (type
!= AS_SEQUENCE
)
204 str_buf
[str_pnt
++] = aspath_delimiter_char (type
, AS_SEG_END
);
206 str_buf
[str_pnt
++] = ' ';
208 if (assegment
->type
!= AS_SEQUENCE
)
209 str_buf
[str_pnt
++] = aspath_delimiter_char (assegment
->type
, AS_SEG_START
);
213 /* Increment counts */
214 switch (assegment
->type
)
217 count
+= assegment
->length
;
222 case AS_CONFED_SEQUENCE
:
223 confed_count
+= assegment
->length
;
230 for (i
= 0; i
< assegment
->length
; i
++)
236 if (assegment
->type
== AS_SET
237 || assegment
->type
== AS_CONFED_SET
)
238 str_buf
[str_pnt
++] = ',';
240 str_buf
[str_pnt
++] = ' ';
245 len
= sprintf (str_buf
+ str_pnt
, "%d", ntohs (assegment
->asval
[i
]));
249 type
= assegment
->type
;
250 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
253 if (assegment
->type
!= AS_SEQUENCE
)
254 str_buf
[str_pnt
++] = aspath_delimiter_char (assegment
->type
, AS_SEG_END
);
256 str_buf
[str_pnt
] = '\0';
259 as
->confed_count
= confed_count
;
264 /* Intern allocated AS path. */
266 aspath_intern (struct aspath
*aspath
)
270 /* Assert this AS path structure is not interned. */
271 assert (aspath
->refcnt
== 0);
273 /* Check AS path hash. */
274 find
= hash_get (ashash
, aspath
, hash_alloc_intern
);
277 aspath_free (aspath
);
282 find
->str
= aspath_make_str_count (find
);
287 /* Duplicate aspath structure. Created same aspath structure but
288 reference count and AS path string is cleared. */
290 aspath_dup (struct aspath
*aspath
)
294 new = XMALLOC (MTYPE_AS_PATH
, sizeof (struct aspath
));
295 memset (new, 0, sizeof (struct aspath
));
297 new->length
= aspath
->length
;
301 new->data
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
);
302 memcpy (new->data
, aspath
->data
, aspath
->length
);
307 /* new->str = aspath_make_str_count (aspath); */
313 aspath_hash_alloc (struct aspath
*arg
)
315 struct aspath
*aspath
;
317 /* New aspath strucutre is needed. */
318 aspath
= XMALLOC (MTYPE_AS_PATH
, sizeof (struct aspath
));
319 memset ((void *) aspath
, 0, sizeof (struct aspath
));
320 aspath
->length
= arg
->length
;
322 /* In case of IBGP connection aspath's length can be zero. */
325 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, arg
->length
);
326 memcpy (aspath
->data
, arg
->data
, arg
->length
);
331 /* Make AS path string. */
332 aspath
->str
= aspath_make_str_count (aspath
);
334 /* Malformed AS path value. */
337 aspath_free (aspath
);
344 /* AS path parse function. pnt is a pointer to byte stream and length
345 is length of byte stream. If there is same AS path in the the AS
346 path hash then return it else make new AS path structure. */
348 aspath_parse (caddr_t pnt
, int length
)
353 /* If length is odd it's malformed AS path. */
357 /* Looking up aspath hash entry. */
361 /* If already same aspath exist then return it. */
362 find
= hash_get (ashash
, &as
, aspath_hash_alloc
);
370 #define min(A,B) ((A) < (B) ? (A) : (B))
372 #define ASSEGMENT_SIZE(N) (AS_HEADER_SIZE + ((N) * AS_VALUE_SIZE))
375 aspath_aggregate_segment_copy (struct aspath
*aspath
, struct assegment
*seg
,
378 struct assegment
*newseg
;
382 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, ASSEGMENT_SIZE (i
));
383 newseg
= (struct assegment
*) aspath
->data
;
384 aspath
->length
= ASSEGMENT_SIZE (i
);
388 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
389 aspath
->length
+ ASSEGMENT_SIZE (i
));
390 newseg
= (struct assegment
*) (aspath
->data
+ aspath
->length
);
391 aspath
->length
+= ASSEGMENT_SIZE (i
);
394 newseg
->type
= seg
->type
;
396 memcpy (newseg
->asval
, seg
->asval
, (i
* AS_VALUE_SIZE
));
402 aspath_aggregate_as_set_add (struct aspath
*aspath
, struct assegment
*asset
,
407 /* If this is first AS set member, create new as-set segment. */
412 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, ASSEGMENT_SIZE (1));
413 asset
= (struct assegment
*) aspath
->data
;
414 aspath
->length
= ASSEGMENT_SIZE (1);
418 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
419 aspath
->length
+ ASSEGMENT_SIZE (1));
420 asset
= (struct assegment
*) (aspath
->data
+ aspath
->length
);
421 aspath
->length
+= ASSEGMENT_SIZE (1);
423 asset
->type
= AS_SET
;
425 asset
->asval
[0] = as
;
431 /* Check this AS value already exists or not. */
432 for (i
= 0; i
< asset
->length
; i
++)
433 if (asset
->asval
[i
] == as
)
436 offset
= (caddr_t
) asset
- (caddr_t
) aspath
->data
;
437 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
438 aspath
->length
+ AS_VALUE_SIZE
);
440 asset
= (struct assegment
*) (aspath
->data
+ offset
);
441 aspath
->length
+= AS_VALUE_SIZE
;
442 asset
->asval
[asset
->length
] = as
;
449 /* Modify as1 using as2 for aggregation. */
451 aspath_aggregate (struct aspath
*as1
, struct aspath
*as2
)
462 struct assegment
*seg1
;
463 struct assegment
*seg2
;
464 struct aspath
*aspath
;
465 struct assegment
*asset
;
472 end1
= as1
->data
+ as1
->length
;
474 end2
= as2
->data
+ as2
->length
;
476 seg1
= (struct assegment
*) cp1
;
477 seg2
= (struct assegment
*) cp2
;
479 /* First of all check common leading sequence. */
480 while ((cp1
< end1
) && (cp2
< end2
))
482 /* Check segment type. */
483 if (seg1
->type
!= seg2
->type
)
486 /* Minimum segment length. */
487 minlen
= min (seg1
->length
, seg2
->length
);
489 for (match
= 0; match
< minlen
; match
++)
490 if (seg1
->asval
[match
] != seg2
->asval
[match
])
496 aspath
= aspath_new();
497 aspath
= aspath_aggregate_segment_copy (aspath
, seg1
, match
);
500 if (match
!= minlen
|| match
!= seg1
->length
501 || seg1
->length
!= seg2
->length
)
504 cp1
+= ((seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
505 cp2
+= ((seg2
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
507 seg1
= (struct assegment
*) cp1
;
508 seg2
= (struct assegment
*) cp2
;
512 aspath
= aspath_new();
514 /* Make as-set using rest of all information. */
518 seg1
= (struct assegment
*) cp1
;
520 for (i
= match1
; i
< seg1
->length
; i
++)
521 asset
= aspath_aggregate_as_set_add (aspath
, asset
, seg1
->asval
[i
]);
524 cp1
+= ((seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
530 seg2
= (struct assegment
*) cp2
;
532 for (i
= match2
; i
< seg2
->length
; i
++)
533 asset
= aspath_aggregate_as_set_add (aspath
, asset
, seg2
->asval
[i
]);
536 cp2
+= ((seg2
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
);
542 /* When a BGP router receives an UPDATE with an MP_REACH_NLRI
543 attribute, check the leftmost AS number in the AS_PATH attribute is
544 or not the peer's AS number. */
546 aspath_firstas_check (struct aspath
*aspath
, as_t asno
)
549 struct assegment
*assegment
;
555 assegment
= (struct assegment
*) pnt
;
558 && assegment
->type
== AS_SEQUENCE
559 && assegment
->asval
[0] == htons (asno
))
565 /* AS path loop check. If aspath contains asno then return 1. */
567 aspath_loop_check (struct aspath
*aspath
, as_t asno
)
571 struct assegment
*assegment
;
578 end
= aspath
->data
+ aspath
->length
;
583 assegment
= (struct assegment
*) pnt
;
585 for (i
= 0; i
< assegment
->length
; i
++)
586 if (assegment
->asval
[i
] == htons (asno
))
589 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
594 /* When all of AS path is private AS return 1. */
596 aspath_private_as_check (struct aspath
*aspath
)
600 struct assegment
*assegment
;
605 if (aspath
->length
== 0)
609 end
= aspath
->data
+ aspath
->length
;
614 assegment
= (struct assegment
*) pnt
;
616 for (i
= 0; i
< assegment
->length
; i
++)
618 if (ntohs (assegment
->asval
[i
]) < BGP_PRIVATE_AS_MIN
619 || ntohs (assegment
->asval
[i
]) > BGP_PRIVATE_AS_MAX
)
622 pnt
+= (assegment
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
627 /* Merge as1 to as2. as2 should be uninterned aspath. */
629 aspath_merge (struct aspath
*as1
, struct aspath
*as2
)
636 data
= XMALLOC (MTYPE_AS_SEG
, as1
->length
+ as2
->length
);
637 memcpy (data
, as1
->data
, as1
->length
);
638 memcpy (data
+ as1
->length
, as2
->data
, as2
->length
);
640 XFREE (MTYPE_AS_SEG
, as2
->data
);
642 as2
->length
+= as1
->length
;
643 as2
->count
+= as1
->count
;
647 /* Prepend as1 to as2. as2 should be uninterned aspath. */
649 aspath_prepend (struct aspath
*as1
, struct aspath
*as2
)
653 struct assegment
*seg1
= NULL
;
654 struct assegment
*seg2
= NULL
;
659 seg2
= (struct assegment
*) as2
->data
;
661 /* In case of as2 is empty AS. */
664 as2
->length
= as1
->length
;
665 as2
->data
= XMALLOC (MTYPE_AS_SEG
, as1
->length
);
666 as2
->count
= as1
->count
;
667 memcpy (as2
->data
, as1
->data
, as1
->length
);
671 /* assegment points last segment of as1. */
673 end
= as1
->data
+ as1
->length
;
676 seg1
= (struct assegment
*) pnt
;
677 pnt
+= (seg1
->length
* AS_VALUE_SIZE
) + AS_HEADER_SIZE
;
680 /* In case of as1 is empty AS. */
684 /* Compare last segment type of as1 and first segment type of as2. */
685 if (seg1
->type
!= seg2
->type
)
686 return aspath_merge (as1
, as2
);
688 if (seg1
->type
== AS_SEQUENCE
)
691 struct assegment
*seg
= NULL
;
693 newdata
= XMALLOC (MTYPE_AS_SEG
,
694 as1
->length
+ as2
->length
- AS_HEADER_SIZE
);
695 memcpy (newdata
, as1
->data
, as1
->length
);
696 seg
= (struct assegment
*) (newdata
+ ((caddr_t
)seg1
- as1
->data
));
697 seg
->length
+= seg2
->length
;
698 memcpy (newdata
+ as1
->length
, as2
->data
+ AS_HEADER_SIZE
,
699 as2
->length
- AS_HEADER_SIZE
);
701 XFREE (MTYPE_AS_SEG
, as2
->data
);
703 as2
->length
+= (as1
->length
- AS_HEADER_SIZE
);
704 as2
->count
+= as1
->count
;
710 /* AS_SET merge code is needed at here. */
711 return aspath_merge (as1
, as2
);
717 /* Add specified AS to the leftmost of aspath. */
718 static struct aspath
*
719 aspath_add_one_as (struct aspath
*aspath
, as_t asno
, u_char type
)
721 struct assegment
*assegment
;
723 assegment
= (struct assegment
*) aspath
->data
;
725 /* In case of empty aspath. */
726 if (assegment
== NULL
|| assegment
->length
== 0)
728 aspath
->length
= AS_HEADER_SIZE
+ AS_VALUE_SIZE
;
731 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
, aspath
->length
);
733 aspath
->data
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
);
735 assegment
= (struct assegment
*) aspath
->data
;
736 assegment
->type
= type
;
737 assegment
->length
= 1;
738 assegment
->asval
[0] = htons (asno
);
743 if (assegment
->type
== type
)
746 struct assegment
*newsegment
;
748 newdata
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
+ AS_VALUE_SIZE
);
749 newsegment
= (struct assegment
*) newdata
;
751 newsegment
->type
= type
;
752 newsegment
->length
= assegment
->length
+ 1;
753 newsegment
->asval
[0] = htons (asno
);
755 memcpy (newdata
+ AS_HEADER_SIZE
+ AS_VALUE_SIZE
,
756 aspath
->data
+ AS_HEADER_SIZE
,
757 aspath
->length
- AS_HEADER_SIZE
);
759 XFREE (MTYPE_AS_SEG
, aspath
->data
);
761 aspath
->data
= newdata
;
762 aspath
->length
+= AS_VALUE_SIZE
;
765 struct assegment
*newsegment
;
767 newdata
= XMALLOC (MTYPE_AS_SEG
, aspath
->length
+ AS_VALUE_SIZE
+ AS_HEADER_SIZE
);
768 newsegment
= (struct assegment
*) newdata
;
770 newsegment
->type
= type
;
771 newsegment
->length
= 1;
772 newsegment
->asval
[0] = htons (asno
);
774 memcpy (newdata
+ AS_HEADER_SIZE
+ AS_VALUE_SIZE
,
778 XFREE (MTYPE_AS_SEG
, aspath
->data
);
780 aspath
->data
= newdata
;
781 aspath
->length
+= AS_HEADER_SIZE
+ AS_VALUE_SIZE
;
787 /* Add specified AS to the leftmost of aspath. */
789 aspath_add_seq (struct aspath
*aspath
, as_t asno
)
791 return aspath_add_one_as (aspath
, asno
, AS_SEQUENCE
);
794 /* Compare leftmost AS value for MED check. If as1's leftmost AS and
795 as2's leftmost AS is same return 1. */
797 aspath_cmp_left (struct aspath
*aspath1
, struct aspath
*aspath2
)
799 struct assegment
*seg1
;
800 struct assegment
*seg2
;
804 seg1
= (struct assegment
*) aspath1
->data
;
805 seg2
= (struct assegment
*) aspath2
->data
;
807 while (seg1
&& seg1
->length
808 && (seg1
->type
== AS_CONFED_SEQUENCE
|| seg1
->type
== AS_CONFED_SET
))
809 seg1
= (struct assegment
*) ((caddr_t
) seg1
+ ASSEGMENT_LEN (seg1
));
810 while (seg2
&& seg2
->length
811 && (seg2
->type
== AS_CONFED_SEQUENCE
|| seg2
->type
== AS_CONFED_SET
))
812 seg2
= (struct assegment
*) ((caddr_t
) seg2
+ ASSEGMENT_LEN (seg2
));
815 if (seg1
== NULL
|| seg1
->length
== 0 || seg1
->type
!= AS_SEQUENCE
)
817 as1
= seg1
->asval
[0];
819 if (seg2
== NULL
|| seg2
->length
== 0 || seg2
->type
!= AS_SEQUENCE
)
821 as2
= seg2
->asval
[0];
829 /* Compare leftmost AS value for MED check. If as1's leftmost AS and
830 as2's leftmost AS is same return 1. (confederation as-path
833 aspath_cmp_left_confed (struct aspath
*aspath1
, struct aspath
*aspath2
)
835 struct assegment
*seg1
;
836 struct assegment
*seg2
;
841 if (aspath1
->count
|| aspath2
->count
)
844 seg1
= (struct assegment
*) aspath1
->data
;
845 seg2
= (struct assegment
*) aspath2
->data
;
848 if (seg1
== NULL
|| seg1
->length
== 0 || seg1
->type
!= AS_CONFED_SEQUENCE
)
850 as1
= seg1
->asval
[0];
853 if (seg2
== NULL
|| seg2
->length
== 0 || seg2
->type
!= AS_CONFED_SEQUENCE
)
855 as2
= seg2
->asval
[0];
863 /* Delete first sequential AS_CONFED_SEQUENCE from aspath. */
865 aspath_delete_confed_seq (struct aspath
*aspath
)
868 struct assegment
*assegment
;
873 assegment
= (struct assegment
*) aspath
->data
;
877 if (assegment
->type
!= AS_CONFED_SEQUENCE
)
880 seglen
= ASSEGMENT_LEN (assegment
);
882 if (seglen
== aspath
->length
)
884 XFREE (MTYPE_AS_SEG
, aspath
->data
);
890 memcpy (aspath
->data
, aspath
->data
+ seglen
,
891 aspath
->length
- seglen
);
892 aspath
->data
= XREALLOC (MTYPE_AS_SEG
, aspath
->data
,
893 aspath
->length
- seglen
);
894 aspath
->length
-= seglen
;
897 assegment
= (struct assegment
*) aspath
->data
;
902 /* Add new AS number to the leftmost part of the aspath as
903 AS_CONFED_SEQUENCE. */
905 aspath_add_confed_seq (struct aspath
*aspath
, as_t asno
)
907 return aspath_add_one_as (aspath
, asno
, AS_CONFED_SEQUENCE
);
910 /* Add new as value to as path structure. */
912 aspath_as_add (struct aspath
*as
, as_t asno
)
916 struct assegment
*assegment
;
918 /* Increase as->data for new as value. */
919 as
->data
= XREALLOC (MTYPE_AS_SEG
, as
->data
, as
->length
+ 2);
923 end
= as
->data
+ as
->length
;
924 assegment
= (struct assegment
*) pnt
;
926 /* Last segment search procedure. */
927 while (pnt
+ 2 < end
)
929 assegment
= (struct assegment
*) pnt
;
931 /* We add 2 for segment_type and segment_length and segment
932 value assegment->length * 2. */
933 pnt
+= (AS_HEADER_SIZE
+ (assegment
->length
* AS_VALUE_SIZE
));
936 assegment
->asval
[assegment
->length
] = htons (asno
);
940 /* Add new as segment to the as path. */
942 aspath_segment_add (struct aspath
*as
, int type
)
944 struct assegment
*assegment
;
946 if (as
->data
== NULL
)
948 as
->data
= XMALLOC (MTYPE_AS_SEG
, 2);
949 assegment
= (struct assegment
*) as
->data
;
954 as
->data
= XREALLOC (MTYPE_AS_SEG
, as
->data
, as
->length
+ 2);
955 assegment
= (struct assegment
*) (as
->data
+ as
->length
);
959 assegment
->type
= type
;
960 assegment
->length
= 0;
966 return aspath_parse (NULL
, 0);
972 struct aspath
*aspath
;
974 aspath
= aspath_new ();
975 aspath
->str
= aspath_make_str_count (aspath
);
982 return ashash
->count
;
986 Theoretically, one as path can have:
988 One BGP packet size should be less than 4096.
989 One BGP attribute size should be less than 4096 - BGP header size.
990 One BGP aspath size should be less than 4096 - BGP header size -
991 BGP mandantry attribute size.
994 /* AS path string lexical token enum. */
1000 as_token_confed_start
,
1001 as_token_confed_end
,
1005 /* Return next token and point for string parse. */
1007 aspath_gettoken (const char *buf
, enum as_token
*token
, u_short
*asno
)
1009 const char *p
= buf
;
1012 while (isspace ((int) *p
))
1015 /* Check the end of the string and type specify characters
1023 *token
= as_token_set_start
;
1028 *token
= as_token_set_end
;
1033 *token
= as_token_confed_start
;
1038 *token
= as_token_confed_end
;
1044 /* Check actual AS value. */
1045 if (isdigit ((int) *p
))
1049 *token
= as_token_asval
;
1052 while (isdigit ((int) *p
))
1055 asval
+= (*p
- '0');
1062 /* There is no match then return unknown token. */
1063 *token
= as_token_unknown
;
1068 aspath_str2aspath (const char *str
)
1070 enum as_token token
;
1073 struct aspath
*aspath
;
1076 aspath
= aspath_new ();
1078 /* We start default type as AS_SEQUENCE. */
1079 as_type
= AS_SEQUENCE
;
1082 while ((str
= aspath_gettoken (str
, &token
, &asno
)) != NULL
)
1086 case as_token_asval
:
1089 aspath_segment_add (aspath
, as_type
);
1092 aspath_as_add (aspath
, asno
);
1094 case as_token_set_start
:
1096 aspath_segment_add (aspath
, as_type
);
1099 case as_token_set_end
:
1100 as_type
= AS_SEQUENCE
;
1103 case as_token_confed_start
:
1104 as_type
= AS_CONFED_SEQUENCE
;
1105 aspath_segment_add (aspath
, as_type
);
1108 case as_token_confed_end
:
1109 as_type
= AS_SEQUENCE
;
1112 case as_token_unknown
:
1119 aspath
->str
= aspath_make_str_count (aspath
);
1124 /* Make hash value by raw aspath data. */
1126 aspath_key_make (struct aspath
*aspath
)
1128 unsigned int key
= 0;
1130 unsigned short *pnt
;
1132 length
= aspath
->length
/ 2;
1133 pnt
= (unsigned short *) aspath
->data
;
1144 /* If two aspath have same value then return 1 else return 0 */
1146 aspath_cmp (struct aspath
*as1
, struct aspath
*as2
)
1148 if (as1
->length
== as2
->length
1149 && !memcmp (as1
->data
, as2
->data
, as1
->length
))
1155 /* AS path hash initialize. */
1159 ashash
= hash_create_size (32767, aspath_key_make
, aspath_cmp
);
1162 /* return and as path value */
1164 aspath_print (struct aspath
*as
)
1169 /* Printing functions */
1171 aspath_print_vty (struct vty
*vty
, struct aspath
*as
)
1173 vty_out (vty
, "%s", as
->str
);
1177 aspath_show_all_iterator (struct hash_backet
*backet
, struct vty
*vty
)
1181 as
= (struct aspath
*) backet
->data
;
1183 vty_out (vty
, "[%p:%u] (%ld) ", backet
, backet
->key
, as
->refcnt
);
1184 vty_out (vty
, "%s%s", as
->str
, VTY_NEWLINE
);
1187 /* Print all aspath and hash information. This function is used from
1188 `show ip bgp paths' command. */
1190 aspath_print_all_vty (struct vty
*vty
)
1192 hash_iterate (ashash
,
1193 (void (*) (struct hash_backet
*, void *))
1194 aspath_show_all_iterator
,