zebra_fpm_protobuf.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Quagga; see the file COPYING. If not, write to the Free
  22. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  23. * 02111-1307, USA.
  24. */
  25. #include <zebra.h>
  26. #include "log.h"
  27. #include "rib.h"
  28. #include "qpb/qpb.pb-c.h"
  29. #include "qpb/qpb.h"
  30. #include "qpb/qpb_allocator.h"
  31. #include "qpb/linear_allocator.h"
  32. #include "fpm/fpm_pb.h"
  33. #include "zebra_fpm_private.h"
  34. /*
  35. * create_delete_route_message
  36. */
  37. static Fpm__DeleteRoute *
  38. create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
  39. struct rib *rib)
  40. {
  41. Fpm__DeleteRoute *msg;
  42. msg = QPB_ALLOC(allocator, typeof(*msg));
  43. if (!msg) {
  44. assert(0);
  45. return NULL;
  46. }
  47. fpm__delete_route__init(msg);
  48. msg->vrf_id = rib_dest_vrf(dest)->vrf_id;
  49. qpb_address_family_set(&msg->address_family, rib_dest_af(dest));
  50. /*
  51. * XXX Hardcode subaddress family for now.
  52. */
  53. msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
  54. msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest));
  55. if (!msg->key) {
  56. assert(0);
  57. return NULL;
  58. }
  59. return msg;
  60. }
  61. /*
  62. * add_nexthop
  63. */
  64. static inline int
  65. add_nexthop (qpb_allocator_t *allocator, Fpm__AddRoute *msg, rib_dest_t *dest,
  66. struct nexthop *nexthop)
  67. {
  68. uint32_t if_index;
  69. union g_addr *gateway, *src;
  70. gateway = src = NULL;
  71. if_index = nexthop->ifindex;
  72. if (nexthop->type == NEXTHOP_TYPE_IPV4
  73. || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  74. {
  75. gateway = &nexthop->gate;
  76. if (nexthop->src.ipv4.s_addr)
  77. src = &nexthop->src;
  78. }
  79. if (nexthop->type == NEXTHOP_TYPE_IPV6
  80. || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  81. || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  82. {
  83. gateway = &nexthop->gate;
  84. }
  85. if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  86. || nexthop->type == NEXTHOP_TYPE_IFNAME)
  87. {
  88. if (nexthop->src.ipv4.s_addr)
  89. src = &nexthop->src;
  90. }
  91. if (!gateway && if_index == 0)
  92. return 0;
  93. /*
  94. * We have a valid nexthop.
  95. */
  96. {
  97. Fpm__Nexthop *pb_nh;
  98. pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh));
  99. if (!pb_nh) {
  100. assert(0);
  101. return 0;
  102. }
  103. fpm__nexthop__init(pb_nh);
  104. if (if_index != 0) {
  105. pb_nh->if_id = qpb_if_identifier_create (allocator, if_index);
  106. }
  107. if (gateway) {
  108. pb_nh->address = qpb_l3_address_create (allocator, gateway,
  109. rib_dest_af(dest));
  110. }
  111. msg->nexthops[msg->n_nexthops++] = pb_nh;
  112. }
  113. // TODO: Use src.
  114. return 1;
  115. }
  116. /*
  117. * create_add_route_message
  118. */
  119. static Fpm__AddRoute *
  120. create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
  121. struct rib *rib)
  122. {
  123. Fpm__AddRoute *msg;
  124. int discard;
  125. struct nexthop *nexthop, *tnexthop;
  126. int recursing;
  127. uint num_nhs, u;
  128. struct nexthop *nexthops[MAX (MULTIPATH_NUM, 64)];
  129. msg = QPB_ALLOC(allocator, typeof(*msg));
  130. if (!msg) {
  131. assert(0);
  132. return NULL;
  133. }
  134. fpm__add_route__init(msg);
  135. msg->vrf_id = rib_dest_vrf(dest)->vrf_id;
  136. qpb_address_family_set (&msg->address_family, rib_dest_af(dest));
  137. /*
  138. * XXX Hardcode subaddress family for now.
  139. */
  140. msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
  141. msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest));
  142. qpb_protocol_set (&msg->protocol, rib->type);
  143. if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
  144. discard = 1;
  145. else
  146. discard = 0;
  147. if (discard)
  148. {
  149. if (rib->flags & ZEBRA_FLAG_BLACKHOLE) {
  150. msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
  151. } else if (rib->flags & ZEBRA_FLAG_REJECT) {
  152. msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
  153. } else {
  154. assert (0);
  155. }
  156. return msg;
  157. }
  158. else {
  159. msg->route_type = FPM__ROUTE_TYPE__NORMAL;
  160. }
  161. msg->metric = rib->metric;
  162. /*
  163. * Figure out the set of nexthops to be added to the message.
  164. */
  165. num_nhs = 0;
  166. for (ALL_NEXTHOPS_RO (rib->nexthop, nexthop, tnexthop, recursing))
  167. {
  168. if (MULTIPATH_NUM != 0 && num_nhs >= MULTIPATH_NUM)
  169. break;
  170. if (num_nhs >= ZEBRA_NUM_OF(nexthops))
  171. break;
  172. if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  173. continue;
  174. if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  175. continue;
  176. nexthops[num_nhs] = nexthop;
  177. num_nhs++;
  178. }
  179. if (!num_nhs) {
  180. zfpm_debug ("netlink_encode_route(): No useful nexthop.");
  181. assert(0);
  182. return NULL;
  183. }
  184. /*
  185. * And add them to the message.
  186. */
  187. if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) {
  188. assert(0);
  189. return NULL;
  190. }
  191. msg->n_nexthops = 0;
  192. for (u = 0; u < num_nhs; u++) {
  193. if (!add_nexthop(allocator, msg, dest, nexthops[u])) {
  194. assert(0);
  195. return NULL;
  196. }
  197. }
  198. assert(msg->n_nexthops == num_nhs);
  199. return msg;
  200. }
  201. /*
  202. * create_route_message
  203. */
  204. static Fpm__Message *
  205. create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
  206. struct rib *rib)
  207. {
  208. Fpm__Message *msg;
  209. msg = QPB_ALLOC(allocator, typeof(*msg));
  210. if (!msg) {
  211. assert(0);
  212. return NULL;
  213. }
  214. fpm__message__init(msg);
  215. if (!rib) {
  216. msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE;
  217. msg->delete_route = create_delete_route_message(allocator, dest, rib);
  218. if (!msg->delete_route) {
  219. assert(0);
  220. return NULL;
  221. }
  222. return msg;
  223. }
  224. msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE;
  225. msg->add_route = create_add_route_message(allocator, dest, rib);
  226. if (!msg->add_route) {
  227. assert(0);
  228. return NULL;
  229. }
  230. return msg;
  231. }
  232. /*
  233. * zfpm_protobuf_encode_route
  234. *
  235. * Create a protobuf message corresponding to the given route in the
  236. * given buffer space.
  237. *
  238. * Returns the number of bytes written to the buffer. 0 or a negative
  239. * value indicates an error.
  240. */
  241. int
  242. zfpm_protobuf_encode_route (rib_dest_t *dest, struct rib *rib,
  243. uint8_t *in_buf, size_t in_buf_len)
  244. {
  245. Fpm__Message *msg;
  246. QPB_DECLARE_STACK_ALLOCATOR (allocator, 4096);
  247. size_t len;
  248. QPB_INIT_STACK_ALLOCATOR (allocator);
  249. msg = create_route_message(&allocator, dest, rib);
  250. if (!msg) {
  251. assert(0);
  252. return 0;
  253. }
  254. len = fpm__message__pack(msg, (uint8_t *) in_buf);
  255. assert(len <= in_buf_len);
  256. QPB_RESET_STACK_ALLOCATOR (allocator);
  257. return len;
  258. }