Line data Source code
1 : /*
2 : * Public definitions pertaining to the Forwarding Plane Manager component.
3 : *
4 : * Permission is granted to use, copy, modify and/or distribute this
5 : * software under either one of the licenses below.
6 : *
7 : * Note that if you use other files from the Quagga tree directly or
8 : * indirectly, then the licenses in those files still apply.
9 : *
10 : * Please retain both licenses below when modifying this code in the
11 : * Quagga tree.
12 : *
13 : * Copyright (C) 2012 by Open Source Routing.
14 : * Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
15 : */
16 :
17 : /*
18 : * License Option 1: GPL
19 : *
20 : * This program is free software; you can redistribute it and/or modify it
21 : * under the terms of the GNU General Public License as published by the Free
22 : * Software Foundation; either version 2 of the License, or (at your option)
23 : * any later version.
24 : *
25 : * This program is distributed in the hope that it will be useful,but WITHOUT
26 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
28 : * more details.
29 : *
30 : * You should have received a copy of the GNU General Public License along
31 : * with this program; if not, write to the Free Software Foundation, Inc.,
32 : * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 : */
34 :
35 : /*
36 : * License Option 2: ISC License
37 : *
38 : * Permission to use, copy, modify, and/or distribute this software
39 : * for any purpose with or without fee is hereby granted, provided
40 : * that the above copyright notice and this permission notice appear
41 : * in all copies.
42 : *
43 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
44 : * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
45 : * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
46 : * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
47 : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
48 : * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
49 : * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
50 : * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 : */
52 :
53 : #ifndef _FPM_H
54 : #define _FPM_H
55 :
56 : /*
57 : * The Forwarding Plane Manager (FPM) is an optional component that
58 : * may be used in scenarios where the router has a forwarding path
59 : * that is distinct from the kernel, commonly a hardware-based fast
60 : * path. It is responsible for programming forwarding information
61 : * (such as routes and nexthops) in the fast path.
62 : *
63 : * In Quagga, the Routing Information Base is maintained in the
64 : * 'zebra' infrastructure daemon. Routing protocols communicate their
65 : * best routes to zebra, and zebra computes the best route across
66 : * protocols for each prefix. This latter information comprises the
67 : * bulk of the Forwarding Information Base.
68 : *
69 : * This header file defines a point-to-point interface using which
70 : * zebra can update the FPM about changes in routes. The communication
71 : * takes place over a stream socket. The FPM listens on a well-known
72 : * TCP port, and zebra initiates the connection.
73 : *
74 : * All messages sent over the connection start with a short FPM
75 : * header, fpm_msg_hdr_t. In the case of route add/delete messages,
76 : * the header is followed by a netlink message. Zebra should send a
77 : * complete copy of the forwarding table(s) to the FPM, including
78 : * routes that it may have picked up from the kernel.
79 : *
80 : * The FPM interface uses replace semantics. That is, if a 'route add'
81 : * message for a prefix is followed by another 'route add' message, the
82 : * information in the second message is complete by itself, and replaces
83 : * the information sent in the first message.
84 : *
85 : * If the connection to the FPM goes down for some reason, the client
86 : * (zebra) should send the FPM a complete copy of the forwarding
87 : * table(s) when it reconnects.
88 : */
89 :
90 : #define FPM_DEFAULT_PORT 2620
91 :
92 : /*
93 : * Largest message that can be sent to or received from the FPM.
94 : */
95 : #define FPM_MAX_MSG_LEN 4096
96 :
97 : /*
98 : * Header that precedes each fpm message to/from the FPM.
99 : */
100 : typedef struct fpm_msg_hdr_t_
101 : {
102 : /*
103 : * Protocol version.
104 : */
105 : uint8_t version;
106 :
107 : /*
108 : * Type of message, see below.
109 : */
110 : uint8_t msg_type;
111 :
112 : /*
113 : * Length of entire message, including the header, in network byte
114 : * order.
115 : *
116 : * Note that msg_len is rounded up to make sure that message is at
117 : * the desired alignment. This means that some payloads may need
118 : * padding at the end.
119 : */
120 : uint16_t msg_len;
121 : } fpm_msg_hdr_t;
122 :
123 : /*
124 : * The current version of the FPM protocol is 1.
125 : */
126 : #define FPM_PROTO_VERSION 1
127 :
128 : typedef enum fpm_msg_type_e_ {
129 : FPM_MSG_TYPE_NONE = 0,
130 :
131 : /*
132 : * Indicates that the payload is a completely formed netlink
133 : * message.
134 : */
135 : FPM_MSG_TYPE_NETLINK = 1,
136 : } fpm_msg_type_e;
137 :
138 : /*
139 : * The FPM message header is aligned to the same boundary as netlink
140 : * messages (4). This means that a netlink message does not need
141 : * padding when encapsulated in an FPM message.
142 : */
143 : #define FPM_MSG_ALIGNTO 4
144 :
145 : /*
146 : * fpm_msg_align
147 : *
148 : * Round up the given length to the desired alignment.
149 : */
150 : static inline size_t
151 0 : fpm_msg_align (size_t len)
152 : {
153 0 : return (len + FPM_MSG_ALIGNTO - 1) & ~(FPM_MSG_ALIGNTO - 1);
154 : }
155 :
156 : /*
157 : * The (rounded up) size of the FPM message header. This ensures that
158 : * the message payload always starts at an aligned address.
159 : */
160 : #define FPM_MSG_HDR_LEN (fpm_msg_align (sizeof (fpm_msg_hdr_t)))
161 :
162 : /*
163 : * fpm_data_len_to_msg_len
164 : *
165 : * The length value that should be placed in the msg_len field of the
166 : * header for a *payload* of size 'data_len'.
167 : */
168 : static inline size_t
169 0 : fpm_data_len_to_msg_len (size_t data_len)
170 : {
171 0 : return fpm_msg_align (data_len) + FPM_MSG_HDR_LEN;
172 : }
173 :
174 : /*
175 : * fpm_msg_data
176 : *
177 : * Pointer to the payload of the given fpm header.
178 : */
179 : static inline void *
180 0 : fpm_msg_data (fpm_msg_hdr_t *hdr)
181 : {
182 0 : return ((char*) hdr) + FPM_MSG_HDR_LEN;
183 : }
184 :
185 : /*
186 : * fpm_msg_len
187 : */
188 : static inline size_t
189 0 : fpm_msg_len (const fpm_msg_hdr_t *hdr)
190 : {
191 0 : return ntohs (hdr->msg_len);
192 : }
193 :
194 : /*
195 : * fpm_msg_data_len
196 : */
197 : static inline size_t
198 : fpm_msg_data_len (const fpm_msg_hdr_t *hdr)
199 : {
200 : return (fpm_msg_len (hdr) - FPM_MSG_HDR_LEN);
201 : }
202 :
203 : /*
204 : * fpm_msg_next
205 : *
206 : * Move to the next message in a buffer.
207 : */
208 : static inline fpm_msg_hdr_t *
209 : fpm_msg_next (fpm_msg_hdr_t *hdr, size_t *len)
210 : {
211 : size_t msg_len;
212 :
213 : msg_len = fpm_msg_len (hdr);
214 :
215 : if (len) {
216 : if (*len < msg_len)
217 : {
218 : assert(0);
219 : return NULL;
220 : }
221 : *len -= msg_len;
222 : }
223 :
224 : return (fpm_msg_hdr_t *) (((char*) hdr) + msg_len);
225 : }
226 :
227 : /*
228 : * fpm_msg_hdr_ok
229 : *
230 : * Returns TRUE if a message header looks well-formed.
231 : */
232 : static inline int
233 0 : fpm_msg_hdr_ok (const fpm_msg_hdr_t *hdr)
234 : {
235 : size_t msg_len;
236 :
237 0 : if (hdr->msg_type == FPM_MSG_TYPE_NONE)
238 0 : return 0;
239 :
240 0 : msg_len = fpm_msg_len (hdr);
241 :
242 0 : if (msg_len < FPM_MSG_HDR_LEN || msg_len > FPM_MAX_MSG_LEN)
243 0 : return 0;
244 :
245 0 : if (fpm_msg_align (msg_len) != msg_len)
246 0 : return 0;
247 :
248 0 : return 1;
249 : }
250 :
251 : /*
252 : * fpm_msg_ok
253 : *
254 : * Returns TRUE if a message looks well-formed.
255 : *
256 : * @param len The length in bytes from 'hdr' to the end of the buffer.
257 : */
258 : static inline int
259 : fpm_msg_ok (const fpm_msg_hdr_t *hdr, size_t len)
260 : {
261 : if (len < FPM_MSG_HDR_LEN)
262 : return 0;
263 :
264 : if (!fpm_msg_hdr_ok (hdr))
265 : return 0;
266 :
267 : if (fpm_msg_len (hdr) > len)
268 : return 0;
269 :
270 : return 1;
271 : }
272 :
273 : #endif /* _FPM_H */
|