Branch data Line data Source code
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"
17 : : #include "dirs.h"
18 : : #include "openvswitch/vlog.h"
19 : : #include "ovn/lib/ovn-nb-idl.h"
20 : :
21 : 2342 : VLOG_DEFINE_THIS_MODULE(ovn_util);
22 : :
23 : : static void
24 : 39990 : add_ipv4_netaddr(struct lport_addresses *laddrs, ovs_be32 addr,
25 : : unsigned int plen)
26 : : {
27 : 39990 : laddrs->n_ipv4_addrs++;
28 : 39990 : laddrs->ipv4_addrs = xrealloc(laddrs->ipv4_addrs,
29 : 39990 : laddrs->n_ipv4_addrs * sizeof *laddrs->ipv4_addrs);
30 : :
31 : 39990 : struct ipv4_netaddr *na = &laddrs->ipv4_addrs[laddrs->n_ipv4_addrs - 1];
32 : :
33 : 39990 : na->addr = addr;
34 : 39990 : na->mask = be32_prefix_mask(plen);
35 : 39990 : na->network = addr & na->mask;
36 : 39990 : na->plen = plen;
37 : :
38 : 39990 : ovs_be32 bcast = addr | ~na->mask;
39 : 39990 : inet_ntop(AF_INET, &addr, na->addr_s, sizeof na->addr_s);
40 : 39990 : inet_ntop(AF_INET, &na->network, na->network_s, sizeof na->network_s);
41 : 39990 : inet_ntop(AF_INET, &bcast, na->bcast_s, sizeof na->bcast_s);
42 : 39990 : }
43 : :
44 : : static void
45 : 11151 : add_ipv6_netaddr(struct lport_addresses *laddrs, struct in6_addr addr,
46 : : unsigned int plen)
47 : : {
48 : 11151 : laddrs->n_ipv6_addrs++;
49 : 11151 : laddrs->ipv6_addrs = xrealloc(laddrs->ipv6_addrs,
50 : 11151 : laddrs->n_ipv6_addrs * sizeof *laddrs->ipv6_addrs);
51 : :
52 : 11151 : struct ipv6_netaddr *na = &laddrs->ipv6_addrs[laddrs->n_ipv6_addrs - 1];
53 : :
54 : 11151 : memcpy(&na->addr, &addr, sizeof na->addr);
55 : 11151 : na->mask = ipv6_create_mask(plen);
56 : 11151 : na->network = ipv6_addr_bitand(&addr, &na->mask);
57 : 11151 : na->plen = plen;
58 : 11151 : in6_addr_solicited_node(&na->sn_addr, &addr);
59 : :
60 : 11151 : inet_ntop(AF_INET6, &addr, na->addr_s, sizeof na->addr_s);
61 : 11151 : inet_ntop(AF_INET6, &na->sn_addr, na->sn_addr_s, sizeof na->sn_addr_s);
62 : 11151 : inet_ntop(AF_INET6, &na->network, na->network_s, sizeof na->network_s);
63 : 11151 : }
64 : :
65 : : /* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which
66 : : * should be of the format 'MAC [IP1 IP2 ..]" where IPn should be a
67 : : * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and
68 : : * 'ipv6_addrs' fields of 'laddrs'.
69 : : *
70 : : * Return true if at least 'MAC' is found in 'address', false otherwise.
71 : : *
72 : : * The caller must call destroy_lport_addresses(). */
73 : : bool
74 : 41697 : extract_lsp_addresses(const char *address, struct lport_addresses *laddrs)
75 : : {
76 : 41697 : memset(laddrs, 0, sizeof *laddrs);
77 : :
78 : 41697 : const char *buf = address;
79 : 41697 : int buf_index = 0;
80 : 41697 : const char *buf_end = buf + strlen(address);
81 [ - + ]: 41697 : if (!ovs_scan_len(buf, &buf_index, ETH_ADDR_SCAN_FMT,
82 : : ETH_ADDR_SCAN_ARGS(laddrs->ea))) {
83 : 0 : laddrs->ea = eth_addr_zero;
84 : 0 : return false;
85 : : }
86 : :
87 : 250182 : snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT,
88 : 250182 : ETH_ADDR_ARGS(laddrs->ea));
89 : :
90 : : ovs_be32 ip4;
91 : : struct in6_addr ip6;
92 : : unsigned int plen;
93 : : char *error;
94 : :
95 : : /* Loop through the buffer and extract the IPv4/IPv6 addresses
96 : : * and store in the 'laddrs'. Break the loop if invalid data is found.
97 : : */
98 : 41697 : buf += buf_index;
99 [ + + ]: 72916 : while (buf < buf_end) {
100 : 31251 : buf_index = 0;
101 : 31251 : error = ip_parse_cidr_len(buf, &buf_index, &ip4, &plen);
102 [ + + ]: 31251 : if (!error) {
103 : 30012 : add_ipv4_netaddr(laddrs, ip4, plen);
104 : 30012 : buf += buf_index;
105 : 30012 : continue;
106 : : }
107 : 1239 : free(error);
108 : 1239 : error = ipv6_parse_cidr_len(buf, &buf_index, &ip6, &plen);
109 [ + + ]: 1239 : if (!error) {
110 : 1207 : add_ipv6_netaddr(laddrs, ip6, plen);
111 : : } else {
112 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
113 [ + - ]: 32 : VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", address);
114 : 32 : free(error);
115 : 32 : break;
116 : : }
117 : 1207 : buf += buf_index;
118 : : }
119 : :
120 : 41697 : return true;
121 : : }
122 : :
123 : : /* Extracts the mac, IPv4 and IPv6 addresses from the
124 : : * "nbrec_logical_router_port" parameter 'lrp'. Stores the IPv4 and
125 : : * IPv6 addresses in the 'ipv4_addrs' and 'ipv6_addrs' fields of
126 : : * 'laddrs', respectively. In addition, a link local IPv6 address
127 : : * based on the 'mac' member of 'lrp' is added to the 'ipv6_addrs'
128 : : * field.
129 : : *
130 : : * Return true if a valid 'mac' address is found in 'lrp', false otherwise.
131 : : *
132 : : * The caller must call destroy_lport_addresses(). */
133 : : bool
134 : 9944 : extract_lrp_networks(const struct nbrec_logical_router_port *lrp,
135 : : struct lport_addresses *laddrs)
136 : : {
137 : 9944 : memset(laddrs, 0, sizeof *laddrs);
138 : :
139 [ - + ]: 9944 : if (!eth_addr_from_string(lrp->mac, &laddrs->ea)) {
140 : 0 : laddrs->ea = eth_addr_zero;
141 : 0 : return false;
142 : : }
143 : 59664 : snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT,
144 : 59664 : ETH_ADDR_ARGS(laddrs->ea));
145 : :
146 [ + + ]: 19922 : for (int i = 0; i < lrp->n_networks; i++) {
147 : : ovs_be32 ip4;
148 : : struct in6_addr ip6;
149 : : unsigned int plen;
150 : : char *error;
151 : :
152 : 9978 : error = ip_parse_cidr(lrp->networks[i], &ip4, &plen);
153 [ + - ]: 9978 : if (!error) {
154 [ + - ][ - + ]: 9978 : if (!ip4 || plen == 32) {
155 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
156 [ # # ]: 0 : VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]);
157 : 9978 : continue;
158 : : }
159 : :
160 : 9978 : add_ipv4_netaddr(laddrs, ip4, plen);
161 : 9978 : continue;
162 : : }
163 : 0 : free(error);
164 : :
165 : 0 : error = ipv6_parse_cidr(lrp->networks[i], &ip6, &plen);
166 [ # # ]: 0 : if (!error) {
167 [ # # ]: 0 : if (plen == 128) {
168 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
169 [ # # ]: 0 : VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]);
170 : 0 : continue;
171 : : }
172 : 0 : add_ipv6_netaddr(laddrs, ip6, plen);
173 : : } else {
174 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
175 [ # # ]: 0 : VLOG_INFO_RL(&rl, "invalid syntax '%s' in networks",
176 : : lrp->networks[i]);
177 : 0 : free(error);
178 : : }
179 : : }
180 : :
181 : : /* Always add the IPv6 link local address. */
182 : : struct in6_addr lla;
183 : 9944 : in6_generate_lla(laddrs->ea, &lla);
184 : 9944 : add_ipv6_netaddr(laddrs, lla, 64);
185 : :
186 : 9944 : return true;
187 : : }
188 : :
189 : : void
190 : 71802 : destroy_lport_addresses(struct lport_addresses *laddrs)
191 : : {
192 : 71802 : free(laddrs->ipv4_addrs);
193 : 71802 : free(laddrs->ipv6_addrs);
194 : 71802 : }
195 : :
196 : : /* Allocates a key for NAT conntrack zone allocation for a provided
197 : : * 'key' record and a 'type'.
198 : : *
199 : : * It is the caller's responsibility to free the allocated memory. */
200 : : char *
201 : 73338 : alloc_nat_zone_key(const struct uuid *key, const char *type)
202 : : {
203 : 73338 : return xasprintf(UUID_FMT"_%s", UUID_ARGS(key), type);
204 : : }
205 : :
206 : : const char *
207 : 899 : default_nb_db(void)
208 : : {
209 : : static char *def;
210 [ + - ]: 899 : if (!def) {
211 : 899 : def = getenv("OVN_NB_DB");
212 [ + + ]: 899 : if (!def) {
213 : 229 : def = xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir());
214 : : }
215 : : }
216 : 899 : return def;
217 : : }
218 : :
219 : : const char *
220 : 188 : default_sb_db(void)
221 : : {
222 : : static char *def;
223 [ + - ]: 188 : if (!def) {
224 : 188 : def = getenv("OVN_SB_DB");
225 [ + + ]: 188 : if (!def) {
226 : 64 : def = xasprintf("unix:%s/ovnsb_db.sock", ovs_rundir());
227 : : }
228 : : }
229 : 188 : return def;
230 : : }
|