]>
Commit | Line | Data |
---|---|---|
218351dd RR |
1 | /* |
2 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | * you may not use this file except in compliance with the License. | |
4 | * You may obtain a copy of the License at: | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software | |
9 | * distributed under the License is distributed on an "AS IS" BASIS, | |
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | * See the License for the specific language governing permissions and | |
12 | * limitations under the License. | |
13 | */ | |
14 | ||
15 | #include <config.h> | |
16 | #include "ovn-util.h" | |
8ad609c0 | 17 | #include "dirs.h" |
218351dd | 18 | #include "openvswitch/vlog.h" |
4685e523 | 19 | #include "ovn/lib/ovn-nb-idl.h" |
218351dd RR |
20 | |
21 | VLOG_DEFINE_THIS_MODULE(ovn_util); | |
22 | ||
4685e523 JP |
23 | static void |
24 | add_ipv4_netaddr(struct lport_addresses *laddrs, ovs_be32 addr, | |
25 | unsigned int plen) | |
26 | { | |
27 | laddrs->n_ipv4_addrs++; | |
28 | laddrs->ipv4_addrs = xrealloc(laddrs->ipv4_addrs, | |
29 | laddrs->n_ipv4_addrs * sizeof *laddrs->ipv4_addrs); | |
30 | ||
31 | struct ipv4_netaddr *na = &laddrs->ipv4_addrs[laddrs->n_ipv4_addrs - 1]; | |
32 | ||
33 | na->addr = addr; | |
34 | na->mask = be32_prefix_mask(plen); | |
35 | na->network = addr & na->mask; | |
36 | na->plen = plen; | |
37 | ||
c3179d6f JP |
38 | ovs_be32 bcast = addr | ~na->mask; |
39 | inet_ntop(AF_INET, &addr, na->addr_s, sizeof na->addr_s); | |
40 | inet_ntop(AF_INET, &na->network, na->network_s, sizeof na->network_s); | |
41 | inet_ntop(AF_INET, &bcast, na->bcast_s, sizeof na->bcast_s); | |
4685e523 JP |
42 | } |
43 | ||
44 | static void | |
45 | add_ipv6_netaddr(struct lport_addresses *laddrs, struct in6_addr addr, | |
46 | unsigned int plen) | |
47 | { | |
48 | laddrs->n_ipv6_addrs++; | |
49 | laddrs->ipv6_addrs = xrealloc(laddrs->ipv6_addrs, | |
50 | laddrs->n_ipv6_addrs * sizeof *laddrs->ipv6_addrs); | |
51 | ||
52 | struct ipv6_netaddr *na = &laddrs->ipv6_addrs[laddrs->n_ipv6_addrs - 1]; | |
53 | ||
54 | memcpy(&na->addr, &addr, sizeof na->addr); | |
55 | na->mask = ipv6_create_mask(plen); | |
56 | na->network = ipv6_addr_bitand(&addr, &na->mask); | |
57 | na->plen = plen; | |
fbd9b767 | 58 | in6_addr_solicited_node(&na->sn_addr, &addr); |
4685e523 | 59 | |
c3179d6f JP |
60 | inet_ntop(AF_INET6, &addr, na->addr_s, sizeof na->addr_s); |
61 | inet_ntop(AF_INET6, &na->sn_addr, na->sn_addr_s, sizeof na->sn_addr_s); | |
62 | inet_ntop(AF_INET6, &na->network, na->network_s, sizeof na->network_s); | |
4685e523 JP |
63 | } |
64 | ||
6374d518 LR |
65 | /* Returns true if specified address specifies a dynamic address, |
66 | * supporting the following formats: | |
67 | * | |
68 | * "dynamic": | |
69 | * Both MAC and IP are to be allocated dynamically. | |
70 | * | |
71 | * "xx:xx:xx:xx:xx:xx dynamic": | |
72 | * Use specified MAC address, but allocate an IP address | |
73 | * dynamically. | |
74 | */ | |
75 | bool | |
76 | is_dynamic_lsp_address(const char *address) | |
77 | { | |
78 | struct eth_addr ea; | |
79 | int n; | |
80 | return (!strcmp(address, "dynamic") | |
81 | || (ovs_scan(address, ETH_ADDR_SCAN_FMT" dynamic%n", | |
82 | ETH_ADDR_SCAN_ARGS(ea), &n) && address[n] == '\0')); | |
83 | } | |
84 | ||
4685e523 JP |
85 | /* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which |
86 | * should be of the format 'MAC [IP1 IP2 ..]" where IPn should be a | |
87 | * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and | |
88 | * 'ipv6_addrs' fields of 'laddrs'. | |
f2a715b5 | 89 | * |
218351dd | 90 | * Return true if at least 'MAC' is found in 'address', false otherwise. |
f2a715b5 | 91 | * |
4685e523 | 92 | * The caller must call destroy_lport_addresses(). */ |
218351dd | 93 | bool |
8439c2eb | 94 | extract_lsp_addresses(const char *address, struct lport_addresses *laddrs) |
218351dd | 95 | { |
f2a715b5 JP |
96 | memset(laddrs, 0, sizeof *laddrs); |
97 | ||
8439c2eb | 98 | const char *buf = address; |
218351dd | 99 | int buf_index = 0; |
8439c2eb | 100 | const char *buf_end = buf + strlen(address); |
218351dd RR |
101 | if (!ovs_scan_len(buf, &buf_index, ETH_ADDR_SCAN_FMT, |
102 | ETH_ADDR_SCAN_ARGS(laddrs->ea))) { | |
f2a715b5 | 103 | laddrs->ea = eth_addr_zero; |
218351dd RR |
104 | return false; |
105 | } | |
106 | ||
c3179d6f JP |
107 | snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, |
108 | ETH_ADDR_ARGS(laddrs->ea)); | |
f2a715b5 | 109 | |
218351dd RR |
110 | ovs_be32 ip4; |
111 | struct in6_addr ip6; | |
112 | unsigned int plen; | |
113 | char *error; | |
114 | ||
218351dd RR |
115 | /* Loop through the buffer and extract the IPv4/IPv6 addresses |
116 | * and store in the 'laddrs'. Break the loop if invalid data is found. | |
117 | */ | |
118 | buf += buf_index; | |
119 | while (buf < buf_end) { | |
120 | buf_index = 0; | |
121 | error = ip_parse_cidr_len(buf, &buf_index, &ip4, &plen); | |
122 | if (!error) { | |
4685e523 | 123 | add_ipv4_netaddr(laddrs, ip4, plen); |
218351dd RR |
124 | buf += buf_index; |
125 | continue; | |
126 | } | |
127 | free(error); | |
128 | error = ipv6_parse_cidr_len(buf, &buf_index, &ip6, &plen); | |
5942a98d | 129 | if (!error) { |
4685e523 JP |
130 | add_ipv6_netaddr(laddrs, ip6, plen); |
131 | } else { | |
218351dd RR |
132 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); |
133 | VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", address); | |
134 | free(error); | |
135 | break; | |
136 | } | |
137 | buf += buf_index; | |
138 | } | |
139 | ||
140 | return true; | |
141 | } | |
3bd4ae23 | 142 | |
4685e523 JP |
143 | /* Extracts the mac, IPv4 and IPv6 addresses from the |
144 | * "nbrec_logical_router_port" parameter 'lrp'. Stores the IPv4 and | |
145 | * IPv6 addresses in the 'ipv4_addrs' and 'ipv6_addrs' fields of | |
a63f7235 JP |
146 | * 'laddrs', respectively. In addition, a link local IPv6 address |
147 | * based on the 'mac' member of 'lrp' is added to the 'ipv6_addrs' | |
148 | * field. | |
4685e523 | 149 | * |
a63f7235 | 150 | * Return true if a valid 'mac' address is found in 'lrp', false otherwise. |
4685e523 JP |
151 | * |
152 | * The caller must call destroy_lport_addresses(). */ | |
153 | bool | |
154 | extract_lrp_networks(const struct nbrec_logical_router_port *lrp, | |
155 | struct lport_addresses *laddrs) | |
156 | { | |
157 | memset(laddrs, 0, sizeof *laddrs); | |
158 | ||
159 | if (!eth_addr_from_string(lrp->mac, &laddrs->ea)) { | |
160 | laddrs->ea = eth_addr_zero; | |
161 | return false; | |
162 | } | |
c3179d6f JP |
163 | snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, |
164 | ETH_ADDR_ARGS(laddrs->ea)); | |
4685e523 JP |
165 | |
166 | for (int i = 0; i < lrp->n_networks; i++) { | |
167 | ovs_be32 ip4; | |
168 | struct in6_addr ip6; | |
169 | unsigned int plen; | |
170 | char *error; | |
171 | ||
172 | error = ip_parse_cidr(lrp->networks[i], &ip4, &plen); | |
173 | if (!error) { | |
174 | if (!ip4 || plen == 32) { | |
175 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); | |
176 | VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); | |
177 | continue; | |
178 | } | |
179 | ||
180 | add_ipv4_netaddr(laddrs, ip4, plen); | |
181 | continue; | |
182 | } | |
183 | free(error); | |
184 | ||
185 | error = ipv6_parse_cidr(lrp->networks[i], &ip6, &plen); | |
186 | if (!error) { | |
187 | if (plen == 128) { | |
188 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); | |
189 | VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); | |
190 | continue; | |
191 | } | |
192 | add_ipv6_netaddr(laddrs, ip6, plen); | |
193 | } else { | |
194 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); | |
195 | VLOG_INFO_RL(&rl, "invalid syntax '%s' in networks", | |
196 | lrp->networks[i]); | |
197 | free(error); | |
198 | } | |
199 | } | |
200 | ||
a63f7235 JP |
201 | /* Always add the IPv6 link local address. */ |
202 | struct in6_addr lla; | |
203 | in6_generate_lla(laddrs->ea, &lla); | |
204 | add_ipv6_netaddr(laddrs, lla, 64); | |
205 | ||
4685e523 JP |
206 | return true; |
207 | } | |
208 | ||
f2a715b5 JP |
209 | void |
210 | destroy_lport_addresses(struct lport_addresses *laddrs) | |
211 | { | |
f2a715b5 | 212 | free(laddrs->ipv4_addrs); |
f2a715b5 JP |
213 | free(laddrs->ipv6_addrs); |
214 | } | |
215 | ||
3bd4ae23 | 216 | /* Allocates a key for NAT conntrack zone allocation for a provided |
34114cf8 | 217 | * 'key' record and a 'type'. |
3bd4ae23 GS |
218 | * |
219 | * It is the caller's responsibility to free the allocated memory. */ | |
220 | char * | |
85423044 | 221 | alloc_nat_zone_key(const struct uuid *key, const char *type) |
3bd4ae23 | 222 | { |
85423044 | 223 | return xasprintf(UUID_FMT"_%s", UUID_ARGS(key), type); |
3bd4ae23 | 224 | } |
8ad609c0 BP |
225 | |
226 | const char * | |
227 | default_nb_db(void) | |
228 | { | |
229 | static char *def; | |
230 | if (!def) { | |
231 | def = getenv("OVN_NB_DB"); | |
232 | if (!def) { | |
233 | def = xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir()); | |
234 | } | |
235 | } | |
236 | return def; | |
237 | } | |
238 | ||
239 | const char * | |
240 | default_sb_db(void) | |
241 | { | |
242 | static char *def; | |
243 | if (!def) { | |
244 | def = getenv("OVN_SB_DB"); | |
245 | if (!def) { | |
246 | def = xasprintf("unix:%s/ovnsb_db.sock", ovs_rundir()); | |
247 | } | |
248 | } | |
249 | return def; | |
250 | } |