]>
Commit | Line | Data |
---|---|---|
fb018d25 DS |
1 | /* A generic nexthop structure |
2 | * Copyright (C) 2013 Cumulus Networks, Inc. | |
3 | * | |
a399694f | 4 | * This file is part of Quagga. |
fb018d25 | 5 | * |
a399694f | 6 | * Quagga is free software; you can redistribute it and/or modify it |
fb018d25 DS |
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 | |
9 | * later version. | |
10 | * | |
a399694f | 11 | * Quagga is distributed in the hope that it will be useful, but |
fb018d25 DS |
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. | |
15 | * | |
896014f4 DL |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
fb018d25 DS |
19 | */ |
20 | #include <zebra.h> | |
21 | ||
22 | #include "prefix.h" | |
23 | #include "table.h" | |
24 | #include "memory.h" | |
fb018d25 DS |
25 | #include "command.h" |
26 | #include "if.h" | |
27 | #include "log.h" | |
28 | #include "sockunion.h" | |
29 | #include "linklist.h" | |
30 | #include "thread.h" | |
31 | #include "prefix.h" | |
32 | #include "nexthop.h" | |
40c7bdb0 | 33 | #include "mpls.h" |
fb018d25 | 34 | |
40c7bdb0 | 35 | DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") |
36 | DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") | |
4a1ab8e4 | 37 | |
fb018d25 DS |
38 | /* check if nexthops are same, non-recursive */ |
39 | int | |
40 | nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2) | |
41 | { | |
42 | if (next1->type != next2->type) | |
43 | return 0; | |
44 | ||
45 | switch (next1->type) | |
46 | { | |
47 | case NEXTHOP_TYPE_IPV4: | |
48 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
49 | if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)) | |
50 | return 0; | |
51 | if (next1->ifindex && (next1->ifindex != next2->ifindex)) | |
52 | return 0; | |
53 | break; | |
54 | case NEXTHOP_TYPE_IFINDEX: | |
fb018d25 DS |
55 | if (next1->ifindex != next2->ifindex) |
56 | return 0; | |
57 | break; | |
fb018d25 DS |
58 | case NEXTHOP_TYPE_IPV6: |
59 | if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) | |
60 | return 0; | |
61 | break; | |
62 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
fb018d25 DS |
63 | if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) |
64 | return 0; | |
65 | if (next1->ifindex != next2->ifindex) | |
66 | return 0; | |
67 | break; | |
fb018d25 DS |
68 | default: |
69 | /* do nothing */ | |
70 | break; | |
71 | } | |
72 | return 1; | |
73 | } | |
74 | ||
75 | /* | |
76 | * nexthop_type_to_str | |
77 | */ | |
78 | const char * | |
79 | nexthop_type_to_str (enum nexthop_types_t nh_type) | |
80 | { | |
81 | static const char *desc[] = { | |
82 | "none", | |
83 | "Directly connected", | |
fb018d25 DS |
84 | "IPv4 nexthop", |
85 | "IPv4 nexthop with ifindex", | |
fb018d25 DS |
86 | "IPv6 nexthop", |
87 | "IPv6 nexthop with ifindex", | |
fb018d25 DS |
88 | "Null0 nexthop", |
89 | }; | |
90 | ||
fb018d25 DS |
91 | return desc[nh_type]; |
92 | } | |
a399694f | 93 | |
a64448ba DS |
94 | /* |
95 | * Check if the labels match for the 2 nexthops specified. | |
96 | */ | |
97 | int | |
98 | nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2) | |
99 | { | |
100 | struct nexthop_label *nhl1, *nhl2; | |
101 | ||
102 | nhl1 = nh1->nh_label; | |
103 | nhl2 = nh2->nh_label; | |
104 | if ((nhl1 && !nhl2) || (!nhl1 && nhl2)) | |
105 | return 0; | |
106 | ||
107 | if (nhl1->num_labels != nhl2->num_labels) | |
108 | return 0; | |
109 | ||
110 | if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels)) | |
111 | return 0; | |
112 | ||
113 | return 1; | |
114 | } | |
115 | ||
a399694f DS |
116 | struct nexthop * |
117 | nexthop_new (void) | |
118 | { | |
119 | return XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); | |
120 | } | |
121 | ||
122 | /* Add nexthop to the end of a nexthop list. */ | |
123 | void | |
124 | nexthop_add (struct nexthop **target, struct nexthop *nexthop) | |
125 | { | |
126 | struct nexthop *last; | |
127 | ||
128 | for (last = *target; last && last->next; last = last->next) | |
129 | ; | |
130 | if (last) | |
131 | last->next = nexthop; | |
132 | else | |
133 | *target = nexthop; | |
134 | nexthop->prev = last; | |
135 | } | |
136 | ||
137 | void | |
138 | copy_nexthops (struct nexthop **tnh, struct nexthop *nh) | |
139 | { | |
140 | struct nexthop *nexthop; | |
141 | struct nexthop *nh1; | |
142 | ||
143 | for (nh1 = nh; nh1; nh1 = nh1->next) | |
144 | { | |
145 | nexthop = nexthop_new(); | |
146 | nexthop->flags = nh->flags; | |
147 | nexthop->type = nh->type; | |
148 | nexthop->ifindex = nh->ifindex; | |
a399694f DS |
149 | memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr)); |
150 | memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr)); | |
c0f4be83 | 151 | if (nh->nh_label) |
ce549947 RW |
152 | nexthop_add_labels (nexthop, nh->nh_label_type, |
153 | nh->nh_label->num_labels, &nh->nh_label->label[0]); | |
a399694f DS |
154 | nexthop_add(tnh, nexthop); |
155 | ||
156 | if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) | |
157 | copy_nexthops(&nexthop->resolved, nh1->resolved); | |
158 | } | |
159 | } | |
160 | ||
161 | /* Free nexthop. */ | |
162 | void | |
163 | nexthop_free (struct nexthop *nexthop) | |
164 | { | |
40c7bdb0 | 165 | nexthop_del_labels (nexthop); |
a399694f DS |
166 | if (nexthop->resolved) |
167 | nexthops_free(nexthop->resolved); | |
168 | XFREE (MTYPE_NEXTHOP, nexthop); | |
169 | } | |
170 | ||
171 | /* Frees a list of nexthops */ | |
172 | void | |
173 | nexthops_free (struct nexthop *nexthop) | |
174 | { | |
175 | struct nexthop *nh, *next; | |
176 | ||
177 | for (nh = nexthop; nh; nh = next) | |
178 | { | |
179 | next = nh->next; | |
180 | nexthop_free (nh); | |
181 | } | |
182 | } | |
80c2442a | 183 | |
40c7bdb0 | 184 | /* Update nexthop with label information. */ |
185 | void | |
ce549947 RW |
186 | nexthop_add_labels (struct nexthop *nexthop, enum lsp_types_t type, |
187 | u_int8_t num_labels, mpls_label_t *label) | |
40c7bdb0 | 188 | { |
189 | struct nexthop_label *nh_label; | |
190 | int i; | |
191 | ||
ce549947 | 192 | nexthop->nh_label_type = type; |
e2a4192a | 193 | nh_label = XCALLOC (MTYPE_NH_LABEL, sizeof (struct nexthop_label) + |
194 | num_labels * sizeof (mpls_label_t)); | |
40c7bdb0 | 195 | nh_label->num_labels = num_labels; |
196 | for (i = 0; i < num_labels; i++) | |
197 | nh_label->label[i] = *(label + i); | |
198 | nexthop->nh_label = nh_label; | |
199 | } | |
200 | ||
201 | /* Free label information of nexthop, if present. */ | |
202 | void | |
203 | nexthop_del_labels (struct nexthop *nexthop) | |
204 | { | |
205 | if (nexthop->nh_label) | |
ce549947 RW |
206 | { |
207 | XFREE (MTYPE_NH_LABEL, nexthop->nh_label); | |
208 | nexthop->nh_label_type = ZEBRA_LSP_NONE; | |
209 | } | |
40c7bdb0 | 210 | } |
211 | ||
80c2442a | 212 | const char * |
213 | nexthop2str (struct nexthop *nexthop, char *str, int size) | |
214 | { | |
215 | switch (nexthop->type) | |
216 | { | |
217 | case NEXTHOP_TYPE_IFINDEX: | |
218 | snprintf (str, size, "if %u", nexthop->ifindex); | |
219 | break; | |
220 | case NEXTHOP_TYPE_IPV4: | |
221 | snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4)); | |
222 | break; | |
223 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
224 | snprintf (str, size, "%s if %u", | |
225 | inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex); | |
226 | break; | |
227 | case NEXTHOP_TYPE_IPV6: | |
228 | snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6)); | |
229 | break; | |
230 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
231 | snprintf (str, size, "%s if %u", | |
232 | inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex); | |
233 | break; | |
234 | case NEXTHOP_TYPE_BLACKHOLE: | |
235 | snprintf (str, size, "blackhole"); | |
236 | break; | |
237 | default: | |
238 | snprintf (str, size, "unknown"); | |
239 | break; | |
240 | } | |
241 | ||
242 | return str; | |
243 | } |