summaryrefslogtreecommitdiff
path: root/lib/byte-order.h
blob: 66d29a2b37da6e074b3abccf463be5f1f8540e63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2008, 2010, 2011, 2013, 2016 Nicira, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef BYTE_ORDER_H
#define BYTE_ORDER_H 1

#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include "openvswitch/types.h"

#ifndef __CHECKER__
#if !(defined(_WIN32) || defined(htonll))
static inline ovs_be64
htonll(uint64_t n)
{
    return htonl(1) == 1 ? n : ((uint64_t) htonl(n) << 32) | htonl(n >> 32);
}

static inline uint64_t
ntohll(ovs_be64 n)
{
    return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32);
}
#endif /* !(defined(_WIN32) || defined(htonll)) */
#else
/* Making sparse happy with these functions also makes them unreadable, so
 * don't bother to show it their implementations. */
ovs_be64 htonll(uint64_t);
uint64_t ntohll(ovs_be64);
#endif

static inline ovs_be128
hton128(const ovs_u128 src)
{
    ovs_be128 dst;

    dst.be64.hi = htonll(src.u64.hi);
    dst.be64.lo = htonll(src.u64.lo);
    return dst;
}

static inline ovs_u128
ntoh128(const ovs_be128 src)
{
    ovs_u128 dst;

    dst.u64.hi = ntohll(src.be64.hi);
    dst.u64.lo = ntohll(src.be64.lo);
    return dst;
}

static inline uint32_t
uint32_byteswap(uint32_t crc) {
    return (((crc & 0x000000ff) << 24) |
            ((crc & 0x0000ff00) <<  8) |
            ((crc & 0x00ff0000) >>  8) |
            ((crc & 0xff000000) >> 24));
}

/* These macros may substitute for htons(), htonl(), and htonll() in contexts
 * where function calls are not allowed, such as case labels.  They should not
 * be used elsewhere because all of them evaluate their argument many times. */
#if defined(WORDS_BIGENDIAN) || __CHECKER__
#define CONSTANT_HTONS(VALUE) ((OVS_FORCE ovs_be16) ((VALUE) & 0xffff))
#define CONSTANT_HTONL(VALUE) ((OVS_FORCE ovs_be32) ((VALUE) & 0xffffffff))
#define CONSTANT_HTONLL(VALUE) \
        ((OVS_FORCE ovs_be64) ((VALUE) & UINT64_C(0xffffffffffffffff)))
#else
#define CONSTANT_HTONS(VALUE)                       \
        (((((ovs_be16) (VALUE)) & 0xff00) >> 8) |   \
         ((((ovs_be16) (VALUE)) & 0x00ff) << 8))
#define CONSTANT_HTONL(VALUE)                           \
        (((((ovs_be32) (VALUE)) & 0x000000ff) << 24) |  \
         ((((ovs_be32) (VALUE)) & 0x0000ff00) <<  8) |  \
         ((((ovs_be32) (VALUE)) & 0x00ff0000) >>  8) |  \
         ((((ovs_be32) (VALUE)) & 0xff000000) >> 24))
#define CONSTANT_HTONLL(VALUE)                                           \
        (((((ovs_be64) (VALUE)) & UINT64_C(0x00000000000000ff)) << 56) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x000000000000ff00)) << 40) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x0000000000ff0000)) << 24) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x00000000ff000000)) <<  8) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x000000ff00000000)) >>  8) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x0000ff0000000000)) >> 24) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0x00ff000000000000)) >> 40) | \
         ((((ovs_be64) (VALUE)) & UINT64_C(0xff00000000000000)) >> 56))
#endif

/* Returns the ovs_be32 that you would get from:
 *
 *    union { uint8_t b[4]; ovs_be32 be32; } x = { .b = { b0, b1, b2, b3 } };
 *    return x.be32;
 *
 * but without the undefined behavior. */
static inline ovs_be32
bytes_to_be32(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
{
#if WORDS_BIGENDIAN
    uint32_t x = ((uint32_t) b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
#else
    uint32_t x = ((uint32_t) b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
#endif
    return (OVS_FORCE ovs_be32) x;
}

/* These functions zero-extend big-endian values to longer ones,
 * or truncate long big-endian value to shorter ones. */
#ifndef __CHECKER__
#if WORDS_BIGENDIAN
static inline ovs_be32 be16_to_be32(ovs_be16 x) { return x; }
static inline ovs_be64 be16_to_be64(ovs_be16 x) { return x; }
static inline ovs_be64 be32_to_be64(ovs_be32 x) { return x; }
static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x; }
static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x; }
static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x; }
#else /* !WORDS_BIGENDIAN */
static inline ovs_be32 be16_to_be32(ovs_be16 x) { return (ovs_be32) x << 16; }
static inline ovs_be64 be16_to_be64(ovs_be16 x) { return (ovs_be64) x << 48; }
static inline ovs_be64 be32_to_be64(ovs_be32 x) { return (ovs_be64) x << 32; }
static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x >> 32; }
static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x >> 48; }
static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x >> 16; }
#endif /* !WORDS_BIGENDIAN */
#else /* __CHECKER__ */
/* Making sparse happy with these functions also makes them unreadable, so
 * don't bother to show it their implementations. */
ovs_be32 be16_to_be32(ovs_be16);
ovs_be64 be16_to_be64(ovs_be16);
ovs_be64 be32_to_be64(ovs_be32);
ovs_be32 be64_to_be32(ovs_be64);
ovs_be16 be64_to_be16(ovs_be64);
ovs_be16 be32_to_be16(ovs_be32);
#endif

#endif /* byte-order.h */