# -*- 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 . """ Base interface for Dynamips Network Input/Output (NIO) module ("nio"). http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L451 """ from ..dynamips_error import DynamipsError import logging log = logging.getLogger(__name__) class NIO(object): """ Base NIO class :param hypervisor: Dynamips hypervisor instance """ def __init__(self, hypervisor): self._hypervisor = hypervisor self._bandwidth = None # no bandwidth constraint by default self._input_filter = None # no input filter applied by default self._output_filter = None # no output filter applied by default self._input_filter_options = None # no input filter options by default self._output_filter_options = None # no output filter options by default self._dynamips_direction = {"in": 0, "out": 1, "both": 2} def list(self): """ Returns all NIOs. :returns: NIO list """ return self._hypervisor.send("nio list") def delete(self): """ Deletes this NIO. """ self._hypervisor.send("nio delete {}".format(self._name)) log.info("NIO {name} has been deleted".format(name=self._name)) def rename(self, new_name): """ Renames this NIO :param new_name: new NIO name """ self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name, new_name=new_name)) log.info("NIO {name} renamed to {new_name}".format(name=self._name, new_name=new_name)) self._name = new_name def debug(self, debug): """ Enables/Disables debugging for this NIO. :param debug: debug value (0 = disable, enable = 1) """ self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name, debug=debug)) def bind_filter(self, direction, filter_name): """ Adds a packet filter to this NIO. Filter "freq_drop" drops packets. Filter "capture" captures packets. :param direction: "in", "out" or "both" :param filter_name: name of the filter to apply """ if direction not in self._dynamips_direction: raise DynamipsError("Unknown direction {} to bind filter {}:".format(direction, filter_name)) dynamips_direction = self._dynamips_direction[direction] self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name, direction=dynamips_direction, filter=filter_name)) if direction == "in": self._input_filter = filter_name elif direction == "out": self._output_filter = filter_name elif direction == "both": self._input_filter = filter_name self._output_filter = filter_name def unbind_filter(self, direction): """ Removes packet filter for this NIO. :param direction: "in", "out" or "both" """ if direction not in self._dynamips_direction: raise DynamipsError("Unknown direction {} to unbind filter:".format(direction)) dynamips_direction = self._dynamips_direction[direction] self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name, direction=dynamips_direction)) if direction == "in": self._input_filter = None elif direction == "out": self._output_filter = None elif direction == "both": self._input_filter = None self._output_filter = None def setup_filter(self, direction, options): """ Setups a packet filter binded with this NIO. Filter "freq_drop" has 1 argument "". It will drop everything with a -1 frequency, drop every Nth packet with a positive frequency, or drop nothing. Filter "capture" has 2 arguments " ". It will capture packets to the target output file. The link type name is a case-insensitive DLT_ name from the PCAP library constants with the DLT_ part removed.See http://www.tcpdump.org/linktypes.html for a list of all available DLT values. :param direction: "in", "out" or "both" :param options: options for the packet filter (string) """ if direction not in self._dynamips_direction: raise DynamipsError("Unknown direction {} to setup filter:".format(direction)) dynamips_direction = self._dynamips_direction[direction] self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name, direction=dynamips_direction, options=options)) if direction == "in": self._input_filter_options = options elif direction == "out": self._output_filter_options = options elif direction == "both": self._input_filter_options = options self._output_filter_options = options @property def input_filter(self): """ Returns the input packet filter for this NIO. :returns: tuple (filter name, filter options) """ return self._input_filter, self._input_filter_options @property def output_filter(self): """ Returns the output packet filter for this NIO. :returns: tuple (filter name, filter options) """ return self._output_filter, self._output_filter_options def get_stats(self): """ Gets statistics for this NIO. :returns: NIO statistics (string with packets in, packets out, bytes in, bytes out) """ return self._hypervisor.send("nio get_stats {}".format(self._name))[0] def reset_stats(self): """ Resets statistics for this NIO. """ self._hypervisor.send("nio reset_stats {}".format(self._name)) def set_bandwidth(self, bandwidth): """ Sets bandwidth constraint. :param bandwidth: bandwidth integer value (in Kb/s) """ self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth)) self._bandwidth = bandwidth @property def bandwidth(self): """ Returns the bandwidth constraint for this NIO. :returns: bandwidth integer value (in Kb/s) """ return self._bandwidth def __str__(self): """ NIO string representation. :returns: NIO name """ return self._name @property def name(self): """ Returns the NIO name. :returns: NIO name """ return self._name