1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 /* Make sure the net/if.h header is included before any linux/ one */
6 #include <linux/if_arp.h>
7 #include <linux/if_vlan.h>
9 #include "parse-util.h"
10 #include "vlan-util.h"
13 static int netdev_vlan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*req
) {
17 struct ifla_vlan_flags flags
= {};
18 VLan
*v
= VLAN(netdev
);
21 r
= sd_netlink_message_append_u16(req
, IFLA_VLAN_ID
, v
->id
);
25 if (v
->protocol
>= 0) {
26 r
= sd_netlink_message_append_u16(req
, IFLA_VLAN_PROTOCOL
, htobe16(v
->protocol
));
32 flags
.mask
|= VLAN_FLAG_GVRP
;
33 SET_FLAG(flags
.flags
, VLAN_FLAG_GVRP
, v
->gvrp
);
37 flags
.mask
|= VLAN_FLAG_MVRP
;
38 SET_FLAG(flags
.flags
, VLAN_FLAG_MVRP
, v
->mvrp
);
41 if (v
->reorder_hdr
!= -1) {
42 flags
.mask
|= VLAN_FLAG_REORDER_HDR
;
43 SET_FLAG(flags
.flags
, VLAN_FLAG_REORDER_HDR
, v
->reorder_hdr
);
46 if (v
->loose_binding
!= -1) {
47 flags
.mask
|= VLAN_FLAG_LOOSE_BINDING
;
48 SET_FLAG(flags
.flags
, VLAN_FLAG_LOOSE_BINDING
, v
->loose_binding
);
51 r
= sd_netlink_message_append_data(req
, IFLA_VLAN_FLAGS
, &flags
, sizeof(struct ifla_vlan_flags
));
55 if (!set_isempty(v
->egress_qos_maps
)) {
56 struct ifla_vlan_qos_mapping
*m
;
58 r
= sd_netlink_message_open_container(req
, IFLA_VLAN_EGRESS_QOS
);
62 SET_FOREACH(m
, v
->egress_qos_maps
) {
63 r
= sd_netlink_message_append_data(req
, IFLA_VLAN_QOS_MAPPING
, m
, sizeof(struct ifla_vlan_qos_mapping
));
68 r
= sd_netlink_message_close_container(req
);
73 if (!set_isempty(v
->ingress_qos_maps
)) {
74 struct ifla_vlan_qos_mapping
*m
;
76 r
= sd_netlink_message_open_container(req
, IFLA_VLAN_INGRESS_QOS
);
80 SET_FOREACH(m
, v
->ingress_qos_maps
) {
81 r
= sd_netlink_message_append_data(req
, IFLA_VLAN_QOS_MAPPING
, m
, sizeof(struct ifla_vlan_qos_mapping
));
86 r
= sd_netlink_message_close_container(req
);
94 static void vlan_qos_maps_hash_func(const struct ifla_vlan_qos_mapping
*x
, struct siphash
*state
) {
95 siphash24_compress_typesafe(x
->from
, state
);
96 siphash24_compress_typesafe(x
->to
, state
);
99 static int vlan_qos_maps_compare_func(const struct ifla_vlan_qos_mapping
*a
, const struct ifla_vlan_qos_mapping
*b
) {
102 r
= CMP(a
->from
, b
->from
);
106 return CMP(a
->to
, b
->to
);
109 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
110 vlan_qos_maps_hash_ops
,
111 struct ifla_vlan_qos_mapping
,
112 vlan_qos_maps_hash_func
,
113 vlan_qos_maps_compare_func
,
116 int config_parse_vlan_qos_maps(
118 const char *filename
,
121 unsigned section_line
,
128 Set
**s
= ASSERT_PTR(data
);
135 if (isempty(rvalue
)) {
140 for (const char *p
= rvalue
;;) {
141 _cleanup_free_
struct ifla_vlan_qos_mapping
*m
= NULL
;
142 _cleanup_free_
char *w
= NULL
;
145 r
= extract_first_word(&p
, &w
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_UNQUOTE
);
149 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s, ignoring: %s", lvalue
, rvalue
);
155 r
= parse_range(w
, &from
, &to
);
157 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s, ignoring: %s", lvalue
, w
);
161 m
= new(struct ifla_vlan_qos_mapping
, 1);
165 *m
= (struct ifla_vlan_qos_mapping
) {
170 r
= set_ensure_consume(s
, &vlan_qos_maps_hash_ops
, TAKE_PTR(m
));
172 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to store %s, ignoring: %s", lvalue
, w
);
178 static int netdev_vlan_verify(NetDev
*netdev
, const char *filename
) {
181 VLan
*v
= VLAN(netdev
);
183 if (v
->id
== VLANID_INVALID
) {
184 log_netdev_warning(netdev
, "VLAN without valid Id (%"PRIu16
") configured in %s.", v
->id
, filename
);
191 static void vlan_done(NetDev
*netdev
) {
192 VLan
*v
= VLAN(netdev
);
194 set_free(v
->egress_qos_maps
);
195 set_free(v
->ingress_qos_maps
);
198 static void vlan_init(NetDev
*netdev
) {
199 VLan
*v
= VLAN(netdev
);
201 v
->id
= VLANID_INVALID
;
205 v
->loose_binding
= -1;
209 const NetDevVTable vlan_vtable
= {
210 .object_size
= sizeof(VLan
),
212 .sections
= NETDEV_COMMON_SECTIONS
"VLAN\0",
213 .fill_message_create
= netdev_vlan_fill_message_create
,
214 .create_type
= NETDEV_CREATE_STACKED
,
215 .config_verify
= netdev_vlan_verify
,
217 .iftype
= ARPHRD_ETHER
,