]> git.proxmox.com Git - mirror_frr.git/blob - lib/nexthop.c
Merge remote-tracking branch 'origin/stable/2.0'
[mirror_frr.git] / lib / nexthop.c
1 /* A generic nexthop structure
2 * Copyright (C) 2013 Cumulus Networks, Inc.
3 *
4 * This file is part of Quagga.
5 *
6 * Quagga 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
9 * later version.
10 *
11 * Quagga 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.
15 *
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
19 */
20 #include <zebra.h>
21
22 #include "prefix.h"
23 #include "table.h"
24 #include "memory.h"
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"
33 #include "mpls.h"
34
35 DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
36 DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
37
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:
55 if (next1->ifindex != next2->ifindex)
56 return 0;
57 break;
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:
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;
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",
84 "IPv4 nexthop",
85 "IPv4 nexthop with ifindex",
86 "IPv6 nexthop",
87 "IPv6 nexthop with ifindex",
88 "Null0 nexthop",
89 };
90
91 return desc[nh_type];
92 }
93
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
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;
149 memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
150 memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
151 if (nh->nh_label)
152 nexthop_add_labels (nexthop, nh->nh_label_type,
153 nh->nh_label->num_labels, &nh->nh_label->label[0]);
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 {
165 nexthop_del_labels (nexthop);
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 }
183
184 /* Update nexthop with label information. */
185 void
186 nexthop_add_labels (struct nexthop *nexthop, enum lsp_types_t type,
187 u_int8_t num_labels, mpls_label_t *label)
188 {
189 struct nexthop_label *nh_label;
190 int i;
191
192 nexthop->nh_label_type = type;
193 nh_label = XCALLOC (MTYPE_NH_LABEL, sizeof (struct nexthop_label) +
194 num_labels * sizeof (mpls_label_t));
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)
206 {
207 XFREE (MTYPE_NH_LABEL, nexthop->nh_label);
208 nexthop->nh_label_type = ZEBRA_LSP_NONE;
209 }
210 }
211
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 }