]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_addr.h
bgpd: fix the IGP metric for best path selection on VPN import
[mirror_frr.git] / pimd / pim_addr.h
1 /*
2 * PIM address generalizations
3 * Copyright (C) 2022 David Lamparter for NetDEF, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #ifndef _PIMD_PIM_ADDR_H
21 #define _PIMD_PIM_ADDR_H
22
23 #include "jhash.h"
24 #include "prefix.h"
25
26 /* clang-format off */
27
28 #if PIM_IPV == 4
29 typedef struct in_addr pim_addr;
30
31 #define PIM_ADDRSTRLEN INET_ADDRSTRLEN
32 #define PIM_AF AF_INET
33 #define PIM_AFI AFI_IP
34 #define PIM_PROTO_REG IPPROTO_RAW
35 #define PIM_IPADDR IPADDR_V4
36 #define ipaddr_pim ipaddr_v4
37 #define PIM_MAX_BITLEN IPV4_MAX_BITLEN
38 #define PIM_AF_NAME "ip"
39 #define PIM_AF_DBG "pim"
40 #define GM_AF_DBG "igmp"
41 #define PIM_MROUTE_DBG "mroute"
42 #define PIMREG "pimreg"
43 #define GM "IGMP"
44
45 #define PIM_ADDR_FUNCNAME(name) ipv4_##name
46
47 union pimprefixptr {
48 prefixtype(pimprefixptr, struct prefix, p)
49 prefixtype(pimprefixptr, struct prefix_ipv4, p4)
50 } TRANSPARENT_UNION;
51
52 union pimprefixconstptr {
53 prefixtype(pimprefixconstptr, const struct prefix, p)
54 prefixtype(pimprefixconstptr, const struct prefix_ipv4, p4)
55 } TRANSPARENT_UNION;
56
57 #else
58 typedef struct in6_addr pim_addr;
59
60 #define PIM_ADDRSTRLEN INET6_ADDRSTRLEN
61 #define PIM_AF AF_INET6
62 #define PIM_AFI AFI_IP6
63 #define PIM_PROTO_REG IPPROTO_PIM
64 #define PIM_IPADDR IPADDR_V6
65 #define ipaddr_pim ipaddr_v6
66 #define PIM_MAX_BITLEN IPV6_MAX_BITLEN
67 #define PIM_AF_NAME "ipv6"
68 #define PIM_AF_DBG "pimv6"
69 #define GM_AF_DBG "mld"
70 #define PIM_MROUTE_DBG "mroute6"
71 #define PIMREG "pim6reg"
72 #define GM "MLD"
73
74 #define PIM_ADDR_FUNCNAME(name) ipv6_##name
75
76 union pimprefixptr {
77 prefixtype(pimprefixptr, struct prefix, p)
78 prefixtype(pimprefixptr, struct prefix_ipv6, p6)
79 } TRANSPARENT_UNION;
80
81 union pimprefixconstptr {
82 prefixtype(pimprefixconstptr, const struct prefix, p)
83 prefixtype(pimprefixconstptr, const struct prefix_ipv6, p6)
84 } TRANSPARENT_UNION;
85 #endif
86
87 /* for assignment/initialization (C99 compound literal)
88 * named PIMADDR_ANY (not PIM_ADDR_ANY) to match INADDR_ANY
89 */
90 #define PIMADDR_ANY (pim_addr){ }
91
92 /* clang-format on */
93
94 static inline bool pim_addr_is_any(pim_addr addr)
95 {
96 pim_addr zero = {};
97
98 return memcmp(&addr, &zero, sizeof(zero)) == 0;
99 }
100
101 static inline int pim_addr_cmp(pim_addr a, pim_addr b)
102 {
103 return memcmp(&a, &b, sizeof(a));
104 }
105
106 static inline void pim_addr_to_prefix(union pimprefixptr out, pim_addr in)
107 {
108 out.p->family = PIM_AF;
109 out.p->prefixlen = PIM_MAX_BITLEN;
110 memcpy(out.p->u.val, &in, sizeof(in));
111 }
112
113 static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in)
114 {
115 pim_addr ret;
116
117 if (in.p->family != PIM_AF)
118 return PIMADDR_ANY;
119
120 memcpy(&ret, in.p->u.val, sizeof(ret));
121 return ret;
122 }
123
124 static inline uint8_t pim_addr_scope(const pim_addr addr)
125 {
126 return PIM_ADDR_FUNCNAME(mcast_scope)(&addr);
127 }
128
129 static inline bool pim_addr_nofwd(const pim_addr addr)
130 {
131 return PIM_ADDR_FUNCNAME(mcast_nofwd)(&addr);
132 }
133
134 static inline bool pim_addr_ssm(const pim_addr addr)
135 {
136 return PIM_ADDR_FUNCNAME(mcast_ssm)(&addr);
137 }
138
139 /* don't use this struct directly, use the pim_sgaddr typedef */
140 struct _pim_sgaddr {
141 pim_addr grp;
142 pim_addr src;
143 };
144
145 typedef struct _pim_sgaddr pim_sgaddr;
146
147 static inline int pim_sgaddr_cmp(const pim_sgaddr a, const pim_sgaddr b)
148 {
149 /* memcmp over the entire struct = memcmp(grp) + memcmp(src) */
150 return memcmp(&a, &b, sizeof(a));
151 }
152
153 static inline uint32_t pim_sgaddr_hash(const pim_sgaddr a, uint32_t initval)
154 {
155 return jhash2((uint32_t *)&a, sizeof(a) / sizeof(uint32_t), initval);
156 }
157
158 #ifdef _FRR_ATTRIBUTE_PRINTFRR
159 #pragma FRR printfrr_ext "%pPA" (pim_addr *)
160 #pragma FRR printfrr_ext "%pSG" (pim_sgaddr *)
161 #endif
162
163 /*
164 * There is no pim_sgaddr2str(). This is intentional. Instead, use:
165 * snprintfrr(buf, sizeof(buf), "%pPA", sgaddr)
166 * (and note that snprintfrr is implicit for vty_out and zlog_*)
167 */
168
169 #endif /* _PIMD_PIM_ADDR_H */