mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-19 21:07:57 +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:
|
||||
- id (switch identifier)
|
||||
- ports (ports settings)
|
||||
|
||||
Optional request parameters:
|
||||
- name (new switch name)
|
||||
- ports (ports settings)
|
||||
|
||||
Response parameters:
|
||||
- same as original request
|
||||
@ -118,22 +118,24 @@ class ETHSW(object):
|
||||
log.debug("received request {}".format(request))
|
||||
ethsw_id = request["id"]
|
||||
ethsw = self._ethernet_switches[ethsw_id]
|
||||
ports = request["ports"]
|
||||
|
||||
# update the port settings
|
||||
for port, info in ports.items():
|
||||
vlan = info["vlan"]
|
||||
port_type = info["type"]
|
||||
try:
|
||||
if port_type == "access":
|
||||
ethsw.set_access_port(int(port), vlan)
|
||||
elif port_type == "dot1q":
|
||||
ethsw.set_dot1q_port(int(port), vlan)
|
||||
elif port_type == "qinq":
|
||||
ethsw.set_qinq_port(int(port), vlan)
|
||||
except DynamipsError as e:
|
||||
self.send_custom_error(str(e))
|
||||
return
|
||||
if "ports" in request:
|
||||
ports = request["ports"]
|
||||
|
||||
# update the port settings
|
||||
for port, info in ports.items():
|
||||
vlan = info["vlan"]
|
||||
port_type = info["type"]
|
||||
try:
|
||||
if port_type == "access":
|
||||
ethsw.set_access_port(int(port), vlan)
|
||||
elif port_type == "dot1q":
|
||||
ethsw.set_dot1q_port(int(port), vlan)
|
||||
elif port_type == "qinq":
|
||||
ethsw.set_qinq_port(int(port), vlan)
|
||||
except DynamipsError as e:
|
||||
self.send_custom_error(str(e))
|
||||
return
|
||||
|
||||
# rename the switch if requested
|
||||
if "name" in request and ethsw.name != request["name"]:
|
||||
|
@ -356,11 +356,11 @@ class DynamipsHypervisor(object):
|
||||
try:
|
||||
if ":" in host:
|
||||
# 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:
|
||||
s = socket.socket(socket.AF_INET, socket_type)
|
||||
# the port is available if bind is a success
|
||||
s.bind((host, port))
|
||||
with socket.socket(socket.AF_INET, socket_type) as s:
|
||||
s.bind((host, port)) # the port is available if bind is a success
|
||||
return port
|
||||
except socket.error as e:
|
||||
if e.errno == errno.EADDRINUSE: # socket already in use
|
||||
|
@ -23,11 +23,16 @@ import os
|
||||
import sys
|
||||
import base64
|
||||
import tempfile
|
||||
import fcntl
|
||||
import struct
|
||||
import socket
|
||||
from gns3server.modules import IModule
|
||||
from gns3server.config import Config
|
||||
from .iou_device import IOUDevice
|
||||
from .iou_error import IOUError
|
||||
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 logging
|
||||
@ -469,6 +474,10 @@ class IOU(IModule):
|
||||
- lport (local port)
|
||||
- rhost (remote host)
|
||||
- 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:
|
||||
- same as original request
|
||||
@ -490,12 +499,40 @@ class IOU(IModule):
|
||||
|
||||
try:
|
||||
nio = None
|
||||
#TODO: support for TAP and Ethernet NIOs
|
||||
if request["nio"] == "NIO_UDP":
|
||||
lport = request["lport"]
|
||||
rhost = request["rhost"]
|
||||
rport = request["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:
|
||||
raise IOUError("Requested NIO doesn't exist or is not supported: {}".format(request["nio"]))
|
||||
except IOUError as e:
|
||||
|
@ -32,7 +32,9 @@ from .ioucon import start_ioucon
|
||||
from .iou_error import IOUError
|
||||
from .adapters.ethernet_adapter import EthernetAdapter
|
||||
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
|
||||
log = logging.getLogger(__name__)
|
||||
@ -323,12 +325,20 @@ class IOUDevice(object):
|
||||
for unit in adapter.ports.keys():
|
||||
nio = adapter.get_nio(unit)
|
||||
if nio:
|
||||
#TODO: handle TAP and Ethernet NIOs
|
||||
tunnel = {"tunnel_udp": "{lport}:{rhost}:{rport}".format(lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport)}
|
||||
if isinstance(nio, NIO_UDP):
|
||||
# UDP tunnel
|
||||
connection = {"tunnel_udp": "{lport}:{rhost}:{rport}".format(lport=nio.lport,
|
||||
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
|
||||
bay_id += 1
|
||||
|
||||
@ -766,11 +776,11 @@ class IOUDevice(object):
|
||||
try:
|
||||
if ":" in host:
|
||||
# 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:
|
||||
s = socket.socket(socket.AF_INET, socket_type)
|
||||
# the port is available if bind is a success
|
||||
s.bind((host, port))
|
||||
with socket.socket(socket.AF_INET, socket_type) as s:
|
||||
s.bind((host, port)) # the port is available if bind is a success
|
||||
return port
|
||||
except socket.error as e:
|
||||
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.
|
||||
"""
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NIO_UDP(object):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user