]>
Commit | Line | Data |
---|---|---|
47a3a827 | 1 | // SPDX-License-Identifier: ISC OR GPL-2.0-or-later |
443b9937 AS |
2 | /* |
3 | * Public definitions pertaining to the Forwarding Plane Manager component. | |
4 | * | |
5 | * Permission is granted to use, copy, modify and/or distribute this | |
6 | * software under either one of the licenses below. | |
7 | * | |
8 | * Note that if you use other files from the Quagga tree directly or | |
9 | * indirectly, then the licenses in those files still apply. | |
10 | * | |
11 | * Please retain both licenses below when modifying this code in the | |
12 | * Quagga tree. | |
13 | * | |
14 | * Copyright (C) 2012 by Open Source Routing. | |
15 | * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC") | |
16 | */ | |
17 | ||
18 | /* | |
19 | * License Option 1: GPL | |
443b9937 | 20 | * License Option 2: ISC License |
443b9937 AS |
21 | */ |
22 | ||
23 | #ifndef _FPM_H | |
24 | #define _FPM_H | |
25 | ||
26 | /* | |
27 | * The Forwarding Plane Manager (FPM) is an optional component that | |
28 | * may be used in scenarios where the router has a forwarding path | |
29 | * that is distinct from the kernel, commonly a hardware-based fast | |
30 | * path. It is responsible for programming forwarding information | |
31 | * (such as routes and nexthops) in the fast path. | |
32 | * | |
33 | * In Quagga, the Routing Information Base is maintained in the | |
34 | * 'zebra' infrastructure daemon. Routing protocols communicate their | |
35 | * best routes to zebra, and zebra computes the best route across | |
36 | * protocols for each prefix. This latter information comprises the | |
37 | * bulk of the Forwarding Information Base. | |
38 | * | |
39 | * This header file defines a point-to-point interface using which | |
40 | * zebra can update the FPM about changes in routes. The communication | |
41 | * takes place over a stream socket. The FPM listens on a well-known | |
42 | * TCP port, and zebra initiates the connection. | |
43 | * | |
44 | * All messages sent over the connection start with a short FPM | |
45 | * header, fpm_msg_hdr_t. In the case of route add/delete messages, | |
46 | * the header is followed by a netlink message. Zebra should send a | |
47 | * complete copy of the forwarding table(s) to the FPM, including | |
48 | * routes that it may have picked up from the kernel. | |
49 | * | |
50 | * The FPM interface uses replace semantics. That is, if a 'route add' | |
51 | * message for a prefix is followed by another 'route add' message, the | |
52 | * information in the second message is complete by itself, and replaces | |
53 | * the information sent in the first message. | |
54 | * | |
55 | * If the connection to the FPM goes down for some reason, the client | |
56 | * (zebra) should send the FPM a complete copy of the forwarding | |
57 | * table(s) when it reconnects. | |
58 | */ | |
59 | ||
711ff0ba | 60 | /* |
d62a17ae | 61 | * Local host as a default server for fpm connection |
711ff0ba USK |
62 | */ |
63 | #define FPM_DEFAULT_IP (htonl (INADDR_LOOPBACK)) | |
64 | ||
65 | /* | |
66 | * default port for fpm connections | |
67 | */ | |
443b9937 AS |
68 | #define FPM_DEFAULT_PORT 2620 |
69 | ||
70 | /* | |
71 | * Largest message that can be sent to or received from the FPM. | |
72 | */ | |
73 | #define FPM_MAX_MSG_LEN 4096 | |
74 | ||
93c7bed1 AS |
75 | #ifdef __SUNPRO_C |
76 | #pragma pack(1) | |
77 | #endif | |
78 | ||
443b9937 AS |
79 | /* |
80 | * Header that precedes each fpm message to/from the FPM. | |
81 | */ | |
d62a17ae | 82 | typedef struct fpm_msg_hdr_t_ { |
83 | /* | |
84 | * Protocol version. | |
85 | */ | |
86 | uint8_t version; | |
87 | ||
88 | /* | |
89 | * Type of message, see below. | |
90 | */ | |
91 | uint8_t msg_type; | |
92 | ||
93 | /* | |
94 | * Length of entire message, including the header, in network byte | |
95 | * order. | |
96 | */ | |
97 | uint16_t msg_len; | |
98 | } __attribute__((packed)) fpm_msg_hdr_t; | |
93c7bed1 AS |
99 | |
100 | #ifdef __SUNPRO_C | |
101 | #pragma pack() | |
102 | #endif | |
443b9937 AS |
103 | |
104 | /* | |
105 | * The current version of the FPM protocol is 1. | |
106 | */ | |
107 | #define FPM_PROTO_VERSION 1 | |
108 | ||
109 | typedef enum fpm_msg_type_e_ { | |
d62a17ae | 110 | FPM_MSG_TYPE_NONE = 0, |
111 | ||
112 | /* | |
113 | * Indicates that the payload is a completely formed netlink | |
114 | * message. | |
115 | * | |
116 | * XXX Netlink cares about the alignment of messages. When any | |
117 | * FPM_MSG_TYPE_NETLINK messages are sent over a channel, then all | |
118 | * messages should be sized such that netlink alignment is | |
119 | * maintained. | |
120 | */ | |
121 | FPM_MSG_TYPE_NETLINK = 1, | |
122 | FPM_MSG_TYPE_PROTOBUF = 2, | |
443b9937 AS |
123 | } fpm_msg_type_e; |
124 | ||
125 | /* | |
126 | * The FPM message header is aligned to the same boundary as netlink | |
127 | * messages (4). This means that a netlink message does not need | |
128 | * padding when encapsulated in an FPM message. | |
129 | */ | |
130 | #define FPM_MSG_ALIGNTO 4 | |
131 | ||
132 | /* | |
133 | * fpm_msg_align | |
134 | * | |
135 | * Round up the given length to the desired alignment. | |
93c7bed1 AS |
136 | * |
137 | * **NB**: Alignment is required only when netlink messages are used. | |
443b9937 | 138 | */ |
d62a17ae | 139 | static inline size_t fpm_msg_align(size_t len) |
443b9937 | 140 | { |
d62a17ae | 141 | return (len + FPM_MSG_ALIGNTO - 1) & ~(FPM_MSG_ALIGNTO - 1); |
443b9937 AS |
142 | } |
143 | ||
144 | /* | |
145 | * The (rounded up) size of the FPM message header. This ensures that | |
146 | * the message payload always starts at an aligned address. | |
147 | */ | |
0d6f7fd6 | 148 | #define FPM_MSG_HDR_LEN (sizeof(fpm_msg_hdr_t)) |
93c7bed1 AS |
149 | |
150 | #ifndef COMPILE_ASSERT | |
151 | #define COMPILE_ASSERT(x) extern int __dummy[2 * !!(x) - 1] | |
152 | #endif | |
153 | ||
154 | COMPILE_ASSERT(FPM_MSG_ALIGNTO == FPM_MSG_HDR_LEN); | |
443b9937 AS |
155 | |
156 | /* | |
157 | * fpm_data_len_to_msg_len | |
158 | * | |
159 | * The length value that should be placed in the msg_len field of the | |
160 | * header for a *payload* of size 'data_len'. | |
161 | */ | |
d62a17ae | 162 | static inline size_t fpm_data_len_to_msg_len(size_t data_len) |
443b9937 | 163 | { |
d62a17ae | 164 | return data_len + FPM_MSG_HDR_LEN; |
443b9937 AS |
165 | } |
166 | ||
167 | /* | |
168 | * fpm_msg_data | |
169 | * | |
170 | * Pointer to the payload of the given fpm header. | |
171 | */ | |
d62a17ae | 172 | static inline void *fpm_msg_data(fpm_msg_hdr_t *hdr) |
443b9937 | 173 | { |
d62a17ae | 174 | return ((char *)hdr) + FPM_MSG_HDR_LEN; |
443b9937 AS |
175 | } |
176 | ||
177 | /* | |
178 | * fpm_msg_len | |
179 | */ | |
d62a17ae | 180 | static inline size_t fpm_msg_len(const fpm_msg_hdr_t *hdr) |
443b9937 | 181 | { |
d62a17ae | 182 | return ntohs(hdr->msg_len); |
443b9937 AS |
183 | } |
184 | ||
185 | /* | |
186 | * fpm_msg_data_len | |
187 | */ | |
d62a17ae | 188 | static inline size_t fpm_msg_data_len(const fpm_msg_hdr_t *hdr) |
443b9937 | 189 | { |
d62a17ae | 190 | return (fpm_msg_len(hdr) - FPM_MSG_HDR_LEN); |
443b9937 AS |
191 | } |
192 | ||
193 | /* | |
194 | * fpm_msg_next | |
195 | * | |
196 | * Move to the next message in a buffer. | |
197 | */ | |
d62a17ae | 198 | static inline fpm_msg_hdr_t *fpm_msg_next(fpm_msg_hdr_t *hdr, size_t *len) |
443b9937 | 199 | { |
d62a17ae | 200 | size_t msg_len; |
443b9937 | 201 | |
d62a17ae | 202 | msg_len = fpm_msg_len(hdr); |
443b9937 | 203 | |
d62a17ae | 204 | if (len) { |
205 | if (*len < msg_len) { | |
206 | assert(0); | |
207 | return NULL; | |
208 | } | |
209 | *len -= msg_len; | |
210 | } | |
443b9937 | 211 | |
d62a17ae | 212 | return (fpm_msg_hdr_t *)(((char *)hdr) + msg_len); |
443b9937 AS |
213 | } |
214 | ||
215 | /* | |
216 | * fpm_msg_hdr_ok | |
217 | * | |
2951a7a4 | 218 | * Returns true if a message header looks well-formed. |
443b9937 | 219 | */ |
d62a17ae | 220 | static inline int fpm_msg_hdr_ok(const fpm_msg_hdr_t *hdr) |
443b9937 | 221 | { |
d62a17ae | 222 | size_t msg_len; |
443b9937 | 223 | |
d62a17ae | 224 | if (hdr->msg_type == FPM_MSG_TYPE_NONE) |
225 | return 0; | |
443b9937 | 226 | |
d62a17ae | 227 | msg_len = fpm_msg_len(hdr); |
443b9937 | 228 | |
d62a17ae | 229 | if (msg_len < FPM_MSG_HDR_LEN || msg_len > FPM_MAX_MSG_LEN) |
230 | return 0; | |
443b9937 | 231 | |
d62a17ae | 232 | /* |
233 | * Netlink messages must be aligned properly. | |
234 | */ | |
235 | if (hdr->msg_type == FPM_MSG_TYPE_NETLINK | |
236 | && fpm_msg_align(msg_len) != msg_len) | |
237 | return 0; | |
443b9937 | 238 | |
d62a17ae | 239 | return 1; |
443b9937 AS |
240 | } |
241 | ||
242 | /* | |
243 | * fpm_msg_ok | |
244 | * | |
2951a7a4 | 245 | * Returns true if a message looks well-formed. |
443b9937 AS |
246 | * |
247 | * @param len The length in bytes from 'hdr' to the end of the buffer. | |
248 | */ | |
d62a17ae | 249 | static inline int fpm_msg_ok(const fpm_msg_hdr_t *hdr, size_t len) |
443b9937 | 250 | { |
d62a17ae | 251 | if (len < FPM_MSG_HDR_LEN) |
252 | return 0; | |
443b9937 | 253 | |
d62a17ae | 254 | if (!fpm_msg_hdr_ok(hdr)) |
255 | return 0; | |
443b9937 | 256 | |
d62a17ae | 257 | if (fpm_msg_len(hdr) > len) |
258 | return 0; | |
443b9937 | 259 | |
d62a17ae | 260 | return 1; |
443b9937 AS |
261 | } |
262 | ||
711ff0ba USK |
263 | // tcp maximum range |
264 | #define TCP_MAX_PORT 65535 | |
265 | ||
d62a17ae | 266 | // tcp minimum range |
711ff0ba USK |
267 | #define TCP_MIN_PORT 1 |
268 | ||
443b9937 | 269 | #endif /* _FPM_H */ |