]>
git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_oil.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2008 Everton da Silva Marques
12 #include "pim_mroute.h"
15 * Where did we get this (S,G) from?
17 * GM - Learned from IGMP/MLD
18 * PIM - Learned from PIM
19 * SOURCE - Learned from Source multicast packet received
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)
30 /* OIF is present in the OIL but must not be used for forwarding traffic */
31 #define PIM_OIF_FLAG_MUTE (1 << 4)
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
37 * Don't come running to me if this assumption is bad,
40 #define PIM_OIF_PIM_REGISTER_VIF 0
41 #define PIM_MAX_USABLE_VIFS (MAXVIFS - 1)
43 struct channel_counts
{
44 unsigned long long lastused
;
45 unsigned long origpktcnt
;
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
;
57 qpim_channel_oil_list holds a list of struct channel_oil.
59 Each channel_oil.oil is used to control an (S,G) entry in the Kernel
60 Multicast Forwarding Cache.
62 There is a case when we create a channel_oil but don't install in the kernel
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).
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).
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.
81 PREDECL_RBTREE_UNIQ(rb_pim_oil
);
84 struct pim_instance
*pim
;
86 struct rb_pim_oil_item oil_rb
;
94 int oil_inherited_rescan
;
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
;
105 static inline pim_addr
*oil_origin(struct channel_oil
*c_oil
)
107 return &c_oil
->oil
.mfcc_origin
;
110 static inline pim_addr
*oil_mcastgrp(struct channel_oil
*c_oil
)
112 return &c_oil
->oil
.mfcc_mcastgrp
;
115 static inline vifi_t
*oil_parent(struct channel_oil
*c_oil
)
117 return &c_oil
->oil
.mfcc_parent
;
120 static inline bool oil_if_has(struct channel_oil
*c_oil
, vifi_t ifi
)
122 return !!c_oil
->oil
.mfcc_ttls
[ifi
];
125 static inline void oil_if_set(struct channel_oil
*c_oil
, vifi_t ifi
, uint8_t set
)
127 c_oil
->oil
.mfcc_ttls
[ifi
] = set
;
130 static inline int oil_if_cmp(struct mfcctl
*oil1
, struct mfcctl
*oil2
)
132 return memcmp(&oil1
->mfcc_ttls
[0], &oil2
->mfcc_ttls
[0],
133 sizeof(oil1
->mfcc_ttls
));
136 static inline pim_addr
*oil_origin(struct channel_oil
*c_oil
)
138 return &c_oil
->oil
.mf6cc_origin
.sin6_addr
;
141 static inline pim_addr
*oil_mcastgrp(struct channel_oil
*c_oil
)
143 return &c_oil
->oil
.mf6cc_mcastgrp
.sin6_addr
;
146 static inline mifi_t
*oil_parent(struct channel_oil
*c_oil
)
148 return &c_oil
->oil
.mf6cc_parent
;
151 static inline bool oil_if_has(struct channel_oil
*c_oil
, mifi_t ifi
)
153 return !!IF_ISSET(ifi
, &c_oil
->oil
.mf6cc_ifset
);
156 static inline void oil_if_set(struct channel_oil
*c_oil
, mifi_t ifi
,
160 IF_SET(ifi
, &c_oil
->oil
.mf6cc_ifset
);
162 IF_CLR(ifi
, &c_oil
->oil
.mf6cc_ifset
);
165 static inline int oil_if_cmp(struct mf6cctl
*oil1
, struct mf6cctl
*oil2
)
167 return memcmp(&oil1
->mf6cc_ifset
, &oil2
->mf6cc_ifset
,
168 sizeof(oil1
->mf6cc_ifset
));
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
);
177 void pim_oil_init(struct pim_instance
*pim
);
178 void pim_oil_terminate(struct pim_instance
*pim
);
180 void pim_channel_oil_free(struct channel_oil
*c_oil
);
181 struct channel_oil
*pim_find_channel_oil(struct pim_instance
*pim
,
183 struct channel_oil
*pim_channel_oil_add(struct pim_instance
*pim
,
184 pim_sgaddr
*sg
, const char *name
);
185 void pim_clear_nocache_state(struct pim_interface
*pim_ifp
);
186 struct channel_oil
*pim_channel_oil_del(struct channel_oil
*c_oil
,
189 int pim_channel_add_oif(struct channel_oil
*c_oil
, struct interface
*oif
,
190 uint32_t proto_mask
, const char *caller
);
191 int pim_channel_del_oif(struct channel_oil
*c_oil
, struct interface
*oif
,
192 uint32_t proto_mask
, const char *caller
);
194 int pim_channel_oil_empty(struct channel_oil
*c_oil
);
196 char *pim_channel_oil_dump(struct channel_oil
*c_oil
, char *buf
, size_t size
);
198 void pim_channel_update_oif_mute(struct channel_oil
*c_oil
,
199 struct pim_interface
*pim_ifp
);
201 void pim_channel_oil_upstream_deref(struct channel_oil
*c_oil
);
202 void pim_channel_del_inherited_oif(struct channel_oil
*c_oil
,
203 struct interface
*oif
, const char *caller
);
205 #endif /* PIM_OIL_H */