]> git.proxmox.com Git - mirror_frr.git/blame - lib/nexthop.c
Merge pull request #531 from qlyoung/fix-stack-ref
[mirror_frr.git] / lib / nexthop.c
CommitLineData
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
40c7bdb0 36DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
37DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
4a1ab8e4 38
fb018d25
DS
39/* check if nexthops are same, non-recursive */
40int
41nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2)
42{
43 if (next1->type != next2->type)
44 return 0;
45
46 switch (next1->type)
47 {
48 case NEXTHOP_TYPE_IPV4:
49 case NEXTHOP_TYPE_IPV4_IFINDEX:
50 if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
51 return 0;
52 if (next1->ifindex && (next1->ifindex != next2->ifindex))
53 return 0;
54 break;
55 case NEXTHOP_TYPE_IFINDEX:
fb018d25
DS
56 if (next1->ifindex != next2->ifindex)
57 return 0;
58 break;
fb018d25
DS
59 case NEXTHOP_TYPE_IPV6:
60 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
61 return 0;
62 break;
63 case NEXTHOP_TYPE_IPV6_IFINDEX:
fb018d25
DS
64 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
65 return 0;
66 if (next1->ifindex != next2->ifindex)
67 return 0;
68 break;
fb018d25
DS
69 default:
70 /* do nothing */
71 break;
72 }
73 return 1;
74}
75
76/*
77 * nexthop_type_to_str
78 */
79const char *
80nexthop_type_to_str (enum nexthop_types_t nh_type)
81{
82 static const char *desc[] = {
83 "none",
84 "Directly connected",
fb018d25
DS
85 "IPv4 nexthop",
86 "IPv4 nexthop with ifindex",
fb018d25
DS
87 "IPv6 nexthop",
88 "IPv6 nexthop with ifindex",
fb018d25
DS
89 "Null0 nexthop",
90 };
91
fb018d25
DS
92 return desc[nh_type];
93}
a399694f 94
a64448ba
DS
95/*
96 * Check if the labels match for the 2 nexthops specified.
97 */
98int
99nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2)
100{
101 struct nexthop_label *nhl1, *nhl2;
102
103 nhl1 = nh1->nh_label;
104 nhl2 = nh2->nh_label;
105 if ((nhl1 && !nhl2) || (!nhl1 && nhl2))
106 return 0;
107
108 if (nhl1->num_labels != nhl2->num_labels)
109 return 0;
110
111 if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels))
112 return 0;
113
114 return 1;
115}
116
a399694f
DS
117struct nexthop *
118nexthop_new (void)
119{
120 return XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
121}
122
123/* Add nexthop to the end of a nexthop list. */
124void
125nexthop_add (struct nexthop **target, struct nexthop *nexthop)
126{
127 struct nexthop *last;
128
129 for (last = *target; last && last->next; last = last->next)
130 ;
131 if (last)
132 last->next = nexthop;
133 else
134 *target = nexthop;
135 nexthop->prev = last;
136}
137
138void
139copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
140{
141 struct nexthop *nexthop;
142 struct nexthop *nh1;
143
144 for (nh1 = nh; nh1; nh1 = nh1->next)
145 {
146 nexthop = nexthop_new();
147 nexthop->flags = nh->flags;
148 nexthop->type = nh->type;
149 nexthop->ifindex = nh->ifindex;
a399694f
DS
150 memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
151 memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
c0f4be83 152 if (nh->nh_label)
ce549947
RW
153 nexthop_add_labels (nexthop, nh->nh_label_type,
154 nh->nh_label->num_labels, &nh->nh_label->label[0]);
a399694f
DS
155 nexthop_add(tnh, nexthop);
156
157 if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
158 copy_nexthops(&nexthop->resolved, nh1->resolved);
159 }
160}
161
162/* Free nexthop. */
163void
164nexthop_free (struct nexthop *nexthop)
165{
40c7bdb0 166 nexthop_del_labels (nexthop);
a399694f
DS
167 if (nexthop->resolved)
168 nexthops_free(nexthop->resolved);
169 XFREE (MTYPE_NEXTHOP, nexthop);
170}
171
172/* Frees a list of nexthops */
173void
174nexthops_free (struct nexthop *nexthop)
175{
176 struct nexthop *nh, *next;
177
178 for (nh = nexthop; nh; nh = next)
179 {
180 next = nh->next;
181 nexthop_free (nh);
182 }
183}
80c2442a 184
40c7bdb0 185/* Update nexthop with label information. */
186void
ce549947
RW
187nexthop_add_labels (struct nexthop *nexthop, enum lsp_types_t type,
188 u_int8_t num_labels, mpls_label_t *label)
40c7bdb0 189{
190 struct nexthop_label *nh_label;
191 int i;
192
ce549947 193 nexthop->nh_label_type = type;
e2a4192a 194 nh_label = XCALLOC (MTYPE_NH_LABEL, sizeof (struct nexthop_label) +
195 num_labels * sizeof (mpls_label_t));
40c7bdb0 196 nh_label->num_labels = num_labels;
197 for (i = 0; i < num_labels; i++)
198 nh_label->label[i] = *(label + i);
199 nexthop->nh_label = nh_label;
200}
201
202/* Free label information of nexthop, if present. */
203void
204nexthop_del_labels (struct nexthop *nexthop)
205{
206 if (nexthop->nh_label)
ce549947
RW
207 {
208 XFREE (MTYPE_NH_LABEL, nexthop->nh_label);
209 nexthop->nh_label_type = ZEBRA_LSP_NONE;
210 }
40c7bdb0 211}
212
80c2442a 213const char *
214nexthop2str (struct nexthop *nexthop, char *str, int size)
215{
216 switch (nexthop->type)
217 {
218 case NEXTHOP_TYPE_IFINDEX:
219 snprintf (str, size, "if %u", nexthop->ifindex);
220 break;
221 case NEXTHOP_TYPE_IPV4:
222 snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4));
223 break;
224 case NEXTHOP_TYPE_IPV4_IFINDEX:
225 snprintf (str, size, "%s if %u",
226 inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex);
227 break;
228 case NEXTHOP_TYPE_IPV6:
229 snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6));
230 break;
231 case NEXTHOP_TYPE_IPV6_IFINDEX:
232 snprintf (str, size, "%s if %u",
233 inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex);
234 break;
235 case NEXTHOP_TYPE_BLACKHOLE:
236 snprintf (str, size, "blackhole");
237 break;
238 default:
239 snprintf (str, size, "unknown");
240 break;
241 }
242
243 return str;
244}