]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_addr.h
pim6d: Completing "ipv6 mld" command.
[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_IPADDR IPADDR_V4
35 #define ipaddr_pim ipaddr_v4
36 #define PIM_MAX_BITLEN IPV4_MAX_BITLEN
37 #define PIM_AF_NAME "ip"
38 #define PIMREG "pimreg"
39 #define GM "IGMP"
40
41 #define PIM_ADDR_FUNCNAME(name) ipv4_##name
42
43 union pimprefixptr {
44 prefixtype(pimprefixptr, struct prefix, p)
45 prefixtype(pimprefixptr, struct prefix_ipv4, p4)
46 } TRANSPARENT_UNION;
47
48 union pimprefixconstptr {
49 prefixtype(pimprefixconstptr, const struct prefix, p)
50 prefixtype(pimprefixconstptr, const struct prefix_ipv4, p4)
51 } TRANSPARENT_UNION;
52
53 #else
54 typedef struct in6_addr pim_addr;
55
56 #define PIM_ADDRSTRLEN INET6_ADDRSTRLEN
57 #define PIM_AF AF_INET6
58 #define PIM_AFI AFI_IP6
59 #define PIM_IPADDR IPADDR_V6
60 #define ipaddr_pim ipaddr_v6
61 #define PIM_MAX_BITLEN IPV6_MAX_BITLEN
62 #define PIM_AF_NAME "ipv6"
63 #define PIMREG "pim6reg"
64 #define GM "MLD"
65
66 #define PIM_ADDR_FUNCNAME(name) ipv6_##name
67
68 union pimprefixptr {
69 prefixtype(pimprefixptr, struct prefix, p)
70 prefixtype(pimprefixptr, struct prefix_ipv6, p6)
71 } TRANSPARENT_UNION;
72
73 union pimprefixconstptr {
74 prefixtype(pimprefixconstptr, const struct prefix, p)
75 prefixtype(pimprefixconstptr, const struct prefix_ipv6, p6)
76 } TRANSPARENT_UNION;
77 #endif
78
79 /* for assignment/initialization (C99 compound literal)
80 * named PIMADDR_ANY (not PIM_ADDR_ANY) to match INADDR_ANY
81 */
82 #define PIMADDR_ANY (pim_addr){ }
83
84 /* clang-format on */
85
86 static inline bool pim_addr_is_any(pim_addr addr)
87 {
88 pim_addr zero = {};
89
90 return memcmp(&addr, &zero, sizeof(zero)) == 0;
91 }
92
93 static inline int pim_addr_cmp(pim_addr a, pim_addr b)
94 {
95 return memcmp(&a, &b, sizeof(a));
96 }
97
98 static inline void pim_addr_to_prefix(union pimprefixptr out, pim_addr in)
99 {
100 out.p->family = PIM_AF;
101 out.p->prefixlen = PIM_MAX_BITLEN;
102 memcpy(out.p->u.val, &in, sizeof(in));
103 }
104
105 static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in)
106 {
107 pim_addr ret;
108
109 if (in.p->family != PIM_AF)
110 return PIMADDR_ANY;
111
112 memcpy(&ret, in.p->u.val, sizeof(ret));
113 return ret;
114 }
115
116 static inline uint8_t pim_addr_scope(const pim_addr addr)
117 {
118 return PIM_ADDR_FUNCNAME(mcast_scope)(&addr);
119 }
120
121 static inline bool pim_addr_nofwd(const pim_addr addr)
122 {
123 return PIM_ADDR_FUNCNAME(mcast_nofwd)(&addr);
124 }
125
126 static inline bool pim_addr_ssm(const pim_addr addr)
127 {
128 return PIM_ADDR_FUNCNAME(mcast_ssm)(&addr);
129 }
130
131 /* don't use this struct directly, use the pim_sgaddr typedef */
132 struct _pim_sgaddr {
133 pim_addr grp;
134 pim_addr src;
135 };
136
137 typedef struct _pim_sgaddr pim_sgaddr;
138
139 static inline int pim_sgaddr_cmp(const pim_sgaddr a, const pim_sgaddr b)
140 {
141 /* memcmp over the entire struct = memcmp(grp) + memcmp(src) */
142 return memcmp(&a, &b, sizeof(a));
143 }
144
145 static inline uint32_t pim_sgaddr_hash(const pim_sgaddr a, uint32_t initval)
146 {
147 return jhash2((uint32_t *)&a, sizeof(a) / sizeof(uint32_t), initval);
148 }
149
150 #ifdef _FRR_ATTRIBUTE_PRINTFRR
151 #pragma FRR printfrr_ext "%pPA" (pim_addr *)
152 #pragma FRR printfrr_ext "%pSG" (pim_sgaddr *)
153 #endif
154
155 /*
156 * There is no pim_sgaddr2str(). This is intentional. Instead, use:
157 * snprintfrr(buf, sizeof(buf), "%pPA", sgaddr)
158 * (and note that snprintfrr is implicit for vty_out and zlog_*)
159 */
160
161 #endif /* _PIMD_PIM_ADDR_H */