]>
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 | * | |
16 | * You should have received a copy of the GNU General Public License | |
a399694f | 17 | * along with Quagga; see the file COPYING. If not, write to the Free |
fb018d25 DS |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | #include <zebra.h> | |
22 | ||
23 | #include "prefix.h" | |
24 | #include "table.h" | |
25 | #include "memory.h" | |
fb018d25 DS |
26 | #include "command.h" |
27 | #include "if.h" | |
28 | #include "log.h" | |
29 | #include "sockunion.h" | |
30 | #include "linklist.h" | |
31 | #include "thread.h" | |
32 | #include "prefix.h" | |
33 | #include "nexthop.h" | |
40c7bdb0 | 34 | #include "mpls.h" |
fb018d25 | 35 | |
ac4d0be5 | 36 | DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") |
37 | DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") | |
4a1ab8e4 | 38 | |
fb018d25 | 39 | /* check if nexthops are same, non-recursive */ |
ac4d0be5 | 40 | int nexthop_same_no_recurse(struct nexthop *next1, struct nexthop *next2) |
fb018d25 | 41 | { |
ac4d0be5 | 42 | if (next1->type != next2->type) |
43 | return 0; | |
44 | ||
45 | switch (next1->type) { | |
46 | case NEXTHOP_TYPE_IPV4: | |
47 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
48 | if (!IPV4_ADDR_SAME(&next1->gate.ipv4, &next2->gate.ipv4)) | |
49 | return 0; | |
50 | if (next1->ifindex && (next1->ifindex != next2->ifindex)) | |
51 | return 0; | |
52 | break; | |
53 | case NEXTHOP_TYPE_IFINDEX: | |
54 | if (next1->ifindex != next2->ifindex) | |
55 | return 0; | |
56 | break; | |
57 | case NEXTHOP_TYPE_IPV6: | |
58 | if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6)) | |
59 | return 0; | |
60 | break; | |
61 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
62 | if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6)) | |
63 | return 0; | |
64 | if (next1->ifindex != next2->ifindex) | |
65 | return 0; | |
66 | break; | |
67 | default: | |
68 | /* do nothing */ | |
69 | break; | |
70 | } | |
71 | return 1; | |
fb018d25 DS |
72 | } |
73 | ||
74 | /* | |
75 | * nexthop_type_to_str | |
76 | */ | |
ac4d0be5 | 77 | const char *nexthop_type_to_str(enum nexthop_types_t nh_type) |
fb018d25 | 78 | { |
ac4d0be5 | 79 | static const char *desc[] = { |
80 | "none", "Directly connected", | |
81 | "IPv4 nexthop", "IPv4 nexthop with ifindex", | |
82 | "IPv6 nexthop", "IPv6 nexthop with ifindex", | |
83 | "Null0 nexthop", | |
84 | }; | |
85 | ||
86 | return desc[nh_type]; | |
fb018d25 | 87 | } |
a399694f | 88 | |
ac4d0be5 | 89 | struct nexthop *nexthop_new(void) |
a399694f | 90 | { |
ac4d0be5 | 91 | return XCALLOC(MTYPE_NEXTHOP, sizeof(struct nexthop)); |
a399694f DS |
92 | } |
93 | ||
94 | /* Add nexthop to the end of a nexthop list. */ | |
ac4d0be5 | 95 | void nexthop_add(struct nexthop **target, struct nexthop *nexthop) |
a399694f | 96 | { |
ac4d0be5 | 97 | struct nexthop *last; |
98 | ||
99 | for (last = *target; last && last->next; last = last->next) | |
100 | ; | |
101 | if (last) | |
102 | last->next = nexthop; | |
103 | else | |
104 | *target = nexthop; | |
105 | nexthop->prev = last; | |
a399694f DS |
106 | } |
107 | ||
ac4d0be5 | 108 | void copy_nexthops(struct nexthop **tnh, struct nexthop *nh) |
a399694f | 109 | { |
ac4d0be5 | 110 | struct nexthop *nexthop; |
111 | struct nexthop *nh1; | |
112 | ||
113 | for (nh1 = nh; nh1; nh1 = nh1->next) { | |
114 | nexthop = nexthop_new(); | |
115 | nexthop->flags = nh->flags; | |
116 | nexthop->type = nh->type; | |
117 | nexthop->ifindex = nh->ifindex; | |
118 | memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr)); | |
119 | memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr)); | |
120 | if (nh->nh_label) | |
121 | nexthop_add_labels(nexthop, nh->nh_label_type, | |
122 | nh->nh_label->num_labels, | |
123 | &nh->nh_label->label[0]); | |
124 | nexthop_add(tnh, nexthop); | |
125 | ||
126 | if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) | |
127 | copy_nexthops(&nexthop->resolved, nh1->resolved); | |
128 | } | |
a399694f DS |
129 | } |
130 | ||
131 | /* Free nexthop. */ | |
ac4d0be5 | 132 | void nexthop_free(struct nexthop *nexthop) |
a399694f | 133 | { |
ac4d0be5 | 134 | nexthop_del_labels(nexthop); |
135 | if (nexthop->resolved) | |
136 | nexthops_free(nexthop->resolved); | |
137 | XFREE(MTYPE_NEXTHOP, nexthop); | |
a399694f DS |
138 | } |
139 | ||
140 | /* Frees a list of nexthops */ | |
ac4d0be5 | 141 | void nexthops_free(struct nexthop *nexthop) |
a399694f | 142 | { |
ac4d0be5 | 143 | struct nexthop *nh, *next; |
a399694f | 144 | |
ac4d0be5 | 145 | for (nh = nexthop; nh; nh = next) { |
146 | next = nh->next; | |
147 | nexthop_free(nh); | |
148 | } | |
a399694f | 149 | } |
80c2442a | 150 | |
40c7bdb0 | 151 | /* Update nexthop with label information. */ |
ac4d0be5 | 152 | void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t type, |
153 | u_int8_t num_labels, mpls_label_t *label) | |
40c7bdb0 | 154 | { |
ac4d0be5 | 155 | struct nexthop_label *nh_label; |
156 | int i; | |
157 | ||
158 | nexthop->nh_label_type = type; | |
159 | nh_label = XCALLOC(MTYPE_NH_LABEL, | |
160 | sizeof(struct nexthop_label) | |
161 | + num_labels * sizeof(mpls_label_t)); | |
162 | nh_label->num_labels = num_labels; | |
163 | for (i = 0; i < num_labels; i++) | |
164 | nh_label->label[i] = *(label + i); | |
165 | nexthop->nh_label = nh_label; | |
40c7bdb0 | 166 | } |
167 | ||
168 | /* Free label information of nexthop, if present. */ | |
ac4d0be5 | 169 | void nexthop_del_labels(struct nexthop *nexthop) |
40c7bdb0 | 170 | { |
ac4d0be5 | 171 | if (nexthop->nh_label) { |
172 | XFREE(MTYPE_NH_LABEL, nexthop->nh_label); | |
173 | nexthop->nh_label_type = ZEBRA_LSP_NONE; | |
174 | } | |
40c7bdb0 | 175 | } |
176 | ||
ac4d0be5 | 177 | const char *nexthop2str(struct nexthop *nexthop, char *str, int size) |
80c2442a | 178 | { |
ac4d0be5 | 179 | switch (nexthop->type) { |
180 | case NEXTHOP_TYPE_IFINDEX: | |
181 | snprintf(str, size, "if %u", nexthop->ifindex); | |
182 | break; | |
183 | case NEXTHOP_TYPE_IPV4: | |
184 | snprintf(str, size, "%s", inet_ntoa(nexthop->gate.ipv4)); | |
185 | break; | |
186 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
187 | snprintf(str, size, "%s if %u", inet_ntoa(nexthop->gate.ipv4), | |
188 | nexthop->ifindex); | |
189 | break; | |
190 | case NEXTHOP_TYPE_IPV6: | |
191 | snprintf(str, size, "%s", inet6_ntoa(nexthop->gate.ipv6)); | |
192 | break; | |
193 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
194 | snprintf(str, size, "%s if %u", inet6_ntoa(nexthop->gate.ipv6), | |
195 | nexthop->ifindex); | |
196 | break; | |
197 | case NEXTHOP_TYPE_BLACKHOLE: | |
198 | snprintf(str, size, "blackhole"); | |
199 | break; | |
200 | default: | |
201 | snprintf(str, size, "unknown"); | |
202 | break; | |
203 | } | |
204 | ||
205 | return str; | |
80c2442a | 206 | } |