]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_oil.h
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pimd / pim_oil.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * PIM for Quagga
4 * Copyright (C) 2008 Everton da Silva Marques
5 */
6
7 #ifndef PIM_OIL_H
8 #define PIM_OIL_H
9
10 struct pim_interface;
11
12 #include "pim_mroute.h"
13
14 /*
15 * Where did we get this (S,G) from?
16 *
17 * GM - Learned from IGMP/MLD
18 * PIM - Learned from PIM
19 * SOURCE - Learned from Source multicast packet received
20 * STAR - Inherited
21 */
22 #define PIM_OIF_FLAG_PROTO_GM (1 << 0)
23 #define PIM_OIF_FLAG_PROTO_PIM (1 << 1)
24 #define PIM_OIF_FLAG_PROTO_STAR (1 << 2)
25 #define PIM_OIF_FLAG_PROTO_VXLAN (1 << 3)
26 #define PIM_OIF_FLAG_PROTO_ANY \
27 (PIM_OIF_FLAG_PROTO_GM | PIM_OIF_FLAG_PROTO_PIM | \
28 PIM_OIF_FLAG_PROTO_STAR | PIM_OIF_FLAG_PROTO_VXLAN)
29
30 /* OIF is present in the OIL but must not be used for forwarding traffic */
31 #define PIM_OIF_FLAG_MUTE (1 << 4)
32 /*
33 * We need a pimreg vif id from the kernel.
34 * Since ifindex == vif id for most cases and the number
35 * of expected interfaces is at most 100, using MAXVIFS -1
36 * is probably ok.
37 * Don't come running to me if this assumption is bad,
38 * fix it.
39 */
40 #define PIM_OIF_PIM_REGISTER_VIF 0
41 #define PIM_MAX_USABLE_VIFS (MAXVIFS - 1)
42
43 struct channel_counts {
44 unsigned long long lastused;
45 unsigned long origpktcnt;
46 unsigned long pktcnt;
47 unsigned long oldpktcnt;
48 unsigned long origbytecnt;
49 unsigned long bytecnt;
50 unsigned long oldbytecnt;
51 unsigned long origwrong_if;
52 unsigned long wrong_if;
53 unsigned long oldwrong_if;
54 };
55
56 /*
57 qpim_channel_oil_list holds a list of struct channel_oil.
58
59 Each channel_oil.oil is used to control an (S,G) entry in the Kernel
60 Multicast Forwarding Cache.
61
62 There is a case when we create a channel_oil but don't install in the kernel
63
64 Case where (S, G) entry not installed in the kernel:
65 FRR receives IGMP/PIM (*, G) join and RP is not configured or
66 not-reachable, then create a channel_oil for the group G with the incoming
67 interface(channel_oil.oil.mfcc_parent) as invalid i.e "MAXVIF" and populate
68 the outgoing interface where join is received. Keep this entry in the stack,
69 but don't install in the kernel(channel_oil.installed = 0).
70
71 Case where (S, G) entry installed in the kernel:
72 When RP is configured and is reachable for the group G, and receiving a
73 join if channel_oil is already present then populate the incoming interface
74 and install the entry in the kernel, if channel_oil not present, then create
75 a new_channel oil(channel_oil.installed = 1).
76
77 is_valid: indicate if this entry is valid to get installed in kernel.
78 installed: indicate if this entry is installed in the kernel.
79
80 */
81 PREDECL_RBTREE_UNIQ(rb_pim_oil);
82
83 struct channel_oil {
84 struct pim_instance *pim;
85
86 struct rb_pim_oil_item oil_rb;
87
88 #if PIM_IPV == 4
89 struct mfcctl oil;
90 #else
91 struct mf6cctl oil;
92 #endif
93 int installed;
94 int oil_inherited_rescan;
95 int oil_size;
96 int oil_ref_count;
97 time_t oif_creation[MAXVIFS];
98 uint32_t oif_flags[MAXVIFS];
99 struct channel_counts cc;
100 struct pim_upstream *up;
101 time_t mroute_creation;
102 };
103
104 #if PIM_IPV == 4
105 static inline pim_addr *oil_origin(struct channel_oil *c_oil)
106 {
107 return &c_oil->oil.mfcc_origin;
108 }
109
110 static inline pim_addr *oil_mcastgrp(struct channel_oil *c_oil)
111 {
112 return &c_oil->oil.mfcc_mcastgrp;
113 }
114
115 static inline vifi_t *oil_parent(struct channel_oil *c_oil)
116 {
117 return &c_oil->oil.mfcc_parent;
118 }
119
120 static inline bool oil_if_has(struct channel_oil *c_oil, vifi_t ifi)
121 {
122 return !!c_oil->oil.mfcc_ttls[ifi];
123 }
124
125 static inline void oil_if_set(struct channel_oil *c_oil, vifi_t ifi, uint8_t set)
126 {
127 c_oil->oil.mfcc_ttls[ifi] = set;
128 }
129
130 static inline int oil_if_cmp(struct mfcctl *oil1, struct mfcctl *oil2)
131 {
132 return memcmp(&oil1->mfcc_ttls[0], &oil2->mfcc_ttls[0],
133 sizeof(oil1->mfcc_ttls));
134 }
135 #else
136 static inline pim_addr *oil_origin(struct channel_oil *c_oil)
137 {
138 return &c_oil->oil.mf6cc_origin.sin6_addr;
139 }
140
141 static inline pim_addr *oil_mcastgrp(struct channel_oil *c_oil)
142 {
143 return &c_oil->oil.mf6cc_mcastgrp.sin6_addr;
144 }
145
146 static inline mifi_t *oil_parent(struct channel_oil *c_oil)
147 {
148 return &c_oil->oil.mf6cc_parent;
149 }
150
151 static inline bool oil_if_has(struct channel_oil *c_oil, mifi_t ifi)
152 {
153 return !!IF_ISSET(ifi, &c_oil->oil.mf6cc_ifset);
154 }
155
156 static inline void oil_if_set(struct channel_oil *c_oil, mifi_t ifi,
157 uint8_t set)
158 {
159 if (set)
160 IF_SET(ifi, &c_oil->oil.mf6cc_ifset);
161 else
162 IF_CLR(ifi, &c_oil->oil.mf6cc_ifset);
163 }
164
165 static inline int oil_if_cmp(struct mf6cctl *oil1, struct mf6cctl *oil2)
166 {
167 return memcmp(&oil1->mf6cc_ifset, &oil2->mf6cc_ifset,
168 sizeof(oil1->mf6cc_ifset));
169 }
170 #endif
171
172 extern int pim_channel_oil_compare(const struct channel_oil *c1,
173 const struct channel_oil *c2);
174 DECLARE_RBTREE_UNIQ(rb_pim_oil, struct channel_oil, oil_rb,
175 pim_channel_oil_compare);
176
177 void pim_oil_init(struct pim_instance *pim);
178 void pim_oil_terminate(struct pim_instance *pim);
179
180 void pim_channel_oil_free(struct channel_oil *c_oil);
181 struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
182 pim_sgaddr *sg);
183 struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
184 pim_sgaddr *sg, const char *name);
185 struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
186 const char *name);
187
188 int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
189 uint32_t proto_mask, const char *caller);
190 int pim_channel_del_oif(struct channel_oil *c_oil, struct interface *oif,
191 uint32_t proto_mask, const char *caller);
192
193 int pim_channel_oil_empty(struct channel_oil *c_oil);
194
195 char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size);
196
197 void pim_channel_update_oif_mute(struct channel_oil *c_oil,
198 struct pim_interface *pim_ifp);
199
200 void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
201 void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
202 struct interface *oif, const char *caller);
203
204 #endif /* PIM_OIL_H */