]>
git.proxmox.com Git - mirror_ovs.git/blob - lib/vlandev.c
2 * Copyright (c) 2011 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <sys/ioctl.h>
29 VLOG_DEFINE_THIS_MODULE(vlandev
);
32 #include "rtnetlink-link.h"
33 #include <linux/if_vlan.h>
34 #include <linux/sockios.h>
35 #include "netdev-linux.h"
37 static struct nln_notifier
*vlan_cache_notifier
;
38 static struct shash vlan_devs
= SHASH_INITIALIZER(&vlan_devs
);
39 static struct shash vlan_real_devs
= SHASH_INITIALIZER(&vlan_real_devs
);
40 static bool cache_valid
;
43 vlan_cache_cb(const struct rtnetlink_link_change
*change OVS_UNUSED
,
52 const char *fn
= "/proc/net/vlan/config";
53 struct shash_node
*node
;
57 if (!vlan_cache_notifier
) {
58 vlan_cache_notifier
= rtnetlink_link_notifier_create(vlan_cache_cb
,
60 if (!vlan_cache_notifier
) {
71 * The 'name' members point to strings owned by the "shash"es so we do not
72 * free them ourselves. */
73 shash_clear_free_data(&vlan_devs
);
74 SHASH_FOR_EACH (node
, &vlan_real_devs
) {
75 struct vlan_real_dev
*vrd
= node
->data
;
77 hmap_destroy(&vrd
->vlan_devs
);
79 shash_clear_free_data(&vlan_real_devs
);
81 /* Repopulate cache. */
82 stream
= fopen(fn
, "r");
84 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
88 if (error
== ENOENT
&& !stat("/proc", &s
)) {
89 /* Probably the vlan module just isn't loaded, and probably that's
90 * because no VLAN devices have been created.
92 * Not really an error. */
96 VLOG_WARN_RL(&rl
, "%s: open failed (%s)", fn
, strerror(error
));
100 while (fgets(line
, sizeof line
, stream
)) {
101 char vlan_dev
[16], real_dev
[16];
104 if (sscanf(line
, "%15[^ |] | %d | %15s", vlan_dev
, &vid
, real_dev
) == 3
105 && vid
>= 0 && vid
<= 4095
106 && !shash_find(&vlan_devs
, vlan_dev
)) {
107 struct vlan_real_dev
*vrd
;
110 vrd
= shash_find_data(&vlan_real_devs
, real_dev
);
112 vrd
= xmalloc(sizeof *vrd
);
113 vrd
->name
= xstrdup(real_dev
);
114 hmap_init(&vrd
->vlan_devs
);
115 shash_add_nocopy(&vlan_real_devs
, vrd
->name
, vrd
);
118 vd
= xmalloc(sizeof *vd
);
119 hmap_insert(&vrd
->vlan_devs
, &vd
->hmap_node
, hash_int(vid
, 0));
120 vd
->name
= xstrdup(vlan_dev
);
123 shash_add_nocopy(&vlan_devs
, vd
->name
, vd
);
133 vlandev_get_real_devs(void)
135 return &vlan_real_devs
;
139 vlandev_get_name(const char *real_dev_name
, int vid
)
141 const struct vlan_real_dev
*real_dev
;
143 real_dev
= shash_find_data(&vlan_real_devs
, real_dev_name
);
145 const struct vlan_dev
*vlan_dev
;
147 HMAP_FOR_EACH_WITH_HASH (vlan_dev
, hmap_node
, hash_int(vid
, 0),
148 &real_dev
->vlan_devs
) {
149 if (vlan_dev
->vid
== vid
) {
150 return vlan_dev
->name
;
159 do_vlan_ioctl(const char *netdev_name
, struct vlan_ioctl_args
*via
,
160 int cmd
, const char *cmd_name
)
162 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
167 ovs_strlcpy(via
->device1
, netdev_name
, sizeof via
->device1
);
169 sock
= netdev_linux_get_af_inet_sock();
174 error
= ioctl(sock
, SIOCSIFVLAN
, via
) < 0 ? errno
: 0;
176 VLOG_WARN_RL(&rl
, "%s: VLAN ioctl %s failed (%s)",
177 netdev_name
, cmd_name
, strerror(error
));
183 vlandev_add(const char *real_dev
, int vid
)
185 struct vlan_ioctl_args via
;
188 memset(&via
, 0, sizeof via
);
191 error
= do_vlan_ioctl(real_dev
, &via
, ADD_VLAN_CMD
, "ADD_VLAN_CMD");
199 vlandev_del(const char *vlan_dev
)
201 struct vlan_ioctl_args via
;
204 memset(&via
, 0, sizeof via
);
205 error
= do_vlan_ioctl(vlan_dev
, &via
, DEL_VLAN_CMD
, "DEL_VLAN_CMD");
211 #else /* !LINUX_DATAPATH */
215 vlandev_refresh(void)
221 vlandev_get_real_devs(void)
223 static struct shash vlan_real_devs
= SHASH_INITIALIZER(&vlan_real_devs
);
225 return &vlan_real_devs
;
229 vlandev_get_name(const char *real_dev_name OVS_UNUSED
, int vid OVS_UNUSED
)
235 vlandev_add(const char *real_dev OVS_UNUSED
, int vid OVS_UNUSED
)
237 VLOG_ERR("not supported on non-Linux platform");
242 vlandev_del(const char *vlan_dev OVS_UNUSED
)
244 VLOG_ERR("not supported on non-Linux platform");