aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip/ip46_address.h
blob: 90f766464f6b005076ae03123bf94a9156f92b96 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * Copyright (c) 2015-2019 Cisco and/or its affiliates.
 * 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 included_ip46_address_h
#define included_ip46_address_h

#include <vnet/ip/ip6_packet.h>
#include <vnet/ip/ip4_packet.h>

typedef enum
{
  IP46_TYPE_ANY,
  IP46_TYPE_BOTH = IP46_TYPE_ANY,
  IP46_TYPE_IP4,
  IP46_TYPE_IP6
} ip46_type_t;

#define IP46_N_TYPES (IP46_TYPE_IP6+2)

#define FOREACH_IP46_TYPE(_type) \
  for (_type = IP46_TYPE_IP4; _type <= IP46_TYPE_IP6; _type++)

extern u8 *format_ip46_type (u8 * s, va_list * args);

typedef CLIB_PACKED (union ip46_address_t_ {
  struct {
    u32 pad[3];
    ip4_address_t ip4;
  };
  ip6_address_t ip6;
  u8 as_u8[16];
  u64 as_u64[2];
}) ip46_address_t;


format_function_t format_ip46_address;

#define ip46_address_initializer {{{ 0 }}}

always_inline u8
ip46_address_is_ip4 (const ip46_address_t * ip46)
{
  return (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0);
}

always_inline void
ip46_address_mask_ip4 (ip46_address_t * ip46)
{
  ((ip46)->pad[0] = (ip46)->pad[1] = (ip46)->pad[2] = 0);
}

always_inline void
ip46_address_set_ip4 (ip46_address_t * ip46, const ip4_address_t * ip)
{
  ip46_address_mask_ip4 (ip46);
  ip46->ip4 = *ip;
}

always_inline void
ip46_address_reset (ip46_address_t * ip46)
{
  ip46->as_u64[0] = ip46->as_u64[1] = 0;
}

always_inline int
ip46_address_cmp (const ip46_address_t * ip46_1,
		  const ip46_address_t * ip46_2)
{
  return (memcmp (ip46_1, ip46_2, sizeof (*ip46_1)));
}

always_inline u8
ip46_address_is_zero (const ip46_address_t * ip46)
{
  return (ip46->as_u64[0] == 0 && ip46->as_u64[1] == 0);
}

always_inline u8
ip46_address_is_equal (const ip46_address_t * ip46_1,
		       const ip46_address_t * ip46_2)
{
  return ((ip46_1->as_u64[0] == ip46_2->as_u64[0]) &&
	  (ip46_1->as_u64[1] == ip46_2->as_u64[1]));
}

static_always_inline int
ip4_address_is_equal (const ip4_address_t * ip4_1,
		      const ip4_address_t * ip4_2)
{
  return (ip4_1->as_u32 == ip4_2->as_u32);
}

static_always_inline int
ip46_address_is_equal_v4 (const ip46_address_t * ip46,
			  const ip4_address_t * ip4)
{
  return (ip46->ip4.as_u32 == ip4->as_u32);
}

static_always_inline int
ip46_address_is_equal_v6 (const ip46_address_t * ip46,
			  const ip6_address_t * ip6)
{
  return ((ip46->ip6.as_u64[0] == ip6->as_u64[0]) &&
	  (ip46->ip6.as_u64[1] == ip6->as_u64[1]));
}

static_always_inline void
ip46_address_copy (ip46_address_t * dst, const ip46_address_t * src)
{
  dst->as_u64[0] = src->as_u64[0];
  dst->as_u64[1] = src->as_u64[1];
}

static_always_inline void
ip46_address_set_ip6 (ip46_address_t * dst, const ip6_address_t * src)
{
  dst->as_u64[0] = src->as_u64[0];
  dst->as_u64[1] = src->as_u64[1];
}

always_inline ip46_address_t
to_ip46 (u32 is_ipv6, u8 * buf)
{
  ip46_address_t ip;
  if (is_ipv6)
    ip.ip6 = *((ip6_address_t *) buf);
  else
    ip46_address_set_ip4 (&ip, (ip4_address_t *) buf);
  return ip;
}

always_inline ip46_type_t
ip46_address_get_type (const ip46_address_t * ip)
{
  return (ip46_address_is_ip4 (ip) ? IP46_TYPE_IP4 : IP46_TYPE_IP6);
}

always_inline uword
ip46_address_is_multicast (const ip46_address_t * a)
{
  return ip46_address_is_ip4 (a) ? ip4_address_is_multicast (&a->ip4) :
    ip6_address_is_multicast (&a->ip6);
}

extern void ip4_address_increment (ip4_address_t * i);
extern void ip6_address_increment (ip6_address_t * i);
extern void ip46_address_increment (ip46_type_t type, ip46_address_t * ip);

#endif /* included_ip46_address_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */