Line data Source code
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 5783 : static inline bool pim_addr_is_any(pim_addr addr)
95 : {
96 5783 : pim_addr zero = {};
97 :
98 5783 : return memcmp(&addr, &zero, sizeof(zero)) == 0;
99 : }
100 :
101 5509 : static inline int pim_addr_cmp(pim_addr a, pim_addr b)
102 : {
103 5251 : return memcmp(&a, &b, sizeof(a));
104 : }
105 :
106 1212 : static inline void pim_addr_to_prefix(union pimprefixptr out, pim_addr in)
107 : {
108 1212 : out.p->family = PIM_AF;
109 1212 : out.p->prefixlen = PIM_MAX_BITLEN;
110 1212 : memcpy(out.p->u.val, &in, sizeof(in));
111 : }
112 :
113 3998 : static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in)
114 : {
115 3998 : pim_addr ret;
116 :
117 3564 : if (in.p->family != PIM_AF)
118 : return PIMADDR_ANY;
119 :
120 2492 : memcpy(&ret, in.p->u.val, sizeof(ret));
121 2277 : 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 215 : static inline bool pim_addr_ssm(const pim_addr addr)
135 : {
136 215 : 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 3120 : 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 3120 : return memcmp(&a, &b, sizeof(a));
151 : }
152 :
153 63 : static inline uint32_t pim_sgaddr_hash(const pim_sgaddr a, uint32_t initval)
154 : {
155 63 : 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 */
|