]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
26625d51 DL |
2 | /* |
3 | * PIM address generalizations | |
4 | * Copyright (C) 2022 David Lamparter for NetDEF, Inc. | |
26625d51 DL |
5 | */ |
6 | ||
7 | #ifndef _PIMD_PIM_ADDR_H | |
8 | #define _PIMD_PIM_ADDR_H | |
9 | ||
10 | #include "jhash.h" | |
a6751e23 DL |
11 | #include "prefix.h" |
12 | ||
13 | /* clang-format off */ | |
26625d51 | 14 | |
ae449dc5 | 15 | #if PIM_IPV == 4 |
26625d51 | 16 | typedef struct in_addr pim_addr; |
a6751e23 DL |
17 | |
18 | #define PIM_ADDRSTRLEN INET_ADDRSTRLEN | |
19 | #define PIM_AF AF_INET | |
20 | #define PIM_AFI AFI_IP | |
e23b5d86 | 21 | #define PIM_PROTO_REG IPPROTO_RAW |
dea337dc DL |
22 | #define PIM_IPADDR IPADDR_V4 |
23 | #define ipaddr_pim ipaddr_v4 | |
a6751e23 | 24 | #define PIM_MAX_BITLEN IPV4_MAX_BITLEN |
ebde3825 | 25 | #define PIM_AF_NAME "ip" |
68a7caf4 | 26 | #define PIM_AF_DBG "pim" |
a2559761 | 27 | #define GM_AF_DBG "igmp" |
ca8cbecd | 28 | #define PIM_MROUTE_DBG "mroute" |
d8cace87 | 29 | #define PIMREG "pimreg" |
5c1b3cd2 | 30 | #define GM "IGMP" |
bd2c824a | 31 | #define IPPROTO_GM IPPROTO_IGMP |
a6751e23 | 32 | |
eeec4112 DL |
33 | #define PIM_ADDR_FUNCNAME(name) ipv4_##name |
34 | ||
a6751e23 DL |
35 | union pimprefixptr { |
36 | prefixtype(pimprefixptr, struct prefix, p) | |
37 | prefixtype(pimprefixptr, struct prefix_ipv4, p4) | |
38 | } TRANSPARENT_UNION; | |
39 | ||
40 | union pimprefixconstptr { | |
41 | prefixtype(pimprefixconstptr, const struct prefix, p) | |
42 | prefixtype(pimprefixconstptr, const struct prefix_ipv4, p4) | |
43 | } TRANSPARENT_UNION; | |
44 | ||
26625d51 DL |
45 | #else |
46 | typedef struct in6_addr pim_addr; | |
a6751e23 DL |
47 | |
48 | #define PIM_ADDRSTRLEN INET6_ADDRSTRLEN | |
49 | #define PIM_AF AF_INET6 | |
50 | #define PIM_AFI AFI_IP6 | |
e23b5d86 | 51 | #define PIM_PROTO_REG IPPROTO_PIM |
dea337dc DL |
52 | #define PIM_IPADDR IPADDR_V6 |
53 | #define ipaddr_pim ipaddr_v6 | |
a6751e23 | 54 | #define PIM_MAX_BITLEN IPV6_MAX_BITLEN |
ebde3825 | 55 | #define PIM_AF_NAME "ipv6" |
68a7caf4 | 56 | #define PIM_AF_DBG "pimv6" |
a2559761 | 57 | #define GM_AF_DBG "mld" |
ca8cbecd | 58 | #define PIM_MROUTE_DBG "mroute6" |
d8cace87 | 59 | #define PIMREG "pim6reg" |
5c1b3cd2 | 60 | #define GM "MLD" |
bd2c824a | 61 | #define IPPROTO_GM IPPROTO_ICMPV6 |
a6751e23 | 62 | |
eeec4112 DL |
63 | #define PIM_ADDR_FUNCNAME(name) ipv6_##name |
64 | ||
a6751e23 DL |
65 | union pimprefixptr { |
66 | prefixtype(pimprefixptr, struct prefix, p) | |
67 | prefixtype(pimprefixptr, struct prefix_ipv6, p6) | |
68 | } TRANSPARENT_UNION; | |
69 | ||
70 | union pimprefixconstptr { | |
71 | prefixtype(pimprefixconstptr, const struct prefix, p) | |
72 | prefixtype(pimprefixconstptr, const struct prefix_ipv6, p6) | |
73 | } TRANSPARENT_UNION; | |
26625d51 DL |
74 | #endif |
75 | ||
bca160c6 DL |
76 | /* for assignment/initialization (C99 compound literal) |
77 | * named PIMADDR_ANY (not PIM_ADDR_ANY) to match INADDR_ANY | |
78 | */ | |
79 | #define PIMADDR_ANY (pim_addr){ } | |
80 | ||
a6751e23 DL |
81 | /* clang-format on */ |
82 | ||
2a27f13b DL |
83 | static inline bool pim_addr_is_any(pim_addr addr) |
84 | { | |
85 | pim_addr zero = {}; | |
86 | ||
87 | return memcmp(&addr, &zero, sizeof(zero)) == 0; | |
88 | } | |
89 | ||
032a7412 DL |
90 | static inline int pim_addr_cmp(pim_addr a, pim_addr b) |
91 | { | |
92 | return memcmp(&a, &b, sizeof(a)); | |
93 | } | |
94 | ||
a6751e23 DL |
95 | static inline void pim_addr_to_prefix(union pimprefixptr out, pim_addr in) |
96 | { | |
97 | out.p->family = PIM_AF; | |
98 | out.p->prefixlen = PIM_MAX_BITLEN; | |
99 | memcpy(out.p->u.val, &in, sizeof(in)); | |
100 | } | |
101 | ||
102 | static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in) | |
103 | { | |
104 | pim_addr ret; | |
105 | ||
106 | if (in.p->family != PIM_AF) | |
107 | return PIMADDR_ANY; | |
108 | ||
109 | memcpy(&ret, in.p->u.val, sizeof(ret)); | |
110 | return ret; | |
111 | } | |
112 | ||
eeec4112 DL |
113 | static inline uint8_t pim_addr_scope(const pim_addr addr) |
114 | { | |
115 | return PIM_ADDR_FUNCNAME(mcast_scope)(&addr); | |
116 | } | |
117 | ||
118 | static inline bool pim_addr_nofwd(const pim_addr addr) | |
119 | { | |
120 | return PIM_ADDR_FUNCNAME(mcast_nofwd)(&addr); | |
121 | } | |
122 | ||
123 | static inline bool pim_addr_ssm(const pim_addr addr) | |
124 | { | |
125 | return PIM_ADDR_FUNCNAME(mcast_ssm)(&addr); | |
126 | } | |
127 | ||
26625d51 DL |
128 | /* don't use this struct directly, use the pim_sgaddr typedef */ |
129 | struct _pim_sgaddr { | |
130 | pim_addr grp; | |
131 | pim_addr src; | |
132 | }; | |
133 | ||
134 | typedef struct _pim_sgaddr pim_sgaddr; | |
135 | ||
136 | static inline int pim_sgaddr_cmp(const pim_sgaddr a, const pim_sgaddr b) | |
137 | { | |
138 | /* memcmp over the entire struct = memcmp(grp) + memcmp(src) */ | |
139 | return memcmp(&a, &b, sizeof(a)); | |
140 | } | |
141 | ||
142 | static inline uint32_t pim_sgaddr_hash(const pim_sgaddr a, uint32_t initval) | |
143 | { | |
144 | return jhash2((uint32_t *)&a, sizeof(a) / sizeof(uint32_t), initval); | |
145 | } | |
146 | ||
147 | #ifdef _FRR_ATTRIBUTE_PRINTFRR | |
148 | #pragma FRR printfrr_ext "%pPA" (pim_addr *) | |
149 | #pragma FRR printfrr_ext "%pSG" (pim_sgaddr *) | |
150 | #endif | |
151 | ||
152 | /* | |
153 | * There is no pim_sgaddr2str(). This is intentional. Instead, use: | |
154 | * snprintfrr(buf, sizeof(buf), "%pPA", sgaddr) | |
155 | * (and note that snprintfrr is implicit for vty_out and zlog_*) | |
156 | */ | |
157 | ||
158 | #endif /* _PIMD_PIM_ADDR_H */ |