mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-23 14:42:28 +00:00
New feature: packet capture for the Ethernet hub and Ethernet, ATM and Frame relay switches.
This commit is contained in:
parent
606f773f3d
commit
33787d486a
@ -16,6 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
from ..nodes.atm_switch import ATMSwitch
|
from ..nodes.atm_switch import ATMSwitch
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
@ -26,6 +27,8 @@ from ..schemas.atmsw import ATMSW_UPDATE_SCHEMA
|
|||||||
from ..schemas.atmsw import ATMSW_ALLOCATE_UDP_PORT_SCHEMA
|
from ..schemas.atmsw import ATMSW_ALLOCATE_UDP_PORT_SCHEMA
|
||||||
from ..schemas.atmsw import ATMSW_ADD_NIO_SCHEMA
|
from ..schemas.atmsw import ATMSW_ADD_NIO_SCHEMA
|
||||||
from ..schemas.atmsw import ATMSW_DELETE_NIO_SCHEMA
|
from ..schemas.atmsw import ATMSW_DELETE_NIO_SCHEMA
|
||||||
|
from ..schemas.atmsw import ATMSW_START_CAPTURE_SCHEMA
|
||||||
|
from ..schemas.atmsw import ATMSW_STOP_CAPTURE_SCHEMA
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -310,3 +313,83 @@ class ATMSW(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.send_response(True)
|
self.send_response(True)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.start_capture")
|
||||||
|
def atmsw_start_capture(self, request):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port (port identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_name
|
||||||
|
|
||||||
|
Optional request parameters:
|
||||||
|
- data_link_type (PCAP DLT_* value)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_path (path to the capture file)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ATMSW_START_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the ATM switch instance
|
||||||
|
atmsw = self.get_device_instance(request["id"], self._atm_switches)
|
||||||
|
if not atmsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
capture_file_name = request["capture_file_name"]
|
||||||
|
data_link_type = request.get("data_link_type")
|
||||||
|
|
||||||
|
try:
|
||||||
|
capture_file_path = os.path.join(atmsw.hypervisor.working_dir, "captures", capture_file_name)
|
||||||
|
atmsw.start_capture(port, capture_file_path, data_link_type)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"],
|
||||||
|
"capture_file_path": capture_file_path}
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.stop_capture")
|
||||||
|
def atmsw_stop_capture(self, request):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- port (port number)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ATMSW_STOP_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the ATM switch instance
|
||||||
|
atmsw = self.get_device_instance(request["id"], self._atm_switches)
|
||||||
|
if not atmsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
try:
|
||||||
|
atmsw.stop_capture(port)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"]}
|
||||||
|
self.send_response(response)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
from ..nodes.hub import Hub
|
from ..nodes.hub import Hub
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
@ -25,6 +26,8 @@ from ..schemas.ethhub import ETHHUB_UPDATE_SCHEMA
|
|||||||
from ..schemas.ethhub import ETHHUB_ALLOCATE_UDP_PORT_SCHEMA
|
from ..schemas.ethhub import ETHHUB_ALLOCATE_UDP_PORT_SCHEMA
|
||||||
from ..schemas.ethhub import ETHHUB_ADD_NIO_SCHEMA
|
from ..schemas.ethhub import ETHHUB_ADD_NIO_SCHEMA
|
||||||
from ..schemas.ethhub import ETHHUB_DELETE_NIO_SCHEMA
|
from ..schemas.ethhub import ETHHUB_DELETE_NIO_SCHEMA
|
||||||
|
from ..schemas.ethhub import ETHHUB_START_CAPTURE_SCHEMA
|
||||||
|
from ..schemas.ethhub import ETHHUB_STOP_CAPTURE_SCHEMA
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -236,7 +239,7 @@ class ETHHUB(object):
|
|||||||
self.send_response({"port_id": request["port_id"]})
|
self.send_response({"port_id": request["port_id"]})
|
||||||
|
|
||||||
@IModule.route("dynamips.ethhub.delete_nio")
|
@IModule.route("dynamips.ethhub.delete_nio")
|
||||||
def ethsw_delete_nio(self, request):
|
def ethhub_delete_nio(self, request):
|
||||||
"""
|
"""
|
||||||
Deletes an NIO (Network Input/Output).
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
@ -268,3 +271,83 @@ class ETHHUB(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.send_response(True)
|
self.send_response(True)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.start_capture")
|
||||||
|
def ethhub_start_capture(self, request):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port (port identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_name
|
||||||
|
|
||||||
|
Optional request parameters:
|
||||||
|
- data_link_type (PCAP DLT_* value)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_path (path to the capture file)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ETHHUB_START_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Ethernet hub instance
|
||||||
|
ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
|
||||||
|
if not ethhub:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
capture_file_name = request["capture_file_name"]
|
||||||
|
data_link_type = request.get("data_link_type")
|
||||||
|
|
||||||
|
try:
|
||||||
|
capture_file_path = os.path.join(ethhub.hypervisor.working_dir, "captures", capture_file_name)
|
||||||
|
ethhub.start_capture(port, capture_file_path, data_link_type)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"],
|
||||||
|
"capture_file_path": capture_file_path}
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.stop_capture")
|
||||||
|
def ethhub_stop_capture(self, request):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- port (port number)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ETHHUB_STOP_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Ethernet hub instance
|
||||||
|
ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
|
||||||
|
if not ethhub:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
try:
|
||||||
|
ethhub.stop_capture(port)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"]}
|
||||||
|
self.send_response(response)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
from ..nodes.ethernet_switch import EthernetSwitch
|
from ..nodes.ethernet_switch import EthernetSwitch
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
@ -25,6 +26,8 @@ from ..schemas.ethsw import ETHSW_UPDATE_SCHEMA
|
|||||||
from ..schemas.ethsw import ETHSW_ALLOCATE_UDP_PORT_SCHEMA
|
from ..schemas.ethsw import ETHSW_ALLOCATE_UDP_PORT_SCHEMA
|
||||||
from ..schemas.ethsw import ETHSW_ADD_NIO_SCHEMA
|
from ..schemas.ethsw import ETHSW_ADD_NIO_SCHEMA
|
||||||
from ..schemas.ethsw import ETHSW_DELETE_NIO_SCHEMA
|
from ..schemas.ethsw import ETHSW_DELETE_NIO_SCHEMA
|
||||||
|
from ..schemas.ethsw import ETHSW_START_CAPTURE_SCHEMA
|
||||||
|
from ..schemas.ethsw import ETHSW_STOP_CAPTURE_SCHEMA
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -297,3 +300,83 @@ class ETHSW(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.send_response(True)
|
self.send_response(True)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.start_capture")
|
||||||
|
def ethsw_start_capture(self, request):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port (port identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_name
|
||||||
|
|
||||||
|
Optional request parameters:
|
||||||
|
- data_link_type (PCAP DLT_* value)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_path (path to the capture file)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ETHSW_START_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Ethernet switch instance
|
||||||
|
ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
|
||||||
|
if not ethsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
capture_file_name = request["capture_file_name"]
|
||||||
|
data_link_type = request.get("data_link_type")
|
||||||
|
|
||||||
|
try:
|
||||||
|
capture_file_path = os.path.join(ethsw.hypervisor.working_dir, "captures", capture_file_name)
|
||||||
|
ethsw.start_capture(port, capture_file_path, data_link_type)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"],
|
||||||
|
"capture_file_path": capture_file_path}
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.stop_capture")
|
||||||
|
def ethsw_stop_capture(self, request):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- port (port number)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, ETHSW_STOP_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Ethernet switch instance
|
||||||
|
ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
|
||||||
|
if not ethsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
try:
|
||||||
|
ethsw.stop_capture(port)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"]}
|
||||||
|
self.send_response(response)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
from ..nodes.frame_relay_switch import FrameRelaySwitch
|
from ..nodes.frame_relay_switch import FrameRelaySwitch
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
@ -25,6 +26,8 @@ from ..schemas.frsw import FRSW_UPDATE_SCHEMA
|
|||||||
from ..schemas.frsw import FRSW_ALLOCATE_UDP_PORT_SCHEMA
|
from ..schemas.frsw import FRSW_ALLOCATE_UDP_PORT_SCHEMA
|
||||||
from ..schemas.frsw import FRSW_ADD_NIO_SCHEMA
|
from ..schemas.frsw import FRSW_ADD_NIO_SCHEMA
|
||||||
from ..schemas.frsw import FRSW_DELETE_NIO_SCHEMA
|
from ..schemas.frsw import FRSW_DELETE_NIO_SCHEMA
|
||||||
|
from ..schemas.frsw import FRSW_START_CAPTURE_SCHEMA
|
||||||
|
from ..schemas.frsw import FRSW_STOP_CAPTURE_SCHEMA
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -289,3 +292,83 @@ class FRSW(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.send_response(True)
|
self.send_response(True)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.start_capture")
|
||||||
|
def frsw_start_capture(self, request):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port (port identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_name
|
||||||
|
|
||||||
|
Optional request parameters:
|
||||||
|
- data_link_type (PCAP DLT_* value)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
- capture_file_path (path to the capture file)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, FRSW_START_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Frame relay switch instance
|
||||||
|
frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
|
||||||
|
if not frsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
capture_file_name = request["capture_file_name"]
|
||||||
|
data_link_type = request.get("data_link_type")
|
||||||
|
|
||||||
|
try:
|
||||||
|
capture_file_path = os.path.join(frsw.hypervisor.working_dir, "captures", capture_file_name)
|
||||||
|
frsw.start_capture(port, capture_file_path, data_link_type)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"],
|
||||||
|
"capture_file_path": capture_file_path}
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.stop_capture")
|
||||||
|
def frsw_stop_capture(self, request):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
Mandatory request parameters:
|
||||||
|
- id (vm identifier)
|
||||||
|
- port_id (port identifier)
|
||||||
|
- port (port number)
|
||||||
|
|
||||||
|
Response parameters:
|
||||||
|
- port_id (port identifier)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# validate the request
|
||||||
|
if not self.validate_request(request, FRSW_STOP_CAPTURE_SCHEMA):
|
||||||
|
return
|
||||||
|
|
||||||
|
# get the Frame relay switch instance
|
||||||
|
frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
|
||||||
|
if not frsw:
|
||||||
|
return
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
try:
|
||||||
|
frsw.stop_capture(port)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"port_id": request["port_id"]}
|
||||||
|
self.send_response(response)
|
||||||
|
@ -20,6 +20,7 @@ Interface for Dynamips virtual ATM switch module ("atmsw").
|
|||||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593
|
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -351,3 +352,54 @@ class ATMSwitch(object):
|
|||||||
vpi2=vpi2,
|
vpi2=vpi2,
|
||||||
vci2=vci2))
|
vci2=vci2))
|
||||||
del self._mapping[(port1, vpi1, vci1)]
|
del self._mapping[(port1, vpi1, vci1)]
|
||||||
|
|
||||||
|
def start_capture(self, port, output_file, data_link_type="DLT_ATM_RFC1483"):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
:param output_file: PCAP destination file for the capture
|
||||||
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_ATM_RFC1483
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
|
||||||
|
data_link_type = data_link_type.lower()
|
||||||
|
if data_link_type.startswith("dlt_"):
|
||||||
|
data_link_type = data_link_type[4:]
|
||||||
|
|
||||||
|
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||||
|
raise DynamipsError("Port {} has already a filter applied".format(port))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(output_file))
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
except OSError as e:
|
||||||
|
raise DynamipsError("Could not create captures directory {}".format(e))
|
||||||
|
|
||||||
|
nio.bind_filter("both", "capture")
|
||||||
|
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
|
||||||
|
def stop_capture(self, port):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
nio.unbind_filter("both")
|
||||||
|
log.info("ATM switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
@ -20,6 +20,7 @@ Interface for Dynamips virtual Ethernet switch module ("ethsw").
|
|||||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558
|
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -287,3 +288,54 @@ class EthernetSwitch(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("ethsw clear_mac_addr_table {}".format(self._name))
|
self._hypervisor.send("ethsw clear_mac_addr_table {}".format(self._name))
|
||||||
|
|
||||||
|
def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
:param output_file: PCAP destination file for the capture
|
||||||
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
|
||||||
|
data_link_type = data_link_type.lower()
|
||||||
|
if data_link_type.startswith("dlt_"):
|
||||||
|
data_link_type = data_link_type[4:]
|
||||||
|
|
||||||
|
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||||
|
raise DynamipsError("Port {} has already a filter applied".format(port))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(output_file))
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
except OSError as e:
|
||||||
|
raise DynamipsError("Could not create captures directory {}".format(e))
|
||||||
|
|
||||||
|
nio.bind_filter("both", "capture")
|
||||||
|
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
|
||||||
|
def stop_capture(self, port):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
nio.unbind_filter("both")
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
@ -20,6 +20,7 @@ Interface for Dynamips virtual Frame-Relay switch module.
|
|||||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642
|
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -273,3 +274,54 @@ class FrameRelaySwitch(object):
|
|||||||
port2=port2,
|
port2=port2,
|
||||||
dlci2=dlci2))
|
dlci2=dlci2))
|
||||||
del self._mapping[(port1, dlci1)]
|
del self._mapping[(port1, dlci1)]
|
||||||
|
|
||||||
|
def start_capture(self, port, output_file, data_link_type="DLT_FRELAY"):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
:param output_file: PCAP destination file for the capture
|
||||||
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_FRELAY
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
|
||||||
|
data_link_type = data_link_type.lower()
|
||||||
|
if data_link_type.startswith("dlt_"):
|
||||||
|
data_link_type = data_link_type[4:]
|
||||||
|
|
||||||
|
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||||
|
raise DynamipsError("Port {} has already a filter applied".format(port))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(output_file))
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
except OSError as e:
|
||||||
|
raise DynamipsError("Could not create captures directory {}".format(e))
|
||||||
|
|
||||||
|
nio.bind_filter("both", "capture")
|
||||||
|
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
||||||
|
|
||||||
|
log.info("Frame relay switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
|
||||||
|
def stop_capture(self, port):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._nios:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
nio.unbind_filter("both")
|
||||||
|
log.info("Frame relay switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
Hub object that uses the Bridge interface to create a hub with ports.
|
Hub object that uses the Bridge interface to create a hub with ports.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from .bridge import Bridge
|
from .bridge import Bridge
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
@ -134,3 +135,54 @@ class Hub(Bridge):
|
|||||||
|
|
||||||
del self._mapping[port]
|
del self._mapping[port]
|
||||||
return nio
|
return nio
|
||||||
|
|
||||||
|
def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"):
|
||||||
|
"""
|
||||||
|
Starts a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
:param output_file: PCAP destination file for the capture
|
||||||
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._mapping:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._mapping[port]
|
||||||
|
|
||||||
|
data_link_type = data_link_type.lower()
|
||||||
|
if data_link_type.startswith("dlt_"):
|
||||||
|
data_link_type = data_link_type[4:]
|
||||||
|
|
||||||
|
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||||
|
raise DynamipsError("Port {} has already a filter applied".format(port))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(output_file))
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
except OSError as e:
|
||||||
|
raise DynamipsError("Could not create captures directory {}".format(e))
|
||||||
|
|
||||||
|
nio.bind_filter("both", "capture")
|
||||||
|
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
||||||
|
|
||||||
|
log.info("Ethernet hub {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
|
||||||
|
def stop_capture(self, port):
|
||||||
|
"""
|
||||||
|
Stops a packet capture.
|
||||||
|
|
||||||
|
:param port: allocated port
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port not in self._mapping:
|
||||||
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._mapping[port]
|
||||||
|
nio.unbind_filter("both")
|
||||||
|
log.info("Ethernet hub {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port))
|
||||||
|
@ -1578,11 +1578,11 @@ class Router(object):
|
|||||||
nio.bind_filter("both", "capture")
|
nio.bind_filter("both", "capture")
|
||||||
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
|
||||||
|
|
||||||
log.info("router {name} [id={id}]: capturing on port {slot_id}/{port_id}".format(name=self._name,
|
log.info("router {name} [id={id}]: starting packet capture on port {slot_id}/{port_id}".format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio_name=nio.name,
|
nio_name=nio.name,
|
||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
port_id=port_id))
|
port_id=port_id))
|
||||||
|
|
||||||
def stop_capture(self, slot_id, port_id):
|
def stop_capture(self, slot_id, port_id):
|
||||||
"""
|
"""
|
||||||
@ -1604,6 +1604,12 @@ class Router(object):
|
|||||||
nio = adapter.get_nio(port_id)
|
nio = adapter.get_nio(port_id)
|
||||||
nio.unbind_filter("both")
|
nio.unbind_filter("both")
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: stopping packet capture on port {slot_id}/{port_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio_name=nio.name,
|
||||||
|
slot_id=slot_id,
|
||||||
|
port_id=port_id))
|
||||||
|
|
||||||
def _create_slots(self, numslots):
|
def _create_slots(self, numslots):
|
||||||
"""
|
"""
|
||||||
Creates the appropriate number of slots for this router.
|
Creates the appropriate number of slots for this router.
|
||||||
|
@ -264,3 +264,59 @@ ATMSW_DELETE_NIO_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"required": ["id", "port"]
|
"required": ["id", "port"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ATMSW_START_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to start a packet capture on an ATM switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "ATM switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the ATM switch instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
"capture_file_name": {
|
||||||
|
"description": "Capture file name",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"data_link_type": {
|
||||||
|
"description": "PCAP data link type",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port", "capture_file_name"]
|
||||||
|
}
|
||||||
|
|
||||||
|
ATMSW_STOP_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to stop a packet capture on an ATM switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "ATM switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the ATM switch instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port"]
|
||||||
|
}
|
||||||
|
@ -261,3 +261,59 @@ ETHHUB_DELETE_NIO_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"required": ["id", "port"]
|
"required": ["id", "port"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ETHHUB_START_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to start a packet capture on an Ethernet hub instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Ethernet hub instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Ethernet hub instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
"capture_file_name": {
|
||||||
|
"description": "Capture file name",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"data_link_type": {
|
||||||
|
"description": "PCAP data link type",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port", "capture_file_name"]
|
||||||
|
}
|
||||||
|
|
||||||
|
ETHHUB_STOP_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to stop a packet capture on an Ethernet hub instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Ethernet hub instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Ethernet hub instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port"]
|
||||||
|
}
|
||||||
|
@ -290,3 +290,59 @@ ETHSW_DELETE_NIO_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"required": ["id", "port"]
|
"required": ["id", "port"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ETHSW_START_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to start a packet capture on an Ethernet switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Ethernet switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Ethernet switch instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
"capture_file_name": {
|
||||||
|
"description": "Capture file name",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"data_link_type": {
|
||||||
|
"description": "PCAP data link type",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port", "capture_file_name"]
|
||||||
|
}
|
||||||
|
|
||||||
|
ETHSW_STOP_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to stop a packet capture on an Ethernet switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Ethernet switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Ethernet switch instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port"]
|
||||||
|
}
|
||||||
|
@ -264,3 +264,59 @@ FRSW_DELETE_NIO_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"required": ["id", "port"]
|
"required": ["id", "port"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FRSW_START_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to start a packet capture on a Frame relay switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Frame relay switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Frame relay instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
"capture_file_name": {
|
||||||
|
"description": "Capture file name",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"data_link_type": {
|
||||||
|
"description": "PCAP data link type",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port", "capture_file_name"]
|
||||||
|
}
|
||||||
|
|
||||||
|
FRSW_STOP_CAPTURE_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to stop a packet capture on a Frame relay switch instance port",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Frame relay switch instance ID",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port_id": {
|
||||||
|
"description": "Unique port identifier for the Frame relay instance",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"description": "Port number",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"required": ["id", "port_id", "port"]
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user