Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at:
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #include <config.h>
18 : : #include "packets.h"
19 : : #include <arpa/inet.h>
20 : : #include <sys/socket.h>
21 : : #include <netinet/in.h>
22 : : #include <netinet/ip6.h>
23 : : #include <netinet/icmp6.h>
24 : : #include <stdlib.h>
25 : : #include "byte-order.h"
26 : : #include "csum.h"
27 : : #include "crc32c.h"
28 : : #include "flow.h"
29 : : #include "openvswitch/hmap.h"
30 : : #include "openvswitch/dynamic-string.h"
31 : : #include "ovs-thread.h"
32 : : #include "odp-util.h"
33 : : #include "dp-packet.h"
34 : : #include "unaligned.h"
35 : :
36 : : const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
37 : : const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT;
38 : :
39 : : struct in6_addr
40 : 97247 : flow_tnl_dst(const struct flow_tnl *tnl)
41 : : {
42 [ + + ]: 97247 : return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst;
43 : : }
44 : :
45 : : struct in6_addr
46 : 9245 : flow_tnl_src(const struct flow_tnl *tnl)
47 : : {
48 [ + + ]: 9245 : return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src;
49 : : }
50 : :
51 : : /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On
52 : : * success stores the dpid into '*dpidp' and returns true, on failure stores 0
53 : : * into '*dpidp' and returns false.
54 : : *
55 : : * Rejects an all-zeros dpid as invalid. */
56 : : bool
57 : 4700 : dpid_from_string(const char *s, uint64_t *dpidp)
58 : : {
59 [ + + ][ + - ]: 4700 : *dpidp = (strlen(s) == 16 && strspn(s, "0123456789abcdefABCDEF") == 16
60 : : ? strtoull(s, NULL, 16)
61 : : : 0);
62 : 4700 : return *dpidp != 0;
63 : : }
64 : :
65 : : /* Returns true if 'ea' is a reserved address, that a bridge must never
66 : : * forward, false otherwise.
67 : : *
68 : : * If you change this function's behavior, please update corresponding
69 : : * documentation in vswitch.xml at the same time. */
70 : : bool
71 : 30443 : eth_addr_is_reserved(const struct eth_addr ea)
72 : : {
73 : : struct eth_addr_node {
74 : : struct hmap_node hmap_node;
75 : : const uint64_t ea64;
76 : : };
77 : :
78 : : static struct eth_addr_node nodes[] = {
79 : : /* STP, IEEE pause frames, and other reserved protocols. */
80 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000000ULL },
81 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000001ULL },
82 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000002ULL },
83 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000003ULL },
84 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000004ULL },
85 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000005ULL },
86 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000006ULL },
87 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000007ULL },
88 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000008ULL },
89 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000009ULL },
90 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000aULL },
91 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000bULL },
92 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000cULL },
93 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000dULL },
94 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000eULL },
95 : : { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000fULL },
96 : :
97 : : /* Extreme protocols. */
98 : : { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000000ULL }, /* EDP. */
99 : : { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000004ULL }, /* EAPS. */
100 : : { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000006ULL }, /* EAPS. */
101 : :
102 : : /* Cisco protocols. */
103 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000c000000ULL }, /* ISL. */
104 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccccULL }, /* PAgP, UDLD, CDP,
105 : : * DTP, VTP. */
106 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000ccccccdULL }, /* PVST+. */
107 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000ccdcdcdULL }, /* STP Uplink Fast,
108 : : * FlexLink. */
109 : :
110 : : /* Cisco CFM. */
111 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc0ULL },
112 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc1ULL },
113 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc2ULL },
114 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc3ULL },
115 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc4ULL },
116 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc5ULL },
117 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc6ULL },
118 : : { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc7ULL },
119 : : };
120 : :
121 : : static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
122 : : struct eth_addr_node *node;
123 : : static struct hmap addrs;
124 : : uint64_t ea64;
125 : :
126 [ + + ]: 30443 : if (ovsthread_once_start(&once)) {
127 : 170 : hmap_init(&addrs);
128 [ + + ]: 5440 : for (node = nodes; node < &nodes[ARRAY_SIZE(nodes)]; node++) {
129 : 5270 : hmap_insert(&addrs, &node->hmap_node, hash_uint64(node->ea64));
130 : : }
131 : 170 : ovsthread_once_done(&once);
132 : : }
133 : :
134 : 30443 : ea64 = eth_addr_to_uint64(ea);
135 [ + + ][ - + ]: 116162 : HMAP_FOR_EACH_IN_BUCKET (node, hmap_node, hash_uint64(ea64), &addrs) {
136 [ - + ]: 85719 : if (node->ea64 == ea64) {
137 : 0 : return true;
138 : : }
139 : : }
140 : 30443 : return false;
141 : : }
142 : :
143 : : /* Attempts to parse 's' as an Ethernet address. If successful, stores the
144 : : * address in 'ea' and returns true, otherwise zeros 'ea' and returns
145 : : * false. */
146 : : bool
147 : 159151 : eth_addr_from_string(const char *s, struct eth_addr *ea)
148 : : {
149 [ + + ]: 159151 : if (ovs_scan(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(*ea))) {
150 : 92179 : return true;
151 : : } else {
152 : 66972 : *ea = eth_addr_zero;
153 : 66972 : return false;
154 : : }
155 : : }
156 : :
157 : : /* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'.
158 : : * This function is used by Open vSwitch to compose packets in cases where
159 : : * context is important but content doesn't (or shouldn't) matter.
160 : : *
161 : : * The returned packet has enough headroom to insert an 802.1Q VLAN header if
162 : : * desired. */
163 : : void
164 : 2 : compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)
165 : : {
166 : : struct eth_header *eth;
167 : : struct arp_eth_header *arp;
168 : :
169 : 2 : dp_packet_clear(b);
170 : 2 : dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN
171 : : + ARP_ETH_HEADER_LEN);
172 : 2 : dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
173 : 2 : eth = dp_packet_put_uninit(b, sizeof *eth);
174 : 2 : eth->eth_dst = eth_addr_broadcast;
175 : 2 : eth->eth_src = eth_src;
176 : 2 : eth->eth_type = htons(ETH_TYPE_RARP);
177 : :
178 : 2 : arp = dp_packet_put_uninit(b, sizeof *arp);
179 : 2 : arp->ar_hrd = htons(ARP_HRD_ETHERNET);
180 : 2 : arp->ar_pro = htons(ARP_PRO_IP);
181 : 2 : arp->ar_hln = sizeof arp->ar_sha;
182 : 2 : arp->ar_pln = sizeof arp->ar_spa;
183 : 2 : arp->ar_op = htons(ARP_OP_RARP);
184 : 2 : arp->ar_sha = eth_src;
185 : 2 : put_16aligned_be32(&arp->ar_spa, htonl(0));
186 : 2 : arp->ar_tha = eth_src;
187 : 2 : put_16aligned_be32(&arp->ar_tpa, htonl(0));
188 : :
189 : 2 : dp_packet_reset_offsets(b);
190 : 2 : dp_packet_set_l3(b, arp);
191 : 2 : }
192 : :
193 : : /* Insert VLAN header according to given TCI. Packet passed must be Ethernet
194 : : * packet. Ignores the CFI bit of 'tci' using 0 instead.
195 : : *
196 : : * Also adjusts the layer offsets accordingly. */
197 : : void
198 : 248 : eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)
199 : : {
200 : : struct vlan_eth_header *veh;
201 : :
202 : : /* Insert new 802.1Q header. */
203 : 248 : veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN);
204 : 248 : memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);
205 : 248 : veh->veth_type = tpid;
206 : 248 : veh->veth_tci = tci & htons(~VLAN_CFI);
207 : 248 : }
208 : :
209 : : /* Removes outermost VLAN header (if any is present) from 'packet'.
210 : : *
211 : : * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header
212 : : * or may be NULL if there are no VLAN headers. */
213 : : void
214 : 38 : eth_pop_vlan(struct dp_packet *packet)
215 : : {
216 : 38 : struct vlan_eth_header *veh = dp_packet_l2(packet);
217 : :
218 [ + - ][ + - ]: 38 : if (veh && dp_packet_size(packet) >= sizeof *veh
219 [ + - ]: 38 : && eth_type_vlan(veh->veth_type)) {
220 : :
221 : 38 : memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);
222 : 38 : dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);
223 : : }
224 : 38 : }
225 : :
226 : : /* Set ethertype of the packet. */
227 : : static void
228 : 3618 : set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
229 : : {
230 : 3618 : struct eth_header *eh = dp_packet_l2(packet);
231 : :
232 [ - + ]: 3618 : if (!eh) {
233 : 0 : return;
234 : : }
235 : :
236 [ + + ]: 3618 : if (eth_type_vlan(eh->eth_type)) {
237 : : ovs_be16 *p;
238 : 54 : char *l2_5 = dp_packet_l2_5(packet);
239 : :
240 [ + - ]: 54 : p = ALIGNED_CAST(ovs_be16 *,
241 : : (l2_5 ? l2_5 : (char *)dp_packet_l3(packet)) - 2);
242 : 54 : *p = eth_type;
243 : : } else {
244 : 3564 : eh->eth_type = eth_type;
245 : : }
246 : : }
247 : :
248 : 3660 : static bool is_mpls(struct dp_packet *packet)
249 : : {
250 : 3660 : return packet->l2_5_ofs != UINT16_MAX;
251 : : }
252 : :
253 : : /* Set time to live (TTL) of an MPLS label stack entry (LSE). */
254 : : void
255 : 242 : set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl)
256 : : {
257 : 242 : *lse &= ~htonl(MPLS_TTL_MASK);
258 : 242 : *lse |= htonl((ttl << MPLS_TTL_SHIFT) & MPLS_TTL_MASK);
259 : 242 : }
260 : :
261 : : /* Set traffic class (TC) of an MPLS label stack entry (LSE). */
262 : : void
263 : 263 : set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc)
264 : : {
265 : 263 : *lse &= ~htonl(MPLS_TC_MASK);
266 : 263 : *lse |= htonl((tc << MPLS_TC_SHIFT) & MPLS_TC_MASK);
267 : 263 : }
268 : :
269 : : /* Set label of an MPLS label stack entry (LSE). */
270 : : void
271 : 381 : set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label)
272 : : {
273 : 381 : *lse &= ~htonl(MPLS_LABEL_MASK);
274 : 381 : *lse |= htonl((ntohl(label) << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK);
275 : 381 : }
276 : :
277 : : /* Set bottom of stack (BoS) bit of an MPLS label stack entry (LSE). */
278 : : void
279 : 1959 : set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos)
280 : : {
281 : 1959 : *lse &= ~htonl(MPLS_BOS_MASK);
282 : 1959 : *lse |= htonl((bos << MPLS_BOS_SHIFT) & MPLS_BOS_MASK);
283 : 1959 : }
284 : :
285 : : /* Compose an MPLS label stack entry (LSE) from its components:
286 : : * label, traffic class (TC), time to live (TTL) and
287 : : * bottom of stack (BoS) bit. */
288 : : ovs_be32
289 : 178 : set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, ovs_be32 label)
290 : : {
291 : 178 : ovs_be32 lse = htonl(0);
292 : 178 : set_mpls_lse_ttl(&lse, ttl);
293 : 178 : set_mpls_lse_tc(&lse, tc);
294 : 178 : set_mpls_lse_bos(&lse, bos);
295 : 178 : set_mpls_lse_label(&lse, label);
296 : 178 : return lse;
297 : : }
298 : :
299 : : /* Set MPLS label stack entry to outermost MPLS header.*/
300 : : void
301 : 42 : set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse)
302 : : {
303 : : /* Packet type should be MPLS to set label stack entry. */
304 [ + - ]: 42 : if (is_mpls(packet)) {
305 : 42 : struct mpls_hdr *mh = dp_packet_l2_5(packet);
306 : :
307 : : /* Update mpls label stack entry. */
308 : 42 : put_16aligned_be32(&mh->mpls_lse, mpls_lse);
309 : : }
310 : 42 : }
311 : :
312 : : /* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS
313 : : * header. If 'packet' does not already have any MPLS labels, then its
314 : : * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */
315 : : void
316 : 3481 : push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)
317 : : {
318 : : char * header;
319 : : size_t len;
320 : :
321 [ - + ]: 3481 : if (!eth_type_mpls(ethtype)) {
322 : 0 : return;
323 : : }
324 : :
325 [ + + ]: 3481 : if (!is_mpls(packet)) {
326 : : /* Set MPLS label stack offset. */
327 : 127 : packet->l2_5_ofs = packet->l3_ofs;
328 : : }
329 : :
330 : 3481 : set_ethertype(packet, ethtype);
331 : :
332 : : /* Push new MPLS shim header onto packet. */
333 : 3481 : len = packet->l2_5_ofs;
334 : 3481 : header = dp_packet_resize_l2_5(packet, MPLS_HLEN);
335 : 3481 : memmove(header, header + MPLS_HLEN, len);
336 : 3481 : memcpy(header + len, &lse, sizeof lse);
337 : : }
338 : :
339 : : /* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.
340 : : * If the label that was removed was the only MPLS label, changes 'packet''s
341 : : * Ethertype to 'ethtype' (which ordinarily should not be an MPLS
342 : : * Ethertype). */
343 : : void
344 : 137 : pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)
345 : : {
346 [ + - ]: 137 : if (is_mpls(packet)) {
347 : 137 : struct mpls_hdr *mh = dp_packet_l2_5(packet);
348 : 137 : size_t len = packet->l2_5_ofs;
349 : :
350 : 137 : set_ethertype(packet, ethtype);
351 [ + + ]: 137 : if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) {
352 : 67 : dp_packet_set_l2_5(packet, NULL);
353 : : }
354 : : /* Shift the l2 header forward. */
355 : 137 : memmove((char*)dp_packet_data(packet) + MPLS_HLEN, dp_packet_data(packet), len);
356 : 137 : dp_packet_resize_l2_5(packet, -MPLS_HLEN);
357 : : }
358 : 137 : }
359 : :
360 : : /* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The
361 : : * caller must free '*packetp'. On success, returns NULL. On failure, returns
362 : : * an error message and stores NULL in '*packetp'.
363 : : *
364 : : * Aligns the L3 header of '*packetp' on a 32-bit boundary. */
365 : : const char *
366 : 6051 : eth_from_hex(const char *hex, struct dp_packet **packetp)
367 : : {
368 : : struct dp_packet *packet;
369 : :
370 : : /* Use 2 bytes of headroom to 32-bit align the L3 header. */
371 : 6051 : packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2);
372 : :
373 [ + + ]: 6051 : if (dp_packet_put_hex(packet, hex, NULL)[0] != '\0') {
374 : 1975 : dp_packet_delete(packet);
375 : 1975 : *packetp = NULL;
376 : 1975 : return "Trailing garbage in packet data";
377 : : }
378 : :
379 [ - + ]: 4076 : if (dp_packet_size(packet) < ETH_HEADER_LEN) {
380 : 0 : dp_packet_delete(packet);
381 : 0 : *packetp = NULL;
382 : 0 : return "Packet data too short for Ethernet";
383 : : }
384 : :
385 : 4076 : return NULL;
386 : : }
387 : :
388 : : void
389 : 28641 : eth_format_masked(const struct eth_addr eth,
390 : : const struct eth_addr *mask, struct ds *s)
391 : : {
392 : 28641 : ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth));
393 [ + + ][ + + ]: 28641 : if (mask && !eth_mask_is_exact(*mask)) {
394 : 1866 : ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(*mask));
395 : : }
396 : 28641 : }
397 : :
398 : : /* Given the IP netmask 'netmask', returns the number of bits of the IP address
399 : : * that it specifies, that is, the number of 1-bits in 'netmask'.
400 : : *
401 : : * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
402 : : * still be in the valid range but isn't otherwise meaningful. */
403 : : int
404 : 51042 : ip_count_cidr_bits(ovs_be32 netmask)
405 : : {
406 : 51042 : return 32 - ctz32(ntohl(netmask));
407 : : }
408 : :
409 : : void
410 : 17546 : ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s)
411 : : {
412 : 17546 : ds_put_format(s, IP_FMT, IP_ARGS(ip));
413 [ + + ]: 17546 : if (mask != OVS_BE32_MAX) {
414 [ + + ]: 1968 : if (ip_is_cidr(mask)) {
415 : 1960 : ds_put_format(s, "/%d", ip_count_cidr_bits(mask));
416 : : } else {
417 : 8 : ds_put_format(s, "/"IP_FMT, IP_ARGS(mask));
418 : : }
419 : : }
420 : 17546 : }
421 : :
422 : : /* Parses string 's', which must be an IP address. Stores the IP address into
423 : : * '*ip'. Returns true if successful, otherwise false. */
424 : : bool
425 : 502092 : ip_parse(const char *s, ovs_be32 *ip)
426 : : {
427 : 502092 : return inet_pton(AF_INET, s, ip) == 1;
428 : : }
429 : :
430 : : /* Parses string 's', which must be an IP address with an optional netmask or
431 : : * CIDR prefix length. Stores the IP address into '*ip', netmask into '*mask',
432 : : * (255.255.255.255, if 's' lacks a netmask), and number of scanned characters
433 : : * into '*n'.
434 : : *
435 : : * Returns NULL if successful, otherwise an error message that the caller must
436 : : * free(). */
437 : : char * OVS_WARN_UNUSED_RESULT
438 : 44863 : ip_parse_masked_len(const char *s, int *n, ovs_be32 *ip,
439 : : ovs_be32 *mask)
440 : : {
441 : : int prefix;
442 : :
443 [ + + ]: 44863 : if (ovs_scan_len(s, n, IP_SCAN_FMT"/"IP_SCAN_FMT,
444 : : IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask))) {
445 : : /* OK. */
446 [ + + ]: 44850 : } else if (ovs_scan_len(s, n, IP_SCAN_FMT"/%d",
447 : : IP_SCAN_ARGS(ip), &prefix)) {
448 [ + - ][ - + ]: 11336 : if (prefix < 0 || prefix > 32) {
449 : 0 : return xasprintf("%s: IPv4 network prefix bits not between 0 and "
450 : : "32, inclusive", s);
451 : : }
452 : 11336 : *mask = be32_prefix_mask(prefix);
453 [ + + ]: 33514 : } else if (ovs_scan_len(s, n, IP_SCAN_FMT, IP_SCAN_ARGS(ip))) {
454 : 32229 : *mask = OVS_BE32_MAX;
455 : : } else {
456 : 1285 : return xasprintf("%s: invalid IP address", s);
457 : : }
458 : 44863 : return NULL;
459 : : }
460 : :
461 : : /* This function is similar to ip_parse_masked_len(), but doesn't return the
462 : : * number of scanned characters and expects 's' to end after the ip/(optional)
463 : : * mask.
464 : : *
465 : : * Returns NULL if successful, otherwise an error message that the caller must
466 : : * free(). */
467 : : char * OVS_WARN_UNUSED_RESULT
468 : 1941 : ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask)
469 : : {
470 : 1941 : int n = 0;
471 : :
472 : 1941 : char *error = ip_parse_masked_len(s, &n, ip, mask);
473 [ + - ][ - + ]: 1941 : if (!error && s[n]) {
474 : 0 : return xasprintf("%s: invalid IP address", s);
475 : : }
476 : 1941 : return error;
477 : : }
478 : :
479 : : /* Similar to ip_parse_masked_len(), but the mask, if present, must be a CIDR
480 : : * mask and is returned as a prefix len in '*plen'. */
481 : : char * OVS_WARN_UNUSED_RESULT
482 : 42922 : ip_parse_cidr_len(const char *s, int *n, ovs_be32 *ip, unsigned int *plen)
483 : : {
484 : : ovs_be32 mask;
485 : : char *error;
486 : :
487 : 42922 : error = ip_parse_masked_len(s, n, ip, &mask);
488 [ + + ]: 42922 : if (error) {
489 : 1285 : return error;
490 : : }
491 : :
492 [ - + ]: 41637 : if (!ip_is_cidr(mask)) {
493 : 0 : return xasprintf("%s: CIDR network required", s);
494 : : }
495 : 41637 : *plen = ip_count_cidr_bits(mask);
496 : 42922 : return NULL;
497 : : }
498 : :
499 : : /* Similar to ip_parse_cidr_len(), but doesn't return the number of scanned
500 : : * characters and expects 's' to be NULL terminated at the end of the
501 : : * ip/(optional) cidr. */
502 : : char * OVS_WARN_UNUSED_RESULT
503 : 11671 : ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
504 : : {
505 : 11671 : int n = 0;
506 : :
507 : 11671 : char *error = ip_parse_cidr_len(s, &n, ip, plen);
508 [ + + ][ - + ]: 11671 : if (!error && s[n]) {
509 : 0 : return xasprintf("%s: invalid IP address", s);
510 : : }
511 : 11671 : return error;
512 : : }
513 : :
514 : : /* Parses string 's', which must be an IPv6 address. Stores the IPv6 address
515 : : * into '*ip'. Returns true if successful, otherwise false. */
516 : : bool
517 : 161664 : ipv6_parse(const char *s, struct in6_addr *ip)
518 : : {
519 : 161664 : return inet_pton(AF_INET6, s, ip) == 1;
520 : : }
521 : :
522 : : /* Parses string 's', which must be an IPv6 address with an optional netmask or
523 : : * CIDR prefix length. Stores the IPv6 address into '*ip' and the netmask into
524 : : * '*mask' (if 's' does not contain a netmask, all-one-bits is assumed), and
525 : : * number of scanned characters into '*n'.
526 : : *
527 : : * Returns NULL if successful, otherwise an error message that the caller must
528 : : * free(). */
529 : : char * OVS_WARN_UNUSED_RESULT
530 : 1403 : ipv6_parse_masked_len(const char *s, int *n, struct in6_addr *ip,
531 : : struct in6_addr *mask)
532 : : {
533 : : char ipv6_s[IPV6_SCAN_LEN + 1];
534 : : int prefix;
535 : :
536 [ + + ]: 1403 : if (ovs_scan_len(s, n, " "IPV6_SCAN_FMT, ipv6_s)
537 [ + - ]: 1371 : && ipv6_parse(ipv6_s, ip)) {
538 [ + + ]: 1371 : if (ovs_scan_len(s, n, "/%d", &prefix)) {
539 [ + - ][ - + ]: 397 : if (prefix < 0 || prefix > 128) {
540 : 0 : return xasprintf("%s: IPv6 network prefix bits not between 0 "
541 : : "and 128, inclusive", s);
542 : : }
543 : 397 : *mask = ipv6_create_mask(prefix);
544 [ + + ]: 974 : } else if (ovs_scan_len(s, n, "/"IPV6_SCAN_FMT, ipv6_s)) {
545 [ - + ]: 3 : if (!ipv6_parse(ipv6_s, mask)) {
546 : 0 : return xasprintf("%s: Invalid IPv6 mask", s);
547 : : }
548 : : /* OK. */
549 : : } else {
550 : : /* OK. No mask. */
551 : 971 : *mask = in6addr_exact;
552 : : }
553 : 1371 : return NULL;
554 : : }
555 : 1403 : return xasprintf("%s: invalid IPv6 address", s);
556 : : }
557 : :
558 : : /* This function is similar to ipv6_parse_masked_len(), but doesn't return the
559 : : * number of scanned characters and expects 's' to end following the
560 : : * ipv6/(optional) mask. */
561 : : char * OVS_WARN_UNUSED_RESULT
562 : 116 : ipv6_parse_masked(const char *s, struct in6_addr *ip, struct in6_addr *mask)
563 : : {
564 : 116 : int n = 0;
565 : :
566 : 116 : char *error = ipv6_parse_masked_len(s, &n, ip, mask);
567 [ + - ][ - + ]: 116 : if (!error && s[n]) {
568 : 0 : return xasprintf("%s: invalid IPv6 address", s);
569 : : }
570 : 116 : return error;
571 : : }
572 : :
573 : : /* Similar to ipv6_parse_masked_len(), but the mask, if present, must be a CIDR
574 : : * mask and is returned as a prefix length in '*plen'. */
575 : : char * OVS_WARN_UNUSED_RESULT
576 : 1287 : ipv6_parse_cidr_len(const char *s, int *n, struct in6_addr *ip,
577 : : unsigned int *plen)
578 : : {
579 : : struct in6_addr mask;
580 : : char *error;
581 : :
582 : 1287 : error = ipv6_parse_masked_len(s, n, ip, &mask);
583 [ + + ]: 1287 : if (error) {
584 : 32 : return error;
585 : : }
586 : :
587 [ - + ]: 1255 : if (!ipv6_is_cidr(&mask)) {
588 : 0 : return xasprintf("%s: IPv6 CIDR network required", s);
589 : : }
590 : 1255 : *plen = ipv6_count_cidr_bits(&mask);
591 : 1287 : return NULL;
592 : : }
593 : :
594 : : /* Similar to ipv6_parse_cidr_len(), but doesn't return the number of scanned
595 : : * characters and expects 's' to end after the ipv6/(optional) cidr. */
596 : : char * OVS_WARN_UNUSED_RESULT
597 : 48 : ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen)
598 : : {
599 : 48 : int n = 0;
600 : :
601 : 48 : char *error = ipv6_parse_cidr_len(s, &n, ip, plen);
602 [ + - ][ - + ]: 48 : if (!error && s[n]) {
603 : 0 : return xasprintf("%s: invalid IPv6 address", s);
604 : : }
605 : 48 : return error;
606 : : }
607 : :
608 : : /* Stores the string representation of the IPv6 address 'addr' into the
609 : : * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
610 : : * bytes long. */
611 : : void
612 : 3505 : ipv6_format_addr(const struct in6_addr *addr, struct ds *s)
613 : : {
614 : : char *dst;
615 : :
616 : 3505 : ds_reserve(s, s->length + INET6_ADDRSTRLEN);
617 : :
618 : 3505 : dst = s->string + s->length;
619 : 3505 : inet_ntop(AF_INET6, addr, dst, INET6_ADDRSTRLEN);
620 : 3505 : s->length += strlen(dst);
621 : 3505 : }
622 : :
623 : : /* Same as print_ipv6_addr, but optionally encloses the address in square
624 : : * brackets. */
625 : : void
626 : 18 : ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *s,
627 : : bool bracket)
628 : : {
629 [ + + ]: 18 : if (bracket) {
630 : 6 : ds_put_char(s, '[');
631 : : }
632 : 18 : ipv6_format_addr(addr, s);
633 [ + + ]: 18 : if (bracket) {
634 : 6 : ds_put_char(s, ']');
635 : : }
636 : 18 : }
637 : :
638 : : void
639 : 6 : ipv6_format_mapped(const struct in6_addr *addr, struct ds *s)
640 : : {
641 [ + + ][ + - ]: 6 : if (IN6_IS_ADDR_V4MAPPED(addr)) {
[ + + ][ + + ]
642 : 3 : ds_put_format(s, IP_FMT, addr->s6_addr[12], addr->s6_addr[13],
643 : 6 : addr->s6_addr[14], addr->s6_addr[15]);
644 : : } else {
645 : 3 : ipv6_format_addr(addr, s);
646 : : }
647 : 6 : }
648 : :
649 : : void
650 : 3404 : ipv6_format_masked(const struct in6_addr *addr, const struct in6_addr *mask,
651 : : struct ds *s)
652 : : {
653 : 3404 : ipv6_format_addr(addr, s);
654 [ + + ][ + + ]: 3404 : if (mask && !ipv6_mask_is_exact(mask)) {
655 [ + + ]: 421 : if (ipv6_is_cidr(mask)) {
656 : 419 : int cidr_bits = ipv6_count_cidr_bits(mask);
657 : 419 : ds_put_format(s, "/%d", cidr_bits);
658 : : } else {
659 : 2 : ds_put_char(s, '/');
660 : 2 : ipv6_format_addr(mask, s);
661 : : }
662 : : }
663 : 3404 : }
664 : :
665 : : /* Stores the string representation of the IPv6 address 'addr' into the
666 : : * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
667 : : * bytes long. If addr is IPv4-mapped, store an IPv4 dotted-decimal string. */
668 : : const char *
669 : 6762 : ipv6_string_mapped(char *addr_str, const struct in6_addr *addr)
670 : : {
671 : : ovs_be32 ip;
672 : 6762 : ip = in6_addr_get_mapped_ipv4(addr);
673 [ + + ]: 6762 : if (ip) {
674 : 4827 : return inet_ntop(AF_INET, &ip, addr_str, INET6_ADDRSTRLEN);
675 : : } else {
676 : 6762 : return inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
677 : : }
678 : : }
679 : :
680 : : #ifdef s6_addr32
681 : : #define s6_addrX s6_addr32
682 : : #define IPV6_FOR_EACH(VAR) for (int VAR = 0; VAR < 4; VAR++)
683 : : #else
684 : : #define s6_addrX s6_addr
685 : : #define IPV6_FOR_EACH(VAR) for (int VAR = 0; VAR < 16; VAR++)
686 : : #endif
687 : :
688 : : struct in6_addr
689 : 130751 : ipv6_addr_bitand(const struct in6_addr *a, const struct in6_addr *b)
690 : : {
691 : : struct in6_addr dst;
692 [ + + ]: 653755 : IPV6_FOR_EACH (i) {
693 : 523004 : dst.s6_addrX[i] = a->s6_addrX[i] & b->s6_addrX[i];
694 : : }
695 : 130751 : return dst;
696 : : }
697 : :
698 : : struct in6_addr
699 : 70 : ipv6_addr_bitxor(const struct in6_addr *a, const struct in6_addr *b)
700 : : {
701 : : struct in6_addr dst;
702 [ + + ]: 350 : IPV6_FOR_EACH (i) {
703 : 280 : dst.s6_addrX[i] = a->s6_addrX[i] ^ b->s6_addrX[i];
704 : : }
705 : 70 : return dst;
706 : : }
707 : :
708 : : bool
709 : 0 : ipv6_is_zero(const struct in6_addr *a)
710 : : {
711 [ # # ]: 0 : IPV6_FOR_EACH (i) {
712 [ # # ]: 0 : if (a->s6_addrX[i]) {
713 : 0 : return false;
714 : : }
715 : : }
716 : 0 : return true;
717 : : }
718 : :
719 : : /* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N
720 : : * low-order 0-bits. */
721 : : struct in6_addr
722 : 53362 : ipv6_create_mask(int mask)
723 : : {
724 : : struct in6_addr netmask;
725 : 53362 : uint8_t *netmaskp = &netmask.s6_addr[0];
726 : :
727 : 53362 : memset(&netmask, 0, sizeof netmask);
728 [ + + ]: 519191 : while (mask > 8) {
729 : 465829 : *netmaskp = 0xff;
730 : 465829 : netmaskp++;
731 : 465829 : mask -= 8;
732 : : }
733 : :
734 [ + + ]: 53362 : if (mask) {
735 : 53339 : *netmaskp = 0xff << (8 - mask);
736 : : }
737 : :
738 : 53362 : return netmask;
739 : : }
740 : :
741 : : /* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6
742 : : * address that it specifies, that is, the number of 1-bits in 'netmask'.
743 : : * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()).
744 : : *
745 : : * If 'netmask' is not a CIDR netmask (see ipv6_is_cidr()), the return value
746 : : * will still be in the valid range but isn't otherwise meaningful. */
747 : : int
748 : 1696 : ipv6_count_cidr_bits(const struct in6_addr *netmask)
749 : : {
750 : : int i;
751 : 1696 : int count = 0;
752 : 1696 : const uint8_t *netmaskp = &netmask->s6_addr[0];
753 : :
754 [ + + ]: 21605 : for (i=0; i<16; i++) {
755 [ + + ]: 20665 : if (netmaskp[i] == 0xff) {
756 : 19909 : count += 8;
757 : : } else {
758 : : uint8_t nm;
759 : :
760 [ + + ]: 801 : for(nm = netmaskp[i]; nm; nm <<= 1) {
761 : 45 : count++;
762 : : }
763 : 756 : break;
764 : : }
765 : :
766 : : }
767 : :
768 : 1696 : return count;
769 : : }
770 : :
771 : : /* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N
772 : : * high-order 1-bits and 128-N low-order 0-bits. */
773 : : bool
774 : 1694 : ipv6_is_cidr(const struct in6_addr *netmask)
775 : : {
776 : 1694 : const uint8_t *netmaskp = &netmask->s6_addr[0];
777 : : int i;
778 : :
779 [ + + ]: 22314 : for (i=0; i<16; i++) {
780 [ + + ]: 20625 : if (netmaskp[i] != 0xff) {
781 : 756 : uint8_t x = ~netmaskp[i];
782 [ + + ]: 756 : if (x & (x + 1)) {
783 : 1 : return false;
784 : : }
785 [ + + ]: 7223 : while (++i < 16) {
786 [ + + ]: 6472 : if (netmaskp[i]) {
787 : 4 : return false;
788 : : }
789 : : }
790 : : }
791 : : }
792 : :
793 : 1689 : return true;
794 : : }
795 : :
796 : : /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
797 : : * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
798 : : * in 'b' and returned. This payload may be populated with appropriate
799 : : * information by the caller. Sets 'b''s 'frame' pointer and 'l3' offset to
800 : : * the Ethernet header and payload respectively. Aligns b->l3 on a 32-bit
801 : : * boundary.
802 : : *
803 : : * The returned packet has enough headroom to insert an 802.1Q VLAN header if
804 : : * desired. */
805 : : void *
806 : 7905 : eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,
807 : : const struct eth_addr eth_src, uint16_t eth_type,
808 : : size_t size)
809 : : {
810 : : void *data;
811 : : struct eth_header *eth;
812 : :
813 : 7905 : dp_packet_clear(b);
814 : :
815 : : /* The magic 2 here ensures that the L3 header (when it is added later)
816 : : * will be 32-bit aligned. */
817 : 7905 : dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);
818 : 7905 : dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
819 : 7905 : eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);
820 : 7905 : data = dp_packet_put_zeros(b, size);
821 : :
822 : 7905 : eth->eth_dst = eth_dst;
823 : 7905 : eth->eth_src = eth_src;
824 : 7905 : eth->eth_type = htons(eth_type);
825 : :
826 : 7905 : dp_packet_reset_offsets(b);
827 : 7905 : dp_packet_set_l3(b, data);
828 : :
829 : 7905 : return data;
830 : : }
831 : :
832 : : static void
833 : 88 : packet_set_ipv4_addr(struct dp_packet *packet,
834 : : ovs_16aligned_be32 *addr, ovs_be32 new_addr)
835 : : {
836 : 88 : struct ip_header *nh = dp_packet_l3(packet);
837 : 88 : ovs_be32 old_addr = get_16aligned_be32(addr);
838 : 88 : size_t l4_size = dp_packet_l4_size(packet);
839 : :
840 [ + + ][ + - ]: 141 : if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
841 : 53 : struct tcp_header *th = dp_packet_l4(packet);
842 : :
843 : 53 : th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr);
844 [ + + ][ + - ]: 35 : } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) {
845 : 15 : struct udp_header *uh = dp_packet_l4(packet);
846 : :
847 [ + + ]: 15 : if (uh->udp_csum) {
848 : 11 : uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr);
849 [ - + ]: 11 : if (!uh->udp_csum) {
850 : 0 : uh->udp_csum = htons(0xffff);
851 : : }
852 : : }
853 : : }
854 : 88 : nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr);
855 : 88 : put_16aligned_be32(addr, new_addr);
856 : 88 : }
857 : :
858 : : /* Returns true, if packet contains at least one routing header where
859 : : * segements_left > 0.
860 : : *
861 : : * This function assumes that L3 and L4 offsets are set in the packet. */
862 : : static bool
863 : 6 : packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr)
864 : : {
865 : : const struct ovs_16aligned_ip6_hdr *nh;
866 : : size_t len;
867 : : size_t remaining;
868 : 6 : uint8_t *data = dp_packet_l3(packet);
869 : :
870 : 6 : remaining = packet->l4_ofs - packet->l3_ofs;
871 [ - + ]: 6 : if (remaining < sizeof *nh) {
872 : 0 : return false;
873 : : }
874 : 6 : nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data);
875 : 6 : data += sizeof *nh;
876 : 6 : remaining -= sizeof *nh;
877 : 6 : *nexthdr = nh->ip6_nxt;
878 : :
879 : : while (1) {
880 [ + - ]: 6 : if ((*nexthdr != IPPROTO_HOPOPTS)
881 [ + - ]: 6 : && (*nexthdr != IPPROTO_ROUTING)
882 [ + - ]: 6 : && (*nexthdr != IPPROTO_DSTOPTS)
883 [ + - ]: 6 : && (*nexthdr != IPPROTO_AH)
884 [ + - ]: 6 : && (*nexthdr != IPPROTO_FRAGMENT)) {
885 : : /* It's either a terminal header (e.g., TCP, UDP) or one we
886 : : * don't understand. In either case, we're done with the
887 : : * packet, so use it to fill in 'nw_proto'. */
888 : 6 : break;
889 : : }
890 : :
891 : : /* We only verify that at least 8 bytes of the next header are
892 : : * available, but many of these headers are longer. Ensure that
893 : : * accesses within the extension header are within those first 8
894 : : * bytes. All extension headers are required to be at least 8
895 : : * bytes. */
896 [ # # ]: 0 : if (remaining < 8) {
897 : 0 : return false;
898 : : }
899 : :
900 [ # # ]: 0 : if (*nexthdr == IPPROTO_AH) {
901 : : /* A standard AH definition isn't available, but the fields
902 : : * we care about are in the same location as the generic
903 : : * option header--only the header length is calculated
904 : : * differently. */
905 : 0 : const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
906 : :
907 : 0 : *nexthdr = ext_hdr->ip6e_nxt;
908 : 0 : len = (ext_hdr->ip6e_len + 2) * 4;
909 [ # # ]: 0 : } else if (*nexthdr == IPPROTO_FRAGMENT) {
910 : 0 : const struct ovs_16aligned_ip6_frag *frag_hdr
911 : : = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data);
912 : :
913 : 0 : *nexthdr = frag_hdr->ip6f_nxt;
914 : 0 : len = sizeof *frag_hdr;
915 [ # # ]: 0 : } else if (*nexthdr == IPPROTO_ROUTING) {
916 : 0 : const struct ip6_rthdr *rh = (struct ip6_rthdr *)data;
917 : :
918 [ # # ]: 0 : if (rh->ip6r_segleft > 0) {
919 : 0 : return true;
920 : : }
921 : :
922 : 0 : *nexthdr = rh->ip6r_nxt;
923 : 0 : len = (rh->ip6r_len + 1) * 8;
924 : : } else {
925 : 0 : const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;
926 : :
927 : 0 : *nexthdr = ext_hdr->ip6e_nxt;
928 : 0 : len = (ext_hdr->ip6e_len + 1) * 8;
929 : : }
930 : :
931 [ # # ]: 0 : if (remaining < len) {
932 : 0 : return false;
933 : : }
934 : 0 : remaining -= len;
935 : 0 : data += len;
936 : 0 : }
937 : :
938 : 6 : return false;
939 : : }
940 : :
941 : : static void
942 : 19 : packet_update_csum128(struct dp_packet *packet, uint8_t proto,
943 : : ovs_16aligned_be32 addr[4], const ovs_be32 new_addr[4])
944 : : {
945 : 19 : size_t l4_size = dp_packet_l4_size(packet);
946 : :
947 [ - + ][ # # ]: 19 : if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
948 : 0 : struct tcp_header *th = dp_packet_l4(packet);
949 : :
950 : 0 : th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr);
951 [ + + ][ + - ]: 21 : } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
952 : 2 : struct udp_header *uh = dp_packet_l4(packet);
953 : :
954 [ + - ]: 2 : if (uh->udp_csum) {
955 : 2 : uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr);
956 [ - + ]: 2 : if (!uh->udp_csum) {
957 : 0 : uh->udp_csum = htons(0xffff);
958 : : }
959 : : }
960 [ + - ][ + - ]: 17 : } else if (proto == IPPROTO_ICMPV6 &&
961 : : l4_size >= sizeof(struct icmp6_header)) {
962 : 17 : struct icmp6_header *icmp = dp_packet_l4(packet);
963 : :
964 : 17 : icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);
965 : : }
966 : 19 : }
967 : :
968 : : static void
969 : 19 : packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,
970 : : ovs_16aligned_be32 addr[4], const ovs_be32 new_addr[4],
971 : : bool recalculate_csum)
972 : : {
973 [ + - ]: 19 : if (recalculate_csum) {
974 : 19 : packet_update_csum128(packet, proto, addr, new_addr);
975 : : }
976 : 19 : memcpy(addr, new_addr, sizeof(ovs_be32[4]));
977 : 19 : }
978 : :
979 : : static void
980 : 6 : packet_set_ipv6_flow_label(ovs_16aligned_be32 *flow_label, ovs_be32 flow_key)
981 : : {
982 : 6 : ovs_be32 old_label = get_16aligned_be32(flow_label);
983 : 6 : ovs_be32 new_label = (old_label & htonl(~IPV6_LABEL_MASK)) | flow_key;
984 : 6 : put_16aligned_be32(flow_label, new_label);
985 : 6 : }
986 : :
987 : : static void
988 : 6 : packet_set_ipv6_tc(ovs_16aligned_be32 *flow_label, uint8_t tc)
989 : : {
990 : 6 : ovs_be32 old_label = get_16aligned_be32(flow_label);
991 : 6 : ovs_be32 new_label = (old_label & htonl(0xF00FFFFF)) | htonl(tc << 20);
992 : 6 : put_16aligned_be32(flow_label, new_label);
993 : 6 : }
994 : :
995 : : /* Modifies the IPv4 header fields of 'packet' to be consistent with 'src',
996 : : * 'dst', 'tos', and 'ttl'. Updates 'packet''s L4 checksums as appropriate.
997 : : * 'packet' must contain a valid IPv4 packet with correctly populated l[347]
998 : : * markers. */
999 : : void
1000 : 1269 : packet_set_ipv4(struct dp_packet *packet, ovs_be32 src, ovs_be32 dst,
1001 : : uint8_t tos, uint8_t ttl)
1002 : : {
1003 : 1269 : struct ip_header *nh = dp_packet_l3(packet);
1004 : :
1005 [ + + ]: 1269 : if (get_16aligned_be32(&nh->ip_src) != src) {
1006 : 55 : packet_set_ipv4_addr(packet, &nh->ip_src, src);
1007 : : }
1008 : :
1009 [ + + ]: 1269 : if (get_16aligned_be32(&nh->ip_dst) != dst) {
1010 : 33 : packet_set_ipv4_addr(packet, &nh->ip_dst, dst);
1011 : : }
1012 : :
1013 [ + + ]: 1269 : if (nh->ip_tos != tos) {
1014 : 6 : uint8_t *field = &nh->ip_tos;
1015 : :
1016 : 6 : nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field),
1017 : 6 : htons((uint16_t) tos));
1018 : 6 : *field = tos;
1019 : : }
1020 : :
1021 [ + + ]: 1269 : if (nh->ip_ttl != ttl) {
1022 : 1185 : uint8_t *field = &nh->ip_ttl;
1023 : :
1024 : 1185 : nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),
1025 : 1185 : htons(ttl << 8));
1026 : 1185 : *field = ttl;
1027 : : }
1028 : 1269 : }
1029 : :
1030 : : /* Modifies the IPv6 header fields of 'packet' to be consistent with 'src',
1031 : : * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as
1032 : : * appropriate. 'packet' must contain a valid IPv6 packet with correctly
1033 : : * populated l[34] offsets. */
1034 : : void
1035 : 6 : packet_set_ipv6(struct dp_packet *packet, const ovs_be32 src[4],
1036 : : const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl,
1037 : : uint8_t key_hl)
1038 : : {
1039 : 6 : struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
1040 : 6 : uint8_t proto = 0;
1041 : : bool rh_present;
1042 : :
1043 : 6 : rh_present = packet_rh_present(packet, &proto);
1044 : :
1045 [ + - ]: 6 : if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) {
1046 : 6 : packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32, src, true);
1047 : : }
1048 : :
1049 [ + - ]: 6 : if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) {
1050 : 6 : packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst,
1051 : : !rh_present);
1052 : : }
1053 : :
1054 : 6 : packet_set_ipv6_tc(&nh->ip6_flow, key_tc);
1055 : 6 : packet_set_ipv6_flow_label(&nh->ip6_flow, key_fl);
1056 : 6 : nh->ip6_hlim = key_hl;
1057 : 6 : }
1058 : :
1059 : : static void
1060 : 44 : packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)
1061 : : {
1062 [ + + ]: 44 : if (*port != new_port) {
1063 : 23 : *csum = recalc_csum16(*csum, *port, new_port);
1064 : 23 : *port = new_port;
1065 : : }
1066 : 44 : }
1067 : :
1068 : : /* Sets the TCP source and destination port ('src' and 'dst' respectively) of
1069 : : * the TCP header contained in 'packet'. 'packet' must be a valid TCP packet
1070 : : * with its l4 offset properly populated. */
1071 : : void
1072 : 14 : packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
1073 : : {
1074 : 14 : struct tcp_header *th = dp_packet_l4(packet);
1075 : :
1076 : 14 : packet_set_port(&th->tcp_src, src, &th->tcp_csum);
1077 : 14 : packet_set_port(&th->tcp_dst, dst, &th->tcp_csum);
1078 : 14 : }
1079 : :
1080 : : /* Sets the UDP source and destination port ('src' and 'dst' respectively) of
1081 : : * the UDP header contained in 'packet'. 'packet' must be a valid UDP packet
1082 : : * with its l4 offset properly populated. */
1083 : : void
1084 : 10 : packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
1085 : : {
1086 : 10 : struct udp_header *uh = dp_packet_l4(packet);
1087 : :
1088 [ + + ]: 10 : if (uh->udp_csum) {
1089 : 8 : packet_set_port(&uh->udp_src, src, &uh->udp_csum);
1090 : 8 : packet_set_port(&uh->udp_dst, dst, &uh->udp_csum);
1091 : :
1092 [ - + ]: 8 : if (!uh->udp_csum) {
1093 : 8 : uh->udp_csum = htons(0xffff);
1094 : : }
1095 : : } else {
1096 : 2 : uh->udp_src = src;
1097 : 2 : uh->udp_dst = dst;
1098 : : }
1099 : 10 : }
1100 : :
1101 : : /* Sets the SCTP source and destination port ('src' and 'dst' respectively) of
1102 : : * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet
1103 : : * with its l4 offset properly populated. */
1104 : : void
1105 : 7 : packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)
1106 : : {
1107 : 7 : struct sctp_header *sh = dp_packet_l4(packet);
1108 : : ovs_be32 old_csum, old_correct_csum, new_csum;
1109 : 7 : uint16_t tp_len = dp_packet_l4_size(packet);
1110 : :
1111 : 7 : old_csum = get_16aligned_be32(&sh->sctp_csum);
1112 : 7 : put_16aligned_be32(&sh->sctp_csum, 0);
1113 : 7 : old_correct_csum = crc32c((void *)sh, tp_len);
1114 : :
1115 : 7 : sh->sctp_src = src;
1116 : 7 : sh->sctp_dst = dst;
1117 : :
1118 : 7 : new_csum = crc32c((void *)sh, tp_len);
1119 : 7 : put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum ^ new_csum);
1120 : 7 : }
1121 : :
1122 : : /* Sets the ICMP type and code of the ICMP header contained in 'packet'.
1123 : : * 'packet' must be a valid ICMP packet with its l4 offset properly
1124 : : * populated. */
1125 : : void
1126 : 4 : packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)
1127 : : {
1128 : 4 : struct icmp_header *ih = dp_packet_l4(packet);
1129 : 4 : ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code);
1130 : 4 : ovs_be16 new_tc = htons(type << 8 | code);
1131 : :
1132 [ + - ]: 4 : if (orig_tc != new_tc) {
1133 : 4 : ih->icmp_type = type;
1134 : 4 : ih->icmp_code = code;
1135 : :
1136 : 4 : ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc);
1137 : : }
1138 : 4 : }
1139 : :
1140 : : void
1141 : 8 : packet_set_nd(struct dp_packet *packet, const ovs_be32 target[4],
1142 : : const struct eth_addr sll, const struct eth_addr tll)
1143 : : {
1144 : : struct ovs_nd_msg *ns;
1145 : : struct ovs_nd_opt *nd_opt;
1146 : 8 : int bytes_remain = dp_packet_l4_size(packet);
1147 : :
1148 [ - + ]: 8 : if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
1149 : 0 : return;
1150 : : }
1151 : :
1152 : 8 : ns = dp_packet_l4(packet);
1153 : 8 : nd_opt = &ns->options[0];
1154 : 8 : bytes_remain -= sizeof(*ns);
1155 : :
1156 [ + + ]: 8 : if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {
1157 : 7 : packet_set_ipv6_addr(packet, IPPROTO_ICMPV6,
1158 : 7 : ns->target.be32,
1159 : : target, true);
1160 : : }
1161 : :
1162 [ + - ][ + - ]: 8 : while (bytes_remain >= ND_OPT_LEN && nd_opt->nd_opt_len != 0) {
1163 [ + + ]: 8 : if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR
1164 [ + - ]: 6 : && nd_opt->nd_opt_len == 1) {
1165 [ + - ]: 6 : if (!eth_addr_equals(nd_opt->nd_opt_mac, sll)) {
1166 : 6 : ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
1167 : :
1168 : 6 : *csum = recalc_csum48(*csum, nd_opt->nd_opt_mac, sll);
1169 : 6 : nd_opt->nd_opt_mac = sll;
1170 : : }
1171 : :
1172 : : /* A packet can only contain one SLL or TLL option */
1173 : 6 : break;
1174 [ + - ]: 2 : } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR
1175 [ + - ]: 2 : && nd_opt->nd_opt_len == 1) {
1176 [ + - ]: 2 : if (!eth_addr_equals(nd_opt->nd_opt_mac, tll)) {
1177 : 2 : ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
1178 : :
1179 : 2 : *csum = recalc_csum48(*csum, nd_opt->nd_opt_mac, tll);
1180 : 2 : nd_opt->nd_opt_mac = tll;
1181 : : }
1182 : :
1183 : : /* A packet can only contain one SLL or TLL option */
1184 : 2 : break;
1185 : : }
1186 : :
1187 : 0 : nd_opt += nd_opt->nd_opt_len;
1188 : 0 : bytes_remain -= nd_opt->nd_opt_len * ND_OPT_LEN;
1189 : : }
1190 : : }
1191 : :
1192 : : const char *
1193 : 2455 : packet_tcp_flag_to_string(uint32_t flag)
1194 : : {
1195 [ + + + + : 2455 : switch (flag) {
+ + + + +
+ + + + ]
1196 : : case TCP_FIN:
1197 : 309 : return "fin";
1198 : : case TCP_SYN:
1199 : 381 : return "syn";
1200 : : case TCP_RST:
1201 : 293 : return "rst";
1202 : : case TCP_PSH:
1203 : 268 : return "psh";
1204 : : case TCP_ACK:
1205 : 1105 : return "ack";
1206 : : case TCP_URG:
1207 : 13 : return "urg";
1208 : : case TCP_ECE:
1209 : 4 : return "ece";
1210 : : case TCP_CWR:
1211 : 4 : return "cwr";
1212 : : case TCP_NS:
1213 : 6 : return "ns";
1214 : : case 0x200:
1215 : 4 : return "[200]";
1216 : : case 0x400:
1217 : 4 : return "[400]";
1218 : : case 0x800:
1219 : 4 : return "[800]";
1220 : : default:
1221 : 60 : return NULL;
1222 : : }
1223 : : }
1224 : :
1225 : : /* Appends a string representation of the TCP flags value 'tcp_flags'
1226 : : * (e.g. from struct flow.tcp_flags or obtained via TCP_FLAGS) to 's', in the
1227 : : * format used by tcpdump. */
1228 : : void
1229 : 54 : packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags)
1230 : : {
1231 [ - + ]: 54 : if (!tcp_flags) {
1232 : 0 : ds_put_cstr(s, "none");
1233 : 0 : return;
1234 : : }
1235 : :
1236 [ + + ]: 54 : if (tcp_flags & TCP_SYN) {
1237 : 24 : ds_put_char(s, 'S');
1238 : : }
1239 [ + - ]: 54 : if (tcp_flags & TCP_FIN) {
1240 : 54 : ds_put_char(s, 'F');
1241 : : }
1242 [ + - ]: 54 : if (tcp_flags & TCP_PSH) {
1243 : 54 : ds_put_char(s, 'P');
1244 : : }
1245 [ - + ]: 54 : if (tcp_flags & TCP_RST) {
1246 : 0 : ds_put_char(s, 'R');
1247 : : }
1248 [ - + ]: 54 : if (tcp_flags & TCP_URG) {
1249 : 0 : ds_put_char(s, 'U');
1250 : : }
1251 [ + - ]: 54 : if (tcp_flags & TCP_ACK) {
1252 : 54 : ds_put_char(s, '.');
1253 : : }
1254 [ - + ]: 54 : if (tcp_flags & TCP_ECE) {
1255 : 0 : ds_put_cstr(s, "E");
1256 : : }
1257 [ - + ]: 54 : if (tcp_flags & TCP_CWR) {
1258 : 0 : ds_put_cstr(s, "C");
1259 : : }
1260 [ - + ]: 54 : if (tcp_flags & TCP_NS) {
1261 : 0 : ds_put_cstr(s, "N");
1262 : : }
1263 [ - + ]: 54 : if (tcp_flags & 0x200) {
1264 : 0 : ds_put_cstr(s, "[200]");
1265 : : }
1266 [ - + ]: 54 : if (tcp_flags & 0x400) {
1267 : 0 : ds_put_cstr(s, "[400]");
1268 : : }
1269 [ - + ]: 54 : if (tcp_flags & 0x800) {
1270 : 0 : ds_put_cstr(s, "[800]");
1271 : : }
1272 : : }
1273 : :
1274 : : #define ARP_PACKET_SIZE (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
1275 : : ARP_ETH_HEADER_LEN)
1276 : :
1277 : : /* Clears 'b' and replaces its contents by an ARP frame with the specified
1278 : : * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'. The outer
1279 : : * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
1280 : : * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
1281 : : * 'broadcast' is true. Points the L3 header to the ARP header. */
1282 : : void
1283 : 9 : compose_arp(struct dp_packet *b, uint16_t arp_op,
1284 : : const struct eth_addr arp_sha, const struct eth_addr arp_tha,
1285 : : bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa)
1286 : : {
1287 : 9 : compose_arp__(b);
1288 : :
1289 : 9 : struct eth_header *eth = dp_packet_l2(b);
1290 [ + - ]: 9 : eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;
1291 : 9 : eth->eth_src = arp_sha;
1292 : :
1293 : 9 : struct arp_eth_header *arp = dp_packet_l3(b);
1294 : 9 : arp->ar_op = htons(arp_op);
1295 : 9 : arp->ar_sha = arp_sha;
1296 : 9 : arp->ar_tha = arp_tha;
1297 : 9 : put_16aligned_be32(&arp->ar_spa, arp_spa);
1298 : 9 : put_16aligned_be32(&arp->ar_tpa, arp_tpa);
1299 : 9 : }
1300 : :
1301 : : /* Clears 'b' and replaces its contents by an ARP frame. Sets the fields in
1302 : : * the Ethernet and ARP headers that are fixed for ARP frames to those fixed
1303 : : * values, and zeroes the other fields. Points the L3 header to the ARP
1304 : : * header. */
1305 : : void
1306 : 226 : compose_arp__(struct dp_packet *b)
1307 : : {
1308 : 226 : dp_packet_clear(b);
1309 : 226 : dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE);
1310 : 226 : dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
1311 : :
1312 : 226 : struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth);
1313 : 226 : eth->eth_type = htons(ETH_TYPE_ARP);
1314 : :
1315 : 226 : struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp);
1316 : 226 : arp->ar_hrd = htons(ARP_HRD_ETHERNET);
1317 : 226 : arp->ar_pro = htons(ARP_PRO_IP);
1318 : 226 : arp->ar_hln = sizeof arp->ar_sha;
1319 : 226 : arp->ar_pln = sizeof arp->ar_spa;
1320 : :
1321 : 226 : dp_packet_reset_offsets(b);
1322 : 226 : dp_packet_set_l3(b, arp);
1323 : 226 : }
1324 : :
1325 : : /* This function expects packet with ethernet header with correct
1326 : : * l3 pointer set. */
1327 : : static void *
1328 : 5 : compose_ipv6(struct dp_packet *packet, uint8_t proto,
1329 : : const struct in6_addr *src, const struct in6_addr *dst,
1330 : : uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)
1331 : : {
1332 : : struct ip6_hdr *nh;
1333 : : void *data;
1334 : :
1335 : : /* Copy 'src' and 'dst' to temporary buffers to prevent misaligned
1336 : : * accesses. */
1337 : : ovs_be32 sbuf[4], dbuf[4];
1338 : 5 : memcpy(sbuf, src, sizeof sbuf);
1339 : 5 : memcpy(dbuf, dst, sizeof dbuf);
1340 : :
1341 : 5 : nh = dp_packet_l3(packet);
1342 : 5 : nh->ip6_vfc = 0x60;
1343 : 5 : nh->ip6_nxt = proto;
1344 : 5 : nh->ip6_plen = htons(size);
1345 : 5 : data = dp_packet_put_zeros(packet, size);
1346 : 5 : dp_packet_set_l4(packet, data);
1347 : 5 : packet_set_ipv6(packet, sbuf, dbuf, key_tc, key_fl, key_hl);
1348 : 5 : return data;
1349 : : }
1350 : :
1351 : : /* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */
1352 : : void
1353 : 4 : compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,
1354 : : const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)
1355 : : {
1356 : : struct in6_addr sn_addr;
1357 : : struct eth_addr eth_dst;
1358 : : struct ovs_nd_msg *ns;
1359 : : struct ovs_nd_opt *nd_opt;
1360 : : uint32_t icmp_csum;
1361 : :
1362 : 4 : in6_addr_solicited_node(&sn_addr, ipv6_dst);
1363 : 4 : ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
1364 : :
1365 : 4 : eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
1366 : 4 : ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,
1367 : : 0, 0, 255, ND_MSG_LEN + ND_OPT_LEN);
1368 : :
1369 : 4 : ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
1370 : 4 : ns->icmph.icmp6_code = 0;
1371 : 4 : put_16aligned_be32(&ns->rso_flags, htonl(0));
1372 : :
1373 : 4 : nd_opt = &ns->options[0];
1374 : 4 : nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
1375 : 4 : nd_opt->nd_opt_len = 1;
1376 : :
1377 : : /* Copy target address to temp buffer to prevent misaligned access. */
1378 : : ovs_be32 tbuf[4];
1379 : 4 : memcpy(tbuf, ipv6_dst->s6_addr, sizeof tbuf);
1380 : 4 : packet_set_nd(b, tbuf, eth_src, eth_addr_zero);
1381 : :
1382 : 4 : ns->icmph.icmp6_cksum = 0;
1383 : 4 : icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
1384 : 4 : ns->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, ns,
1385 : : ND_MSG_LEN + ND_OPT_LEN));
1386 : 4 : }
1387 : :
1388 : : /* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */
1389 : : void
1390 : 1 : compose_nd_na(struct dp_packet *b,
1391 : : const struct eth_addr eth_src, const struct eth_addr eth_dst,
1392 : : const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,
1393 : : ovs_be32 rso_flags)
1394 : : {
1395 : : struct ovs_nd_msg *na;
1396 : : struct ovs_nd_opt *nd_opt;
1397 : : uint32_t icmp_csum;
1398 : :
1399 : 1 : eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
1400 : 1 : na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,
1401 : : 0, 0, 255, ND_MSG_LEN + ND_OPT_LEN);
1402 : :
1403 : 1 : na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
1404 : 1 : na->icmph.icmp6_code = 0;
1405 : 1 : put_16aligned_be32(&na->rso_flags, rso_flags);
1406 : :
1407 : 1 : nd_opt = &na->options[0];
1408 : 1 : nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
1409 : 1 : nd_opt->nd_opt_len = 1;
1410 : :
1411 : : /* Copy target address to temp buffer to prevent misaligned access. */
1412 : : ovs_be32 tbuf[4];
1413 : 1 : memcpy(tbuf, ipv6_src->s6_addr, sizeof tbuf);
1414 : 1 : packet_set_nd(b, tbuf, eth_addr_zero, eth_src);
1415 : :
1416 : 1 : na->icmph.icmp6_cksum = 0;
1417 : 1 : icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
1418 : 1 : na->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, na,
1419 : : ND_MSG_LEN + ND_OPT_LEN));
1420 : 1 : }
1421 : :
1422 : : uint32_t
1423 : 5688 : packet_csum_pseudoheader(const struct ip_header *ip)
1424 : : {
1425 : 5688 : uint32_t partial = 0;
1426 : :
1427 : 5688 : partial = csum_add32(partial, get_16aligned_be32(&ip->ip_src));
1428 : 5688 : partial = csum_add32(partial, get_16aligned_be32(&ip->ip_dst));
1429 : 5688 : partial = csum_add16(partial, htons(ip->ip_proto));
1430 : 5688 : partial = csum_add16(partial, htons(ntohs(ip->ip_tot_len) -
1431 : 5688 : IP_IHL(ip->ip_ihl_ver) * 4));
1432 : :
1433 : 5688 : return partial;
1434 : : }
1435 : :
1436 : : #ifndef __CHECKER__
1437 : : uint32_t
1438 : 118 : packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6)
1439 : : {
1440 : 118 : uint32_t partial = 0;
1441 : :
1442 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[0])));
1443 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[1])));
1444 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[2])));
1445 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[3])));
1446 : :
1447 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[0])));
1448 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[1])));
1449 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[2])));
1450 : 118 : partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[3])));
1451 : :
1452 : 118 : partial = csum_add16(partial, htons(ip6->ip6_nxt));
1453 : 118 : partial = csum_add16(partial, ip6->ip6_plen);
1454 : :
1455 : 118 : return partial;
1456 : : }
1457 : : #endif
1458 : :
1459 : : void
1460 : 0 : IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6)
1461 : : {
1462 [ # # ]: 0 : if (is_ipv6) {
1463 : 0 : ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt);
1464 : :
1465 : 0 : put_16aligned_be32(ip6, get_16aligned_be32(ip6) |
1466 : 0 : htonl(IP_ECN_CE << 20));
1467 : : } else {
1468 : 0 : struct ip_header *nh = dp_packet_l3(pkt);
1469 : 0 : uint8_t tos = nh->ip_tos;
1470 : :
1471 : 0 : tos |= IP_ECN_CE;
1472 [ # # ]: 0 : if (nh->ip_tos != tos) {
1473 : 0 : nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos),
1474 : 0 : htons((uint16_t) tos));
1475 : 0 : nh->ip_tos = tos;
1476 : : }
1477 : : }
1478 : 0 : }
|