summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_interface.h
blob: 47b70f8039403ee4824691778f5f7c3fa7f9f807 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OSPF Interface functions.
 * Copyright (C) 1999 Toshiaki Takada
 */

#ifndef _ZEBRA_OSPF_INTERFACE_H
#define _ZEBRA_OSPF_INTERFACE_H

#include "lib/bfd.h"
#include "qobj.h"
#include "hook.h"
#include "ospfd/ospf_packet.h"
#include "ospfd/ospf_spf.h"

#define IF_OSPF_IF_INFO(I) ((struct ospf_if_info *)((I)->info))
#define IF_DEF_PARAMS(I) (IF_OSPF_IF_INFO (I)->def_params)
#define IF_OIFS(I)  (IF_OSPF_IF_INFO (I)->oifs)
#define IF_OIFS_PARAMS(I) (IF_OSPF_IF_INFO (I)->params)

/* Despite the name, this macro probably is for specialist use only */
#define OSPF_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)

/* Test whether an OSPF interface parameter is set, generally, given some
 * existing ospf interface
 */
#define OSPF_IF_PARAM_IS_SET(O, P)                                             \
	(OSPF_IF_PARAM_CONFIGURED((O)->params, P)                              \
	 || OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P))

#define OSPF_IF_PARAM(O, P)                                                    \
	(OSPF_IF_PARAM_CONFIGURED((O)->params, P)                              \
		 ? (O)->params->P                                              \
		 : IF_DEF_PARAMS((O)->ifp)->P)

#define DECLARE_IF_PARAM(T, P)                                                 \
	T P;                                                                   \
	uint8_t P##__config : 1
#define UNSET_IF_PARAM(S, P) ((S)->P##__config) = 0
#define SET_IF_PARAM(S, P) ((S)->P##__config) = 1

struct ospf_if_params {
	DECLARE_IF_PARAM(uint32_t,
			 transmit_delay); /* Interface Transmisson Delay */
	DECLARE_IF_PARAM(uint32_t,
			 output_cost_cmd); /* Command Interface Output Cost */
	DECLARE_IF_PARAM(uint32_t,
			 retransmit_interval); /* Retransmission Interval */
	DECLARE_IF_PARAM(uint8_t, passive_interface); /* OSPF Interface is
							passive: no sending or
							receiving (no need to
							join multicast groups)
							*/
	DECLARE_IF_PARAM(uint8_t, priority); /* OSPF Interface priority */
	/* Enable OSPF on this interface with area if_area */
	DECLARE_IF_PARAM(struct in_addr, if_area);
	uint32_t if_area_id_fmt;

	DECLARE_IF_PARAM(uint8_t, type); /* type of interface */
#define OSPF_IF_ACTIVE                  0
#define OSPF_IF_PASSIVE		        1

#define OSPF_IF_PASSIVE_STATUS(O)                                              \
	(OSPF_IF_PARAM_CONFIGURED((O)->params, passive_interface)              \
		 ? (O)->params->passive_interface                              \
		 : (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp),          \
					     passive_interface)                \
			    ? IF_DEF_PARAMS((O)->ifp)->passive_interface       \
			    : (O)->ospf->passive_interface_default))

	DECLARE_IF_PARAM(uint32_t, v_hello); /* Hello Interval */
	DECLARE_IF_PARAM(uint32_t, v_wait);  /* Router Dead Interval */
	bool is_v_wait_set;                  /* Check for Dead Interval set */

	/* GR Hello Delay Interval */
	DECLARE_IF_PARAM(uint16_t, v_gr_hello_delay);

	/* MTU mismatch check (see RFC2328, chap 10.6) */
	DECLARE_IF_PARAM(uint8_t, mtu_ignore);

	/* Fast-Hellos */
	DECLARE_IF_PARAM(uint8_t, fast_hello);

	/* Prefix-Suppression */
	DECLARE_IF_PARAM(bool, prefix_suppression);

	/* Authentication data. */
	uint8_t auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1]; /* Simple password. */
	uint8_t auth_simple__config : 1;

	DECLARE_IF_PARAM(struct list *,
			 auth_crypt);     /* List of Auth cryptographic data. */
	DECLARE_IF_PARAM(int, auth_type); /* OSPF authentication type */

	/* Other, non-configuration state */
	uint32_t network_lsa_seqnum; /* Network LSA seqnum */

	/* BFD configuration */
	struct bfd_configuration {
		/** BFD session detection multiplier. */
		uint8_t detection_multiplier;
		/** BFD session minimum required receive interval. */
		uint32_t min_rx;
		/** BFD session minimum required transmission interval. */
		uint32_t min_tx;
		/** BFD profile. */
		char profile[BFD_PROFILE_NAME_LEN];
	} *bfd_config;

	/* MPLS LDP-IGP Sync configuration */
	struct ldp_sync_info *ldp_sync_info;

	/* point-to-point DMVPN configuration */
	uint8_t ptp_dmvpn;

	/* point-to-multipoint delayed reflooding configuration */
	bool p2mp_delay_reflood;

	/* Opaque LSA capability at interface level (see RFC5250) */
	DECLARE_IF_PARAM(bool, opaque_capable);
};

enum { MEMBER_ALLROUTERS = 0,
       MEMBER_DROUTERS,
       MEMBER_MAX,
};

struct ospf_if_info {
	struct ospf_if_params *def_params;
	struct route_table *params;
	struct route_table *oifs;
	unsigned int
		membership_counts[MEMBER_MAX]; /* multicast group refcnts */

	uint32_t curr_mtu;

	/* Per-interface write socket, configured via 'ospf' object */
	int oii_fd;
};

struct ospf_interface;

struct ospf_vl_data {
	struct in_addr vl_peer;	/* Router-ID of the peer */
	struct in_addr vl_area_id;     /* Transit area */
	int vl_area_id_fmt;	    /* Area ID format */
	struct ospf_interface *vl_oi;  /* Interface data structure */
	struct vertex_nexthop nexthop; /* Nexthop router and oi to use */
	struct in_addr peer_addr;      /* Address used to reach the peer */
	uint8_t flags;
};


#define OSPF_VL_MAX_COUNT 256
#define OSPF_VL_MTU	  1500

#define OSPF_VL_FLAG_APPROVED 0x01

struct crypt_key {
	uint8_t key_id;
	uint8_t auth_key[OSPF_AUTH_MD5_SIZE + 1];
};

/* OSPF interface structure. */
struct ospf_interface {
	/* This interface's parent ospf instance. */
	struct ospf *ospf;

	/* OSPF Area. */
	struct ospf_area *area;

	/* Position range in Router LSA */
	uint16_t lsa_pos_beg; /* inclusive, >= */
	uint16_t lsa_pos_end; /* exclusive, <  */

	/* Interface data from zebra. */
	struct interface *ifp;
	struct ospf_vl_data *vl_data; /* Data for Virtual Link */

	/* Packet send buffer. */
	struct ospf_fifo *obuf; /* Output queue */

	/* OSPF Network Type. */
	uint8_t type;

	/* point-to-point DMVPN configuration */
	uint8_t ptp_dmvpn;

	/* point-to-multipoint delayed reflooding */
	bool p2mp_delay_reflood;

	/* State of Interface State Machine. */
	uint8_t state;

	/* To which multicast groups do we currently belong? */
	uint8_t multicast_memberships;
#define OI_MEMBER_FLAG(M) (1 << (M))
#define OI_MEMBER_COUNT(O,M) (IF_OSPF_IF_INFO(oi->ifp)->membership_counts[(M)])
#define OI_MEMBER_CHECK(O, M)                                                  \
	(CHECK_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M)))
#define OI_MEMBER_JOINED(O, M)                                                 \
	do {                                                                   \
		SET_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M));       \
		IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]++;           \
	} while (0)
#define OI_MEMBER_LEFT(O, M)                                                   \
	do {                                                                   \
		UNSET_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M));     \
		IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]--;           \
	} while (0)

	struct prefix *address;      /* Interface prefix */
	struct connected *connected; /* Pointer to connected */

	/* Configured varables. */
	struct ospf_if_params *params;

	uint32_t crypt_seqnum; /* Cryptographic Sequence Number */
	uint32_t output_cost;  /* Acutual Interface Output Cost */

	/* Neighbor information. */
	struct route_table *nbrs;       /* OSPF Neighbor List */
	struct ospf_neighbor *nbr_self; /* Neighbor Self */
#define DR(I)			((I)->nbr_self->d_router)
#define BDR(I)			((I)->nbr_self->bd_router)
#define OPTIONS(I)		((I)->nbr_self->options)
#define PRIORITY(I)		((I)->nbr_self->priority)

	/* List of configured NBMA neighbor. */
	struct list *nbr_nbma;

	/* Graceful-Restart data. */
	struct {
		struct {
			uint16_t elapsed_seconds;
			struct event *t_grace_send;
		} hello_delay;
	} gr;

	/* self-originated LSAs. */
	struct ospf_lsa *network_lsa_self; /* network-LSA. */
	struct list *opaque_lsa_self;      /* Type-9 Opaque-LSAs */

	struct route_table *ls_upd_queue;

	struct list *ls_ack; /* Link State Acknowledgment list. */

	struct {
		struct list *ls_ack;
		struct in_addr dst;
	} ls_ack_direct;

	/* Timer values. */
	uint32_t v_ls_ack; /* Delayed Link State Acknowledgment */

	/* Threads. */
	struct event *t_hello;		 /* timer */
	struct event *t_wait;		 /* timer */
	struct event *t_ls_ack;		 /* timer */
	struct event *t_ls_ack_direct;	 /* event */
	struct event *t_ls_upd_event;	 /* event */
	struct event *t_opaque_lsa_self; /* Type-9 Opaque-LSAs */

	int on_write_q;

	/* Statistics fields. */
	uint32_t hello_in;     /* Hello message input count. */
	uint32_t hello_out;    /* Hello message output count. */
	uint32_t db_desc_in;   /* database desc. message input count. */
	uint32_t db_desc_out;  /* database desc. message output count. */
	uint32_t ls_req_in;    /* LS request message input count. */
	uint32_t ls_req_out;   /* LS request message output count. */
	uint32_t ls_upd_in;    /* LS update message input count. */
	uint32_t ls_upd_out;   /* LS update message output count. */
	uint32_t ls_ack_in;    /* LS Ack message input count. */
	uint32_t ls_ack_out;   /* LS Ack message output count. */
	uint32_t discarded;    /* discarded input count by error. */
	uint32_t state_change; /* Number of status change. */

	uint32_t full_nbrs;

	QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(ospf_interface);

/* Prototypes. */
extern char *ospf_if_name(struct ospf_interface *oi);
extern struct ospf_interface *
ospf_if_new(struct ospf *ospf, struct interface *ifp, struct prefix *p);
extern void ospf_if_cleanup(struct ospf_interface *oi);
extern void ospf_if_free(struct ospf_interface *oi);
extern int ospf_if_up(struct ospf_interface *oi);
extern int ospf_if_down(struct ospf_interface *oi);

extern int ospf_if_is_up(struct ospf_interface *oi);
extern struct ospf_interface *ospf_if_exists(struct ospf_interface *oi);
extern struct ospf_interface *ospf_if_lookup_by_lsa_pos(struct ospf_area *area,
							int lsa_pos);
extern struct ospf_interface *
ospf_if_lookup_by_local_addr(struct ospf *ospf, struct interface *ifp,
			     struct in_addr addr);
extern struct ospf_interface *ospf_if_lookup_by_prefix(struct ospf *ospf,
						       struct prefix_ipv4 *p);
extern struct ospf_interface *ospf_if_table_lookup(struct interface *ifp,
						   struct prefix *p);
extern struct ospf_interface *ospf_if_addr_local(struct in_addr addr);
extern struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf,
						     struct in_addr addr,
						     struct interface *ifp);
extern struct ospf_interface *ospf_if_is_configured(struct ospf *ospf,
						    struct in_addr *addr);

extern struct ospf_if_params *ospf_lookup_if_params(struct interface *ifp,
						    struct in_addr addr);
extern struct ospf_if_params *ospf_get_if_params(struct interface *ifp,
						 struct in_addr addr);
extern void ospf_free_if_params(struct interface *ifp, struct in_addr addr);
extern void ospf_if_update_params(struct interface *ifp, struct in_addr addr);

extern int ospf_if_new_hook(struct interface *ifp);
extern void ospf_if_init(void);
extern void ospf_if_stream_unset(struct ospf_interface *oi);
extern void ospf_if_reset_variables(struct ospf_interface *oi);
extern int ospf_if_is_enable(struct ospf_interface *oi);
extern int ospf_if_get_output_cost(struct ospf_interface *oi);
extern void ospf_if_recalculate_output_cost(struct interface *ifp);

/* Simulate down/up on the interface. */
extern void ospf_if_reset(struct interface *ifp);

extern struct ospf_interface *ospf_vl_new(struct ospf *ospf,
					  struct ospf_vl_data *vl_data);
extern struct ospf_vl_data *ospf_vl_data_new(struct ospf_area *area,
					     struct in_addr addr);
extern struct ospf_vl_data *
ospf_vl_lookup(struct ospf *ospf, struct ospf_area *area, struct in_addr addr);
extern int ospf_vl_count(struct ospf *ospf, struct ospf_area *area);
extern void ospf_vl_data_free(struct ospf_vl_data *vl_data);
extern void ospf_vl_add(struct ospf *ospf, struct ospf_vl_data *vl_data);
extern void ospf_vl_delete(struct ospf *ospf, struct ospf_vl_data *vl_data);
extern void ospf_vl_up_check(struct ospf_area *area, struct in_addr addr,
			     struct vertex *vertex);
extern void ospf_vl_unapprove(struct ospf *ospf);
extern void ospf_vl_shut_unapproved(struct ospf *ospf);
extern int ospf_full_virtual_nbrs(struct ospf_area *area);
extern int ospf_vls_in_area(struct ospf_area *area);

extern struct crypt_key *ospf_crypt_key_lookup(struct list *list,
					       uint8_t key_id);
extern struct crypt_key *ospf_crypt_key_new(void);
extern void ospf_crypt_key_add(struct list *list, struct crypt_key *key);
extern int ospf_crypt_key_delete(struct list *list, uint8_t key_id);
extern uint8_t ospf_default_iftype(struct interface *ifp);
extern int ospf_interface_neighbor_count(struct ospf_interface *oi);

/* Set all multicast memberships appropriately based on the type and
   state of the interface. */
extern void ospf_if_set_multicast(struct ospf_interface *oi);

extern void ospf_if_interface(struct interface *ifp);

extern uint32_t ospf_if_count_area_params(struct interface *ifp);
extern void ospf_reset_hello_timer(struct interface *ifp, struct in_addr addr,
				   bool is_addr);

extern void ospf_interface_fifo_flush(struct ospf_interface *oi);
DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd));

DECLARE_HOOK(ospf_if_update, (struct interface * ifp), (ifp));
DECLARE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp));

#endif /* _ZEBRA_OSPF_INTERFACE_H */