]>
Commit | Line | Data |
---|---|---|
86da53ab DS |
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" | |
569e87c0 DS |
28 | #include "typesafe.h" |
29 | #include "zclient.h" | |
86da53ab DS |
30 | |
31 | #include "sharp_nht.h" | |
32 | #include "sharp_globals.h" | |
569e87c0 | 33 | #include "sharp_zebra.h" |
86da53ab DS |
34 | |
35 | DEFINE_MTYPE_STATIC(SHARPD, NH_TRACKER, "Nexthop Tracker") | |
569e87c0 | 36 | DEFINE_MTYPE_STATIC(SHARPD, NHG, "Nexthop Group") |
86da53ab DS |
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 | } | |
569e87c0 DS |
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 | char name[256]; | |
2053061b SW |
81 | |
82 | bool installed; | |
569e87c0 DS |
83 | }; |
84 | ||
85 | static uint32_t nhg_id; | |
86 | ||
87 | static uint32_t sharp_get_next_nhid(void) | |
88 | { | |
612fcc5e | 89 | zlog_debug("NHG ID assigned: %u", nhg_id); |
569e87c0 DS |
90 | return nhg_id++; |
91 | } | |
92 | ||
93 | struct sharp_nhg_rb_head nhg_head; | |
94 | ||
95 | static int sharp_nhg_compare_func(const struct sharp_nhg *a, | |
96 | const struct sharp_nhg *b) | |
97 | { | |
98 | return strncmp(a->name, b->name, strlen(a->name)); | |
99 | } | |
100 | ||
101 | DECLARE_RBTREE_UNIQ(sharp_nhg_rb, struct sharp_nhg, mylistitem, | |
102 | sharp_nhg_compare_func); | |
103 | ||
2053061b SW |
104 | static struct sharp_nhg *sharp_nhgroup_find_id(uint32_t id) |
105 | { | |
106 | struct sharp_nhg *lookup; | |
107 | ||
108 | /* Yea its just a for loop, I don't want add complexity | |
109 | * to sharpd with another RB tree for just IDs | |
110 | */ | |
111 | ||
ff9aca4f | 112 | frr_each (sharp_nhg_rb, &nhg_head, lookup) { |
2053061b SW |
113 | if (lookup->id == id) |
114 | return lookup; | |
115 | } | |
116 | ||
117 | return NULL; | |
118 | } | |
119 | ||
569e87c0 DS |
120 | static void sharp_nhgroup_add_cb(const char *name) |
121 | { | |
122 | struct sharp_nhg *snhg; | |
123 | ||
124 | snhg = XCALLOC(MTYPE_NHG, sizeof(*snhg)); | |
125 | snhg->id = sharp_get_next_nhid(); | |
73937edb | 126 | strlcpy(snhg->name, name, sizeof(snhg->name)); |
569e87c0 DS |
127 | |
128 | sharp_nhg_rb_add(&nhg_head, snhg); | |
569e87c0 DS |
129 | } |
130 | ||
131 | static void sharp_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc, | |
132 | const struct nexthop *nhop) | |
133 | { | |
134 | struct sharp_nhg lookup; | |
135 | struct sharp_nhg *snhg; | |
21735352 | 136 | struct nexthop_group_cmd *bnhgc = NULL; |
569e87c0 | 137 | |
73937edb | 138 | strlcpy(lookup.name, nhgc->name, sizeof(lookup.name)); |
569e87c0 DS |
139 | snhg = sharp_nhg_rb_find(&nhg_head, &lookup); |
140 | ||
21735352 SW |
141 | if (nhgc->backup_list_name[0]) |
142 | bnhgc = nhgc_find(nhgc->backup_list_name); | |
143 | ||
144 | nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL)); | |
569e87c0 DS |
145 | } |
146 | ||
147 | static void sharp_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc, | |
148 | const struct nexthop *nhop) | |
149 | { | |
150 | struct sharp_nhg lookup; | |
151 | struct sharp_nhg *snhg; | |
21735352 | 152 | struct nexthop_group_cmd *bnhgc = NULL; |
569e87c0 | 153 | |
73937edb | 154 | strlcpy(lookup.name, nhgc->name, sizeof(lookup.name)); |
569e87c0 DS |
155 | snhg = sharp_nhg_rb_find(&nhg_head, &lookup); |
156 | ||
21735352 SW |
157 | if (nhgc->backup_list_name[0]) |
158 | bnhgc = nhgc_find(nhgc->backup_list_name); | |
159 | ||
160 | nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL)); | |
569e87c0 DS |
161 | } |
162 | ||
163 | static void sharp_nhgroup_delete_cb(const char *name) | |
164 | { | |
165 | struct sharp_nhg lookup; | |
166 | struct sharp_nhg *snhg; | |
167 | ||
73937edb | 168 | strlcpy(lookup.name, name, sizeof(lookup.name)); |
569e87c0 DS |
169 | snhg = sharp_nhg_rb_find(&nhg_head, &lookup); |
170 | if (!snhg) | |
171 | return; | |
172 | ||
cc6a0d7d | 173 | nhg_del(snhg->id); |
569e87c0 DS |
174 | sharp_nhg_rb_del(&nhg_head, snhg); |
175 | XFREE(MTYPE_NHG, snhg); | |
569e87c0 DS |
176 | } |
177 | ||
178 | uint32_t sharp_nhgroup_get_id(const char *name) | |
179 | { | |
180 | struct sharp_nhg lookup; | |
181 | struct sharp_nhg *snhg; | |
182 | ||
73937edb | 183 | strlcpy(lookup.name, name, sizeof(lookup.name)); |
569e87c0 DS |
184 | snhg = sharp_nhg_rb_find(&nhg_head, &lookup); |
185 | if (!snhg) | |
186 | return 0; | |
187 | ||
188 | return snhg->id; | |
189 | } | |
190 | ||
2053061b SW |
191 | void sharp_nhgroup_id_set_installed(uint32_t id, bool installed) |
192 | { | |
193 | struct sharp_nhg *snhg; | |
194 | ||
195 | snhg = sharp_nhgroup_find_id(id); | |
196 | if (!snhg) { | |
197 | zlog_debug("%s: nhg %u not found", __func__, id); | |
198 | return; | |
199 | } | |
200 | ||
201 | snhg->installed = installed; | |
202 | } | |
203 | ||
204 | bool sharp_nhgroup_id_is_installed(uint32_t id) | |
205 | { | |
206 | struct sharp_nhg *snhg; | |
207 | ||
208 | snhg = sharp_nhgroup_find_id(id); | |
209 | if (!snhg) { | |
210 | zlog_debug("%s: nhg %u not found", __func__, id); | |
211 | return false; | |
212 | } | |
213 | ||
214 | return snhg->installed; | |
215 | } | |
216 | ||
569e87c0 DS |
217 | void sharp_nhgroup_init(void) |
218 | { | |
219 | sharp_nhg_rb_init(&nhg_head); | |
220 | nhg_id = zclient_get_nhg_start(ZEBRA_ROUTE_SHARP); | |
221 | ||
222 | nexthop_group_init(sharp_nhgroup_add_cb, sharp_nhgroup_add_nexthop_cb, | |
223 | sharp_nhgroup_del_nexthop_cb, | |
cc6a0d7d | 224 | sharp_nhgroup_delete_cb); |
569e87c0 | 225 | } |