mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-20 05:17:56 +00:00
TAP and Ethernet device support for IOU
This commit is contained in:
parent
41a1d16e92
commit
0e1d8e5071
@ -99,10 +99,10 @@ class ETHSW(object):
|
|||||||
|
|
||||||
Mandatory request parameters:
|
Mandatory request parameters:
|
||||||
- id (switch identifier)
|
- id (switch identifier)
|
||||||
- ports (ports settings)
|
|
||||||
|
|
||||||
Optional request parameters:
|
Optional request parameters:
|
||||||
- name (new switch name)
|
- name (new switch name)
|
||||||
|
- ports (ports settings)
|
||||||
|
|
||||||
Response parameters:
|
Response parameters:
|
||||||
- same as original request
|
- same as original request
|
||||||
@ -118,22 +118,24 @@ class ETHSW(object):
|
|||||||
log.debug("received request {}".format(request))
|
log.debug("received request {}".format(request))
|
||||||
ethsw_id = request["id"]
|
ethsw_id = request["id"]
|
||||||
ethsw = self._ethernet_switches[ethsw_id]
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
ports = request["ports"]
|
|
||||||
|
|
||||||
# update the port settings
|
if "ports" in request:
|
||||||
for port, info in ports.items():
|
ports = request["ports"]
|
||||||
vlan = info["vlan"]
|
|
||||||
port_type = info["type"]
|
# update the port settings
|
||||||
try:
|
for port, info in ports.items():
|
||||||
if port_type == "access":
|
vlan = info["vlan"]
|
||||||
ethsw.set_access_port(int(port), vlan)
|
port_type = info["type"]
|
||||||
elif port_type == "dot1q":
|
try:
|
||||||
ethsw.set_dot1q_port(int(port), vlan)
|
if port_type == "access":
|
||||||
elif port_type == "qinq":
|
ethsw.set_access_port(int(port), vlan)
|
||||||
ethsw.set_qinq_port(int(port), vlan)
|
elif port_type == "dot1q":
|
||||||
except DynamipsError as e:
|
ethsw.set_dot1q_port(int(port), vlan)
|
||||||
self.send_custom_error(str(e))
|
elif port_type == "qinq":
|
||||||
return
|
ethsw.set_qinq_port(int(port), vlan)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
# rename the switch if requested
|
# rename the switch if requested
|
||||||
if "name" in request and ethsw.name != request["name"]:
|
if "name" in request and ethsw.name != request["name"]:
|
||||||
|
@ -356,11 +356,11 @@ class DynamipsHypervisor(object):
|
|||||||
try:
|
try:
|
||||||
if ":" in host:
|
if ":" in host:
|
||||||
# IPv6 address support
|
# IPv6 address support
|
||||||
s = socket.socket(socket.AF_INET6, socket_type)
|
with socket.socket(socket.AF_INET6, socket_type) as s:
|
||||||
|
s.bind((host, port)) # the port is available if bind is a success
|
||||||
else:
|
else:
|
||||||
s = socket.socket(socket.AF_INET, socket_type)
|
with socket.socket(socket.AF_INET, socket_type) as s:
|
||||||
# the port is available if bind is a success
|
s.bind((host, port)) # the port is available if bind is a success
|
||||||
s.bind((host, port))
|
|
||||||
return port
|
return port
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.errno == errno.EADDRINUSE: # socket already in use
|
if e.errno == errno.EADDRINUSE: # socket already in use
|
||||||
|
@ -23,11 +23,16 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import base64
|
import base64
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import fcntl
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
from gns3server.config import Config
|
from gns3server.config import Config
|
||||||
from .iou_device import IOUDevice
|
from .iou_device import IOUDevice
|
||||||
from .iou_error import IOUError
|
from .iou_error import IOUError
|
||||||
from .nios.nio_udp import NIO_UDP
|
from .nios.nio_udp import NIO_UDP
|
||||||
|
from .nios.nio_tap import NIO_TAP
|
||||||
|
from .nios.nio_generic_ethernet import NIO_GenericEthernet
|
||||||
import gns3server.jsonrpc as jsonrpc
|
import gns3server.jsonrpc as jsonrpc
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -469,6 +474,10 @@ class IOU(IModule):
|
|||||||
- lport (local port)
|
- lport (local port)
|
||||||
- rhost (remote host)
|
- rhost (remote host)
|
||||||
- rport (remote port)
|
- rport (remote port)
|
||||||
|
- "NIO_GenericEthernet"
|
||||||
|
- ethernet_device (Ethernet device name e.g. eth0)
|
||||||
|
- "NIO_TAP"
|
||||||
|
- tap_device (TAP device name e.g. tap0)
|
||||||
|
|
||||||
Response parameters:
|
Response parameters:
|
||||||
- same as original request
|
- same as original request
|
||||||
@ -490,12 +499,40 @@ class IOU(IModule):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
nio = None
|
nio = None
|
||||||
#TODO: support for TAP and Ethernet NIOs
|
|
||||||
if request["nio"] == "NIO_UDP":
|
if request["nio"] == "NIO_UDP":
|
||||||
lport = request["lport"]
|
lport = request["lport"]
|
||||||
rhost = request["rhost"]
|
rhost = request["rhost"]
|
||||||
rport = request["rport"]
|
rport = request["rport"]
|
||||||
nio = NIO_UDP(lport, rhost, rport)
|
nio = NIO_UDP(lport, rhost, rport)
|
||||||
|
elif request["nio"] == "NIO_TAP":
|
||||||
|
tap_device = request["tap_device"]
|
||||||
|
|
||||||
|
# check that we have access to the tap device
|
||||||
|
TUNSETIFF = 0x400454ca
|
||||||
|
IFF_TAP = 0x0002
|
||||||
|
IFF_NO_PI = 0x1000
|
||||||
|
try:
|
||||||
|
tun = os.open("/dev/net/tun", os.O_RDWR)
|
||||||
|
except EnvironmentError as e:
|
||||||
|
raise IOUError("Could not open /dev/net/tun: {}".format(e))
|
||||||
|
ifr = struct.pack("16sH", tap_device.encode("utf-8"), IFF_TAP | IFF_NO_PI)
|
||||||
|
try:
|
||||||
|
fcntl.ioctl(tun, TUNSETIFF, ifr)
|
||||||
|
os.close(tun)
|
||||||
|
except IOError as e:
|
||||||
|
raise IOUError("TAP NIO {}: {}".format(tap_device, e))
|
||||||
|
|
||||||
|
nio = NIO_TAP(tap_device)
|
||||||
|
elif request["nio"] == "NIO_GenericEthernet":
|
||||||
|
ethernet_device = request["ethernet_device"]
|
||||||
|
|
||||||
|
# check that we have access to the Ethernet device
|
||||||
|
try:
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW):
|
||||||
|
pass
|
||||||
|
except socket.error as e:
|
||||||
|
raise IOUError("Generic Ethernet NIO {}: {}".format(ethernet_device, e))
|
||||||
|
nio = NIO_GenericEthernet(ethernet_device)
|
||||||
if not nio:
|
if not nio:
|
||||||
raise IOUError("Requested NIO doesn't exist or is not supported: {}".format(request["nio"]))
|
raise IOUError("Requested NIO doesn't exist or is not supported: {}".format(request["nio"]))
|
||||||
except IOUError as e:
|
except IOUError as e:
|
||||||
|
@ -32,7 +32,9 @@ from .ioucon import start_ioucon
|
|||||||
from .iou_error import IOUError
|
from .iou_error import IOUError
|
||||||
from .adapters.ethernet_adapter import EthernetAdapter
|
from .adapters.ethernet_adapter import EthernetAdapter
|
||||||
from .adapters.serial_adapter import SerialAdapter
|
from .adapters.serial_adapter import SerialAdapter
|
||||||
|
from .nios.nio_udp import NIO_UDP
|
||||||
|
from .nios.nio_tap import NIO_TAP
|
||||||
|
from .nios.nio_generic_ethernet import NIO_GenericEthernet
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -323,12 +325,20 @@ class IOUDevice(object):
|
|||||||
for unit in adapter.ports.keys():
|
for unit in adapter.ports.keys():
|
||||||
nio = adapter.get_nio(unit)
|
nio = adapter.get_nio(unit)
|
||||||
if nio:
|
if nio:
|
||||||
#TODO: handle TAP and Ethernet NIOs
|
if isinstance(nio, NIO_UDP):
|
||||||
tunnel = {"tunnel_udp": "{lport}:{rhost}:{rport}".format(lport=nio.lport,
|
# UDP tunnel
|
||||||
rhost=nio.rhost,
|
connection = {"tunnel_udp": "{lport}:{rhost}:{rport}".format(lport=nio.lport,
|
||||||
rport=nio.rport)}
|
rhost=nio.rhost,
|
||||||
|
rport=nio.rport)}
|
||||||
|
elif isinstance(nio, NIO_TAP):
|
||||||
|
# TAP interface
|
||||||
|
connection = {"tap_dev": "{tap_device}".format(tap_device=nio.tap_device)}
|
||||||
|
|
||||||
config["{iouyap_id}:{bay}/{unit}".format(iouyap_id=str(self._id + 512), bay=bay_id, unit=unit_id)] = tunnel
|
elif isinstance(nio, NIO_GenericEthernet):
|
||||||
|
# Ethernet interface
|
||||||
|
connection = {"eth_dev": "{ethernet_device}".format(ethernet_device=nio.ethernet_device)}
|
||||||
|
|
||||||
|
config["{iouyap_id}:{bay}/{unit}".format(iouyap_id=str(self._id + 512), bay=bay_id, unit=unit_id)] = connection
|
||||||
unit_id += 1
|
unit_id += 1
|
||||||
bay_id += 1
|
bay_id += 1
|
||||||
|
|
||||||
@ -766,11 +776,11 @@ class IOUDevice(object):
|
|||||||
try:
|
try:
|
||||||
if ":" in host:
|
if ":" in host:
|
||||||
# IPv6 address support
|
# IPv6 address support
|
||||||
s = socket.socket(socket.AF_INET6, socket_type)
|
with socket.socket(socket.AF_INET6, socket_type) as s:
|
||||||
|
s.bind((host, port)) # the port is available if bind is a success
|
||||||
else:
|
else:
|
||||||
s = socket.socket(socket.AF_INET, socket_type)
|
with socket.socket(socket.AF_INET, socket_type) as s:
|
||||||
# the port is available if bind is a success
|
s.bind((host, port)) # the port is available if bind is a success
|
||||||
s.bind((host, port))
|
|
||||||
return port
|
return port
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.errno == errno.EADDRINUSE: # socket already in use
|
if e.errno == errno.EADDRINUSE: # socket already in use
|
||||||
|
46
gns3server/modules/iou/nios/nio_generic_ethernet.py
Normal file
46
gns3server/modules/iou/nios/nio_generic_ethernet.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Interface for generic Ethernet NIOs (PCAP library).
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class NIO_GenericEthernet(object):
|
||||||
|
"""
|
||||||
|
NIO generic Ethernet NIO.
|
||||||
|
|
||||||
|
:param ethernet_device: Ethernet device name (e.g. eth0)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, ethernet_device):
|
||||||
|
|
||||||
|
self._ethernet_device = ethernet_device
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ethernet_device(self):
|
||||||
|
"""
|
||||||
|
Returns the Ethernet device used by this NIO.
|
||||||
|
|
||||||
|
:returns: the Ethernet device name
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._ethernet_device
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
return "NIO Ethernet"
|
46
gns3server/modules/iou/nios/nio_tap.py
Normal file
46
gns3server/modules/iou/nios/nio_tap.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Interface for TAP NIOs (UNIX based OSes only).
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class NIO_TAP(object):
|
||||||
|
"""
|
||||||
|
IOU TAP NIO.
|
||||||
|
|
||||||
|
:param tap_device: TAP device name (e.g. tap0)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, tap_device):
|
||||||
|
|
||||||
|
self._tap_device = tap_device
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tap_device(self):
|
||||||
|
"""
|
||||||
|
Returns the TAP device used by this NIO.
|
||||||
|
|
||||||
|
:returns: the TAP device name
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._tap_device
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
return "NIO TAP"
|
@ -19,9 +19,6 @@
|
|||||||
Interface for UDP NIOs.
|
Interface for UDP NIOs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class NIO_UDP(object):
|
class NIO_UDP(object):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user