]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_nht.c
sharpd: Fix nexthop group name collision
[mirror_frr.git] / sharpd / sharp_nht.c
1 /*
2 * SHARP - code to track nexthops
3 * Copyright (C) Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This file is part of FRR.
7 *
8 * FRR is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * FRR is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #include <zebra.h>
23
24 #include "memory.h"
25 #include "nexthop.h"
26 #include "nexthop_group.h"
27 #include "vty.h"
28 #include "typesafe.h"
29 #include "zclient.h"
30
31 #include "sharp_nht.h"
32 #include "sharp_globals.h"
33 #include "sharp_zebra.h"
34
35 DEFINE_MTYPE_STATIC(SHARPD, NH_TRACKER, "Nexthop Tracker")
36 DEFINE_MTYPE_STATIC(SHARPD, NHG, "Nexthop Group")
37
38 struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p)
39 {
40 struct listnode *node;
41 struct sharp_nh_tracker *nht;
42
43 for (ALL_LIST_ELEMENTS_RO(sg.nhs, node, nht)) {
44 if (prefix_same(&nht->p, p))
45 break;
46 }
47
48 if (nht)
49 return nht;
50
51 nht = XCALLOC(MTYPE_NH_TRACKER, sizeof(*nht));
52 prefix_copy(&nht->p, p);
53
54 listnode_add(sg.nhs, nht);
55 return nht;
56 }
57
58 void sharp_nh_tracker_dump(struct vty *vty)
59 {
60 struct listnode *node;
61 struct sharp_nh_tracker *nht;
62
63 for (ALL_LIST_ELEMENTS_RO(sg.nhs, node, nht)) {
64 char buf[PREFIX_STRLEN];
65
66 vty_out(vty, "%s: Nexthops: %u Updates: %u\n",
67 prefix2str(&nht->p, buf, sizeof(buf)),
68 nht->nhop_num,
69 nht->updates);
70 }
71 }
72
73 PREDECL_RBTREE_UNIQ(sharp_nhg_rb);
74
75 struct sharp_nhg {
76 struct sharp_nhg_rb_item mylistitem;
77
78 uint32_t id;
79
80 #define NHG_NAME_LEN 256
81 char name[NHG_NAME_LEN];
82
83 bool installed;
84 };
85
86 static uint32_t nhg_id;
87
88 static uint32_t sharp_get_next_nhid(void)
89 {
90 zlog_debug("NHG ID assigned: %u", nhg_id);
91 return nhg_id++;
92 }
93
94 struct sharp_nhg_rb_head nhg_head;
95
96 static int sharp_nhg_compare_func(const struct sharp_nhg *a,
97 const struct sharp_nhg *b)
98 {
99 return strncmp(a->name, b->name, NHG_NAME_LEN);
100 }
101
102 DECLARE_RBTREE_UNIQ(sharp_nhg_rb, struct sharp_nhg, mylistitem,
103 sharp_nhg_compare_func);
104
105 static struct sharp_nhg *sharp_nhgroup_find_id(uint32_t id)
106 {
107 struct sharp_nhg *lookup;
108
109 /* Yea its just a for loop, I don't want add complexity
110 * to sharpd with another RB tree for just IDs
111 */
112
113 frr_each (sharp_nhg_rb, &nhg_head, lookup) {
114 if (lookup->id == id)
115 return lookup;
116 }
117
118 return NULL;
119 }
120
121 static void sharp_nhgroup_add_cb(const char *name)
122 {
123 struct sharp_nhg *snhg;
124
125 snhg = XCALLOC(MTYPE_NHG, sizeof(*snhg));
126 snhg->id = sharp_get_next_nhid();
127 strlcpy(snhg->name, name, sizeof(snhg->name));
128
129 sharp_nhg_rb_add(&nhg_head, snhg);
130 }
131
132 static void sharp_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
133 const struct nexthop *nhop)
134 {
135 struct sharp_nhg lookup;
136 struct sharp_nhg *snhg;
137 struct nexthop_group_cmd *bnhgc = NULL;
138
139 strlcpy(lookup.name, nhgc->name, sizeof(lookup.name));
140 snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
141
142 if (nhgc->backup_list_name[0])
143 bnhgc = nhgc_find(nhgc->backup_list_name);
144
145 nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL));
146 }
147
148 static void sharp_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
149 const struct nexthop *nhop)
150 {
151 struct sharp_nhg lookup;
152 struct sharp_nhg *snhg;
153 struct nexthop_group_cmd *bnhgc = NULL;
154
155 strlcpy(lookup.name, nhgc->name, sizeof(lookup.name));
156 snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
157
158 if (nhgc->backup_list_name[0])
159 bnhgc = nhgc_find(nhgc->backup_list_name);
160
161 nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL));
162 }
163
164 static void sharp_nhgroup_delete_cb(const char *name)
165 {
166 struct sharp_nhg lookup;
167 struct sharp_nhg *snhg;
168
169 strlcpy(lookup.name, name, sizeof(lookup.name));
170 snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
171 if (!snhg)
172 return;
173
174 nhg_del(snhg->id);
175 sharp_nhg_rb_del(&nhg_head, snhg);
176 XFREE(MTYPE_NHG, snhg);
177 }
178
179 uint32_t sharp_nhgroup_get_id(const char *name)
180 {
181 struct sharp_nhg lookup;
182 struct sharp_nhg *snhg;
183
184 strlcpy(lookup.name, name, sizeof(lookup.name));
185 snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
186 if (!snhg)
187 return 0;
188
189 return snhg->id;
190 }
191
192 void sharp_nhgroup_id_set_installed(uint32_t id, bool installed)
193 {
194 struct sharp_nhg *snhg;
195
196 snhg = sharp_nhgroup_find_id(id);
197 if (!snhg) {
198 zlog_debug("%s: nhg %u not found", __func__, id);
199 return;
200 }
201
202 snhg->installed = installed;
203 }
204
205 bool sharp_nhgroup_id_is_installed(uint32_t id)
206 {
207 struct sharp_nhg *snhg;
208
209 snhg = sharp_nhgroup_find_id(id);
210 if (!snhg) {
211 zlog_debug("%s: nhg %u not found", __func__, id);
212 return false;
213 }
214
215 return snhg->installed;
216 }
217
218 void sharp_nhgroup_init(void)
219 {
220 sharp_nhg_rb_init(&nhg_head);
221 nhg_id = zclient_get_nhg_start(ZEBRA_ROUTE_SHARP);
222
223 nexthop_group_init(sharp_nhgroup_add_cb, sharp_nhgroup_add_nexthop_cb,
224 sharp_nhgroup_del_nexthop_cb,
225 sharp_nhgroup_delete_cb);
226 }