Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F118307152
tunnel.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
tunnel.py
View Options
# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
# https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/
# https://community.hetzner.com/tutorials/linux-setup-gre-tunnel
from
copy
import
deepcopy
from
netaddr
import
EUI
from
netaddr
import
mac_unix_expanded
from
random
import
getrandbits
from
vyos.ifconfig.interface
import
Interface
from
vyos.validate
import
assert_list
def
enable_to_on
(
value
):
if
value
==
'enable'
:
return
'on'
if
value
==
'disable'
:
return
'off'
raise
ValueError
(
f
'expect enable or disable but got "{value}"'
)
@Interface.register
class
_Tunnel
(
Interface
):
"""
_Tunnel: private base class for tunnels
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/tunnel.c
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ip6tunnel.c
"""
definition
=
{
**
Interface
.
definition
,
**
{
'section'
:
'tunnel'
,
'prefixes'
:
[
'tun'
,],
},
}
default
=
{
'local'
:
''
,
'remote'
:
''
,
'dev'
:
''
,
'ttl'
:
''
,
'tos'
:
''
,
'key'
:
''
,
'raw'
:
''
,
}
options
=
Interface
.
options
+
list
(
default
.
keys
())
# TODO: This is surely used for more than tunnels
# TODO: could be refactored elsewhere
_command_set
=
{
**
Interface
.
_command_set
,
**
{
'multicast'
:
{
'validate'
:
lambda
v
:
assert_list
(
v
,
[
'enable'
,
'disable'
]),
'convert'
:
enable_to_on
,
'shellcmd'
:
'ip link set dev {ifname} multicast {value}'
,
},
'allmulticast'
:
{
'validate'
:
lambda
v
:
assert_list
(
v
,
[
'enable'
,
'disable'
]),
'convert'
:
enable_to_on
,
'shellcmd'
:
'ip link set dev {ifname} allmulticast {value}'
,
},
}
}
_create_cmd
=
'ip tunnel add {ifname} mode {type}'
def
_create
(
self
):
# add " option-name option-name-value ..." for all options set
options
=
' '
.
join
([
'{} {}'
.
format
(
k
,
self
.
config
[
k
])
for
k
,
v
in
self
.
config
.
items
()
if
v
and
k
not
in
[
'ifname'
,
'type'
,
'raw'
]])
if
'raw'
in
self
.
config
:
options
+=
' '
+
' '
.
join
(
self
.
config
[
'raw'
])
self
.
_cmd
(
'{} {}'
.
format
(
self
.
_create_cmd
.
format
(
**
self
.
config
),
options
))
self
.
set_admin_state
(
'down'
)
def
change_options
(
self
):
change
=
'ip tunnel change {ifname} mode {type}'
# add " option-name option-name-value ..." for all options set
options
=
' '
.
join
([
'{} {}'
.
format
(
k
,
self
.
config
[
k
])
for
k
,
v
in
self
.
config
.
items
()
if
v
and
k
not
in
[
'ifname'
,
'type'
,
'raw'
]])
if
'raw'
in
self
.
config
:
options
+=
' '
+
' '
.
join
(
self
.
config
[
'raw'
])
self
.
_cmd
(
'{} {}'
.
format
(
change
.
format
(
**
self
.
config
),
options
))
def
get_mac
(
self
):
"""
Get current interface MAC (Media Access Contrl) address used.
NOTE: Tunnel interfaces have no "MAC" address by default. The content
of the 'address' file in /sys/class/net/device contains the
local-ip thus we generate a random MAC address instead
Example:
>>> from vyos.ifconfig import Interface
>>> Interface('eth0').get_mac()
'00:50:ab:cd:ef:00'
"""
# we choose 40 random bytes for the MAC address, this gives
# us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A')
tmp
=
EUI
(
getrandbits
(
48
))
.
value
# set locally administered bit in MAC address
tmp
|=
0xf20000000000
# convert integer to "real" MAC address representation
mac
=
EUI
(
hex
(
tmp
)
.
split
(
'x'
)[
-
1
])
# change dialect to use : as delimiter instead of -
mac
.
dialect
=
mac_unix_expanded
return
str
(
mac
)
def
update
(
self
,
config
):
""" General helper function which works on a dictionary retrived by
get_config_dict(). It's main intention is to consolidate the scattered
interface setup code and provide a single point of entry when workin
on any interface. """
# call base class first
super
()
.
update
(
config
)
# Enable/Disable of an interface must always be done at the end of the
# derived class to make use of the ref-counting set_admin_state()
# function. We will only enable the interface if 'up' was called as
# often as 'down'. This is required by some interface implementations
# as certain parameters can only be changed when the interface is
# in admin-down state. This ensures the link does not flap during
# reconfiguration.
state
=
'down'
if
'disable'
in
config
else
'up'
self
.
set_admin_state
(
state
)
class
GREIf
(
_Tunnel
):
"""
GRE: Generic Routing Encapsulation
For more information please refer to:
RFC1701, RFC1702, RFC2784
https://tools.ietf.org/html/rfc2784
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre.c
"""
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'gre'
,
'raw'
:
[
'pmtudisc'
],
# parameters that we can pass raw to ip command
},
}
# GreTap also called GRE Bridge
class
GRETapIf
(
_Tunnel
):
"""
GRETapIF: GreIF using TAP instead of TUN
https://en.wikipedia.org/wiki/TUN/TAP
"""
# no multicast, ttl or tos for gretap
definition
=
{
**
_Tunnel
.
definition
,
**
{
'bridgeable'
:
True
,
},
}
default
=
{
'type'
:
'gretap'
,
'local'
:
''
,
'remote'
:
''
,
'dev'
:
''
,
'raw'
:
[
'pmtudisc'
],
# parameters that we can pass raw to ip command
}
_create_cmd
=
'ip link add name {ifname} type {type}'
def
change_options
(
self
):
pass
class
IP6GREIf
(
_Tunnel
):
"""
IP6Gre: IPv6 Support for Generic Routing Encapsulation (GRE)
For more information please refer to:
https://tools.ietf.org/html/rfc7676
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre6.c
"""
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'ip6gre'
,
'encaplimit'
:
''
,
'hoplimit'
:
''
,
'tclass'
:
''
,
'flowlabel'
:
''
,
},
}
class
IPIPIf
(
_Tunnel
):
"""
IPIP: IP Encapsulation within IP
For more information please refer to:
https://tools.ietf.org/html/rfc2003
"""
# IPIP does not allow to pass multicast, unlike GRE
# but the interface itself can be set with multicast
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'ipip'
,
'raw'
:
[
'pmtudisc'
],
# parameters that we can pass raw to ip command
},
}
class
IPIP6If
(
_Tunnel
):
"""
IPIP6: IPv4 over IPv6 tunnel
For more information please refer to:
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_ip6tnl.c
"""
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'ipip6'
,
'encaplimit'
:
''
,
'hoplimit'
:
''
,
'tclass'
:
''
,
'flowlabel'
:
''
,
},
}
class
IP6IP6If
(
IPIP6If
):
"""
IP6IP6: IPv6 over IPv6 tunnel
For more information please refer to:
https://tools.ietf.org/html/rfc2473
"""
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'ip6ip6'
,
},
}
class
SitIf
(
_Tunnel
):
"""
Sit: Simple Internet Transition
For more information please refer to:
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_iptnl.c
"""
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'sit'
,
},
}
class
Sit6RDIf
(
SitIf
):
"""
Sit6RDIf: Simple Internet Transition with 6RD
https://en.wikipedia.org/wiki/IPv6_rapid_deployment
"""
# TODO: check if key can really be used with 6RD
default
=
{
**
_Tunnel
.
default
,
**
{
'type'
:
'6rd'
,
'6rd_prefix'
:
''
,
'6rd_relay_prefix'
:
''
,
},
}
def
_create
(
self
):
# do not call _Tunnel.create, building fully here
create
=
'ip tunnel add {ifname} mode {type} remote {remote}'
self
.
_cmd
(
create
.
format
(
**
self
.
config
))
self
.
set_interface
(
'state'
,
'down'
)
set6rd
=
'ip tunnel 6rd dev {ifname} 6rd-prefix {6rd-prefix}'
if
'6rd-relay-prefix'
in
self
.
config
:
set6rd
+=
' 6rd-relay-prefix {6rd-relay-prefix}'
self
.
_cmd
(
set6rd
.
format
(
**
self
.
config
))
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Sat, Oct 17, 12:24 AM (4 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4404138
Default Alt Text
tunnel.py (9 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment