]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_fpm_protobuf.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / zebra / zebra_fpm_protobuf.c
CommitLineData
fb0aa886
AS
1/*
2 * zebra_fpm_protobuf.c
3 *
4 * @copyright Copyright (C) 2016 Sproute Networks, Inc.
5 *
6 * @author Avneesh Sachdev <avneesh@sproute.com>
7 *
8 * This file is part of Quagga.
9 *
10 * Quagga is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
13 * later version.
14 *
15 * Quagga is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
896014f4
DL
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
fb0aa886
AS
23 */
24#include <zebra.h>
25
26#include "log.h"
27#include "rib.h"
518acd6f
DL
28#include "zserv.h"
29#include "zebra_vrf.h"
fb0aa886
AS
30
31#include "qpb/qpb.pb-c.h"
32#include "qpb/qpb.h"
33#include "qpb/qpb_allocator.h"
34#include "qpb/linear_allocator.h"
35#include "fpm/fpm_pb.h"
36
b03e089d 37#include "zebra_router.h"
fb0aa886
AS
38#include "zebra_fpm_private.h"
39
40/*
41 * create_delete_route_message
42 */
d62a17ae 43static Fpm__DeleteRoute *create_delete_route_message(qpb_allocator_t *allocator,
44 rib_dest_t *dest,
45 struct route_entry *re)
fb0aa886 46{
d62a17ae 47 Fpm__DeleteRoute *msg;
48
49 msg = QPB_ALLOC(allocator, typeof(*msg));
50 if (!msg) {
51 assert(0);
52 return NULL;
53 }
54
55 fpm__delete_route__init(msg);
56 msg->vrf_id = zvrf_id(rib_dest_vrf(dest));
57
58 qpb_address_family_set(&msg->address_family, rib_dest_af(dest));
59
60 /*
61 * XXX Hardcode subaddress family for now.
62 */
63 msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
64 msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
65 if (!msg->key) {
66 assert(0);
67 return NULL;
68 }
69
70 return msg;
fb0aa886
AS
71}
72
73/*
74 * add_nexthop
75 */
d62a17ae 76static inline int add_nexthop(qpb_allocator_t *allocator, Fpm__AddRoute *msg,
77 rib_dest_t *dest, struct nexthop *nexthop)
fb0aa886 78{
d62a17ae 79 uint32_t if_index;
80 union g_addr *gateway, *src;
81
82 gateway = src = NULL;
83
84 if_index = nexthop->ifindex;
85
86 if (nexthop->type == NEXTHOP_TYPE_IPV4
87 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
88 gateway = &nexthop->gate;
975a328e 89 if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 90 src = &nexthop->src;
91 }
92
93 if (nexthop->type == NEXTHOP_TYPE_IPV6
94 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
95 gateway = &nexthop->gate;
96 }
97
98 if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
975a328e 99 if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 100 src = &nexthop->src;
101 }
102
103 if (!gateway && if_index == 0)
104 return 0;
105
106 /*
107 * We have a valid nexthop.
108 */
109 {
110 Fpm__Nexthop *pb_nh;
111 pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh));
112 if (!pb_nh) {
113 assert(0);
114 return 0;
115 }
116
117 fpm__nexthop__init(pb_nh);
118
119 if (if_index != 0) {
120 pb_nh->if_id =
121 qpb_if_identifier_create(allocator, if_index);
122 }
123
124 if (gateway) {
125 pb_nh->address = qpb_l3_address_create(
126 allocator, gateway, rib_dest_af(dest));
127 }
128
129 msg->nexthops[msg->n_nexthops++] = pb_nh;
130 }
131
132 // TODO: Use src.
4f4060f6 133 (void)src;
d62a17ae 134
135 return 1;
fb0aa886
AS
136}
137
138/*
139 * create_add_route_message
140 */
d62a17ae 141static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
142 rib_dest_t *dest,
143 struct route_entry *re)
fb0aa886 144{
d62a17ae 145 Fpm__AddRoute *msg;
d62a17ae 146 struct nexthop *nexthop;
147 uint num_nhs, u;
148 struct nexthop *nexthops[MULTIPATH_NUM];
149
150 msg = QPB_ALLOC(allocator, typeof(*msg));
151 if (!msg) {
152 assert(0);
153 return NULL;
154 }
155
156 fpm__add_route__init(msg);
157
158 msg->vrf_id = zvrf_id(rib_dest_vrf(dest));
159
160 qpb_address_family_set(&msg->address_family, rib_dest_af(dest));
161
162 /*
163 * XXX Hardcode subaddress family for now.
164 */
165 msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
166 msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
167 qpb_protocol_set(&msg->protocol, re->type);
1a6a5e69 168 msg->has_route_type = 1;
a8309422 169 msg->route_type = FPM__ROUTE_TYPE__NORMAL;
d62a17ae 170 msg->metric = re->metric;
171
172 /*
173 * Figure out the set of nexthops to be added to the message.
174 */
175 num_nhs = 0;
0eb97b86 176 for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
b03e089d 177 if (num_nhs >= zrouter.multipath_num)
d62a17ae 178 break;
179
7e3a1ec7 180 if (num_nhs >= array_size(nexthops))
d62a17ae 181 break;
182
a8309422
DL
183 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
184 switch (nexthop->bh_type) {
185 case BLACKHOLE_REJECT:
186 msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
187 break;
188 case BLACKHOLE_NULL:
189 default:
190 msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
191 break;
192 }
193 return msg;
194 }
195
d62a17ae 196 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
197 continue;
198
199 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
200 continue;
201
202 nexthops[num_nhs] = nexthop;
203 num_nhs++;
204 }
205
206 if (!num_nhs) {
207 zfpm_debug("netlink_encode_route(): No useful nexthop.");
208 assert(0);
209 return NULL;
210 }
211
212 /*
213 * And add them to the message.
214 */
215 if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) {
216 assert(0);
217 return NULL;
218 }
219
220 msg->n_nexthops = 0;
221 for (u = 0; u < num_nhs; u++) {
222 if (!add_nexthop(allocator, msg, dest, nexthops[u])) {
223 assert(0);
224 return NULL;
225 }
226 }
227
228 assert(msg->n_nexthops == num_nhs);
229
230 return msg;
fb0aa886
AS
231}
232
233/*
234 * create_route_message
235 */
d62a17ae 236static Fpm__Message *create_route_message(qpb_allocator_t *allocator,
237 rib_dest_t *dest,
238 struct route_entry *re)
fb0aa886 239{
d62a17ae 240 Fpm__Message *msg;
241
242 msg = QPB_ALLOC(allocator, typeof(*msg));
243 if (!msg) {
244 assert(0);
245 return NULL;
246 }
247
248 fpm__message__init(msg);
249
250 if (!re) {
1a6a5e69 251 msg->has_type = 1;
d62a17ae 252 msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE;
253 msg->delete_route =
254 create_delete_route_message(allocator, dest, re);
255 if (!msg->delete_route) {
256 assert(0);
257 return NULL;
258 }
259 return msg;
260 }
261
1a6a5e69 262 msg->has_type = 1;
d62a17ae 263 msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE;
264 msg->add_route = create_add_route_message(allocator, dest, re);
265 if (!msg->add_route) {
266 assert(0);
267 return NULL;
268 }
269
270 return msg;
fb0aa886
AS
271}
272
273/*
274 * zfpm_protobuf_encode_route
275 *
276 * Create a protobuf message corresponding to the given route in the
277 * given buffer space.
278 *
279 * Returns the number of bytes written to the buffer. 0 or a negative
280 * value indicates an error.
281 */
d62a17ae 282int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re,
283 uint8_t *in_buf, size_t in_buf_len)
fb0aa886 284{
d62a17ae 285 Fpm__Message *msg;
286 QPB_DECLARE_STACK_ALLOCATOR(allocator, 4096);
287 size_t len;
fb0aa886 288
d62a17ae 289 QPB_INIT_STACK_ALLOCATOR(allocator);
fb0aa886 290
d62a17ae 291 msg = create_route_message(&allocator, dest, re);
292 if (!msg) {
293 assert(0);
294 return 0;
295 }
fb0aa886 296
d62a17ae 297 len = fpm__message__pack(msg, (uint8_t *)in_buf);
298 assert(len <= in_buf_len);
fb0aa886 299
d62a17ae 300 QPB_RESET_STACK_ALLOCATOR(allocator);
301 return len;
fb0aa886 302}