/src/frr/bgpd/rfapi/vnc_export_table.c
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * |
4 | | * Copyright 2009-2016, LabN Consulting, L.L.C. |
5 | | * |
6 | | */ |
7 | | |
8 | | |
9 | | #include "lib/zebra.h" |
10 | | #include "lib/prefix.h" |
11 | | #include "lib/agg_table.h" |
12 | | #include "lib/memory.h" |
13 | | #include "lib/vty.h" |
14 | | |
15 | | #include "bgpd/bgpd.h" |
16 | | #include "bgpd/bgp_route.h" |
17 | | |
18 | | #include "bgpd/rfapi/vnc_export_table.h" |
19 | | #include "bgpd/rfapi/rfapi_private.h" |
20 | | #include "bgpd/rfapi/rfapi_import.h" |
21 | | #include "bgpd/rfapi/vnc_debug.h" |
22 | | |
23 | | struct agg_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, |
24 | | const struct prefix *p) |
25 | 0 | { |
26 | 0 | struct agg_table *t = NULL; |
27 | 0 | struct agg_node *rn = NULL; |
28 | 0 | afi_t afi; |
29 | |
|
30 | 0 | if (!bgp || !bgp->rfapi) |
31 | 0 | return NULL; |
32 | | |
33 | 0 | afi = family2afi(p->family); |
34 | 0 | assert(afi == AFI_IP || afi == AFI_IP6); |
35 | | |
36 | 0 | switch (type) { |
37 | 0 | case EXPORT_TYPE_BGP: |
38 | 0 | if (!bgp->rfapi->rt_export_bgp[afi]) |
39 | 0 | bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); |
40 | 0 | t = bgp->rfapi->rt_export_bgp[afi]; |
41 | 0 | break; |
42 | | |
43 | 0 | case EXPORT_TYPE_ZEBRA: |
44 | 0 | if (!bgp->rfapi->rt_export_zebra[afi]) |
45 | 0 | bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); |
46 | 0 | t = bgp->rfapi->rt_export_zebra[afi]; |
47 | 0 | break; |
48 | 0 | } |
49 | | |
50 | 0 | if (t) |
51 | 0 | rn = agg_node_get(t, p); |
52 | 0 | return rn; |
53 | 0 | } |
54 | | |
55 | | struct agg_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, |
56 | | const struct prefix *p) |
57 | 0 | { |
58 | 0 | struct agg_table *t = NULL; |
59 | 0 | struct agg_node *rn = NULL; |
60 | 0 | afi_t afi; |
61 | |
|
62 | 0 | if (!bgp || !bgp->rfapi) |
63 | 0 | return NULL; |
64 | | |
65 | 0 | afi = family2afi(p->family); |
66 | 0 | assert(afi == AFI_IP || afi == AFI_IP6); |
67 | | |
68 | 0 | switch (type) { |
69 | 0 | case EXPORT_TYPE_BGP: |
70 | 0 | if (!bgp->rfapi->rt_export_bgp[afi]) |
71 | 0 | bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); |
72 | 0 | t = bgp->rfapi->rt_export_bgp[afi]; |
73 | 0 | break; |
74 | | |
75 | 0 | case EXPORT_TYPE_ZEBRA: |
76 | 0 | if (!bgp->rfapi->rt_export_zebra[afi]) |
77 | 0 | bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); |
78 | 0 | t = bgp->rfapi->rt_export_zebra[afi]; |
79 | 0 | break; |
80 | 0 | } |
81 | | |
82 | 0 | if (t) |
83 | 0 | rn = agg_node_lookup(t, p); |
84 | 0 | return rn; |
85 | 0 | } |
86 | | |
87 | | struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, |
88 | | const struct prefix *p, struct peer *peer, |
89 | | uint8_t type, uint8_t subtype) |
90 | 0 | { |
91 | 0 | struct agg_node *etn; |
92 | 0 | struct vnc_export_info *eti; |
93 | |
|
94 | 0 | etn = vnc_etn_get(bgp, etype, p); |
95 | 0 | assert(etn); |
96 | | |
97 | 0 | for (eti = etn->info; eti; eti = eti->next) { |
98 | 0 | if (peer == eti->peer && type == eti->type |
99 | 0 | && subtype == eti->subtype) { |
100 | |
|
101 | 0 | break; |
102 | 0 | } |
103 | 0 | } |
104 | |
|
105 | 0 | if (eti) { |
106 | 0 | agg_unlock_node(etn); |
107 | 0 | } else { |
108 | 0 | eti = XCALLOC(MTYPE_RFAPI_ETI, sizeof(struct vnc_export_info)); |
109 | 0 | eti->node = etn; |
110 | 0 | eti->peer = peer; |
111 | 0 | peer_lock(peer); |
112 | 0 | eti->type = type; |
113 | 0 | eti->subtype = subtype; |
114 | 0 | eti->next = etn->info; |
115 | 0 | etn->info = eti; |
116 | 0 | } |
117 | |
|
118 | 0 | return eti; |
119 | 0 | } |
120 | | |
121 | | void vnc_eti_delete(struct vnc_export_info *goner) |
122 | 0 | { |
123 | 0 | struct agg_node *etn; |
124 | 0 | struct vnc_export_info *eti; |
125 | 0 | struct vnc_export_info *eti_prev = NULL; |
126 | |
|
127 | 0 | etn = goner->node; |
128 | |
|
129 | 0 | for (eti = etn->info; eti; eti_prev = eti, eti = eti->next) { |
130 | 0 | if (eti == goner) |
131 | 0 | break; |
132 | 0 | } |
133 | |
|
134 | 0 | if (!eti) { |
135 | 0 | vnc_zlog_debug_verbose("%s: COULDN'T FIND ETI", __func__); |
136 | 0 | return; |
137 | 0 | } |
138 | | |
139 | 0 | if (eti_prev) { |
140 | 0 | eti_prev->next = goner->next; |
141 | 0 | } else { |
142 | 0 | etn->info = goner->next; |
143 | 0 | } |
144 | |
|
145 | 0 | peer_unlock(eti->peer); |
146 | 0 | goner->node = NULL; |
147 | 0 | XFREE(MTYPE_RFAPI_ETI, goner); |
148 | |
|
149 | 0 | agg_unlock_node(etn); |
150 | 0 | } |
151 | | |
152 | | struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, |
153 | | vnc_export_type_t etype, |
154 | | const struct prefix *p, |
155 | | struct peer *peer, uint8_t type, |
156 | | uint8_t subtype) |
157 | 0 | { |
158 | 0 | struct agg_node *etn; |
159 | 0 | struct vnc_export_info *eti; |
160 | |
|
161 | 0 | etn = vnc_etn_lookup(bgp, etype, p); |
162 | 0 | if (!etn) |
163 | 0 | return NULL; |
164 | | |
165 | 0 | for (eti = etn->info; eti; eti = eti->next) { |
166 | 0 | if (peer == eti->peer && type == eti->type |
167 | 0 | && subtype == eti->subtype) { |
168 | |
|
169 | 0 | break; |
170 | 0 | } |
171 | 0 | } |
172 | |
|
173 | 0 | agg_unlock_node(etn); |
174 | |
|
175 | 0 | if (eti && eti->timer) |
176 | 0 | return eti; |
177 | | |
178 | 0 | return NULL; |
179 | 0 | } |