]> git.proxmox.com Git - mirror_frr.git/blob - lib/nexthop.c
Merge pull request #488 from donaldsharp/sudoers3
[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
17 * along with Quagga; see the file COPYING. If not, write to the Free
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"
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"
34 #include "mpls.h"
35
36 DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
37 DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
38
39 /* check if nexthops are same, non-recursive */
40 int
41 nexthop_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:
56 if (next1->ifindex != next2->ifindex)
57 return 0;
58 break;
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:
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;
69 default:
70 /* do nothing */
71 break;
72 }
73 return 1;
74 }
75
76 /*
77 * nexthop_type_to_str
78 */
79 const char *
80 nexthop_type_to_str (enum nexthop_types_t nh_type)
81 {
82 static const char *desc[] = {
83 "none",
84 "Directly connected",
85 "IPv4 nexthop",
86 "IPv4 nexthop with ifindex",
87 "IPv6 nexthop",
88 "IPv6 nexthop with ifindex",
89 "Null0 nexthop",
90 };
91
92 return desc[nh_type];
93 }
94
95 struct nexthop *
96 nexthop_new (void)
97 {
98 return XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
99 }
100
101 /* Add nexthop to the end of a nexthop list. */
102 void
103 nexthop_add (struct nexthop **target, struct nexthop *nexthop)
104 {
105 struct nexthop *last;
106
107 for (last = *target; last && last->next; last = last->next)
108 ;
109 if (last)
110 last->next = nexthop;
111 else
112 *target = nexthop;
113 nexthop->prev = last;
114 }
115
116 void
117 copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
118 {
119 struct nexthop *nexthop;
120 struct nexthop *nh1;
121
122 for (nh1 = nh; nh1; nh1 = nh1->next)
123 {
124 nexthop = nexthop_new();
125 nexthop->flags = nh->flags;
126 nexthop->type = nh->type;
127 nexthop->ifindex = nh->ifindex;
128 memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
129 memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
130 if (nh->nh_label)
131 nexthop_add_labels (nexthop, nh->nh_label_type,
132 nh->nh_label->num_labels, &nh->nh_label->label[0]);
133 nexthop_add(tnh, nexthop);
134
135 if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
136 copy_nexthops(&nexthop->resolved, nh1->resolved);
137 }
138 }
139
140 /* Free nexthop. */
141 void
142 nexthop_free (struct nexthop *nexthop)
143 {
144 nexthop_del_labels (nexthop);
145 if (nexthop->resolved)
146 nexthops_free(nexthop->resolved);
147 XFREE (MTYPE_NEXTHOP, nexthop);
148 }
149
150 /* Frees a list of nexthops */
151 void
152 nexthops_free (struct nexthop *nexthop)
153 {
154 struct nexthop *nh, *next;
155
156 for (nh = nexthop; nh; nh = next)
157 {
158 next = nh->next;
159 nexthop_free (nh);
160 }
161 }
162
163 /* Update nexthop with label information. */
164 void
165 nexthop_add_labels (struct nexthop *nexthop, enum lsp_types_t type,
166 u_int8_t num_labels, mpls_label_t *label)
167 {
168 struct nexthop_label *nh_label;
169 int i;
170
171 nexthop->nh_label_type = type;
172 nh_label = XCALLOC (MTYPE_NH_LABEL, sizeof (struct nexthop_label) +
173 num_labels * sizeof (mpls_label_t));
174 nh_label->num_labels = num_labels;
175 for (i = 0; i < num_labels; i++)
176 nh_label->label[i] = *(label + i);
177 nexthop->nh_label = nh_label;
178 }
179
180 /* Free label information of nexthop, if present. */
181 void
182 nexthop_del_labels (struct nexthop *nexthop)
183 {
184 if (nexthop->nh_label)
185 {
186 XFREE (MTYPE_NH_LABEL, nexthop->nh_label);
187 nexthop->nh_label_type = ZEBRA_LSP_NONE;
188 }
189 }
190
191 const char *
192 nexthop2str (struct nexthop *nexthop, char *str, int size)
193 {
194 switch (nexthop->type)
195 {
196 case NEXTHOP_TYPE_IFINDEX:
197 snprintf (str, size, "if %u", nexthop->ifindex);
198 break;
199 case NEXTHOP_TYPE_IPV4:
200 snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4));
201 break;
202 case NEXTHOP_TYPE_IPV4_IFINDEX:
203 snprintf (str, size, "%s if %u",
204 inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex);
205 break;
206 case NEXTHOP_TYPE_IPV6:
207 snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6));
208 break;
209 case NEXTHOP_TYPE_IPV6_IFINDEX:
210 snprintf (str, size, "%s if %u",
211 inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex);
212 break;
213 case NEXTHOP_TYPE_BLACKHOLE:
214 snprintf (str, size, "blackhole");
215 break;
216 default:
217 snprintf (str, size, "unknown");
218 break;
219 }
220
221 return str;
222 }