TAP and Ethernet device support for IOU

This commit is contained in:
grossmj 2014-03-17 17:32:16 -06:00
parent 41a1d16e92
commit 0e1d8e5071
7 changed files with 172 additions and 34 deletions

View File

@ -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,6 +118,8 @@ class ETHSW(object):
log.debug("received request {}".format(request))
ethsw_id = request["id"]
ethsw = self._ethernet_switches[ethsw_id]
if "ports" in request:
ports = request["ports"]
# update the port settings

View File

@ -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

View File

@ -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:

View File

@ -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,
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

View 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"

View 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"

View File

@ -19,9 +19,6 @@
Interface for UDP NIOs.
"""
import logging
log = logging.getLogger(__name__)
class NIO_UDP(object):
"""