summaryrefslogtreecommitdiffstats
path: root/pimd/pim_vxlan.h
blob: 1a7e9dcf1bd48eda54360f840d772d126ffe53a8 (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
/* PIM support for VxLAN BUM flooding
 *
 * Copyright (C) 2019 Cumulus Networks, Inc.
 *
 * This file is part of FRR.
 *
 * FRR is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * FRR is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#ifndef PIM_VXLAN_H
#define PIM_VXLAN_H

#include "pim_instance.h"

/* global timer used for miscellaneous staggered processing */
#define PIM_VXLAN_WORK_TIME 1
/* number of SG entries processed at one shot */
#define PIM_VXLAN_WORK_MAX 500
/* frequency of periodic NULL registers */
#define PIM_VXLAN_NULL_REG_INTERVAL 60 /* seconds */

#define vxlan_mlag (vxlan_info.mlag)

enum pim_vxlan_sg_flags {
	PIM_VXLAN_SGF_NONE = 0,
	PIM_VXLAN_SGF_DEL_IN_PROG = (1 << 0),
	PIM_VXLAN_SGF_OIF_INSTALLED = (1 << 1)
};

struct pim_vxlan_sg {
	struct pim_instance *pim;

	/* key */
	pim_sgaddr sg;
	char sg_str[PIM_SG_LEN];

	enum pim_vxlan_sg_flags flags;
	struct pim_upstream *up;
	struct listnode *work_node; /* to pim_vxlan.work_list */

	/* termination info (only applicable to termination XG mroutes)
	 * term_if - termination device ipmr-lo is added to the OIL
	 * as local/IGMP membership to allow termination of vxlan traffic
	 */
	struct interface *term_oif;

	/* origination info
	 * iif - lo/vrf or peerlink (on MLAG setups)
	 * peerlink_oif - added to the OIL to send encapsulated BUM traffic to
	 * the MLAG peer switch
	 */
	struct interface *iif;
	/* on a MLAG setup the peerlink is added as a static OIF */
	struct interface *orig_oif;
};

enum pim_vxlan_mlag_flags {
	PIM_VXLAN_MLAGF_NONE = 0,
	PIM_VXLAN_MLAGF_ENABLED = (1 << 0),
	PIM_VXLAN_MLAGF_DO_REG = (1 << 1)
};

struct pim_vxlan_mlag {
	enum pim_vxlan_mlag_flags flags;
	/* XXX - remove this variable from here */
	int role;
	bool peer_state;
	/* routed interface setup on top of MLAG peerlink */
	struct interface *peerlink_rif;
	struct in_addr reg_addr;
};

enum pim_vxlan_flags {
	PIM_VXLANF_NONE = 0,
	PIM_VXLANF_WORK_INITED = (1 << 0)
};

struct pim_vxlan {
	enum pim_vxlan_flags flags;

	struct thread *work_timer;
	struct list *work_list;
	struct listnode *next_work;
	int max_work_cnt;

	struct pim_vxlan_mlag mlag;
};

/* zebra adds-
 * 1. one (S, G) entry where S=local-VTEP-IP and G==BUM-mcast-grp for
 * each BUM MDT. This is the origination entry.
 * 2. and one (*, G) entry each MDT. This is the termination place holder.
 *
 * Note: This doesn't mean that only (*, G) mroutes are used for tunnel
 * termination. (S, G) mroutes with ipmr-lo in the OIL can also be
 * used for tunnel termiation if SPT switchover happens; however such
 * SG entries are created by traffic and will NOT be a part of the vxlan SG
 * database.
 */
static inline bool pim_vxlan_is_orig_mroute(struct pim_vxlan_sg *vxlan_sg)
{
	return !pim_addr_is_any(vxlan_sg->sg.src);
}

static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)
{
	return !pim_addr_is_any(up->sg.src) &&
	       up->rpf.source_nexthop.interface &&
	       if_is_loopback(up->rpf.source_nexthop.interface);
}

static inline bool pim_vxlan_is_term_dev_cfg(struct pim_instance *pim,
			struct interface *ifp)
{
	return pim->vxlan.term_if_cfg == ifp;
}

extern struct pim_vxlan *pim_vxlan_p;
extern struct pim_vxlan_sg *pim_vxlan_sg_find(struct pim_instance *pim,
					      pim_sgaddr *sg);
extern struct pim_vxlan_sg *pim_vxlan_sg_add(struct pim_instance *pim,
					     pim_sgaddr *sg);
extern void pim_vxlan_sg_del(struct pim_instance *pim, pim_sgaddr *sg);
extern void pim_vxlan_update_sg_reg_state(struct pim_instance *pim,
		struct pim_upstream *up, bool reg_join);
extern struct pim_interface *pim_vxlan_get_term_ifp(struct pim_instance *pim);
extern void pim_vxlan_add_vif(struct interface *ifp);
extern void pim_vxlan_del_vif(struct interface *ifp);
extern void pim_vxlan_add_term_dev(struct pim_instance *pim,
		struct interface *ifp);
extern void pim_vxlan_del_term_dev(struct pim_instance *pim);
extern bool pim_vxlan_get_register_src(struct pim_instance *pim,
		struct pim_upstream *up, struct in_addr *src_p);
extern void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
				struct interface *peerlink_rif,
				struct in_addr *reg_addr);
extern bool pim_vxlan_do_mlag_reg(void);
extern void pim_vxlan_inherit_mlag_flags(struct pim_instance *pim,
		struct pim_upstream *up, bool inherit);

/* Shutdown of PIM stop the thread */
extern void pim_vxlan_terminate(void);
#endif /* PIM_VXLAN_H */