Coder Social home page Coder Social logo

ipmininet's People

Contributors

antoinerime avatar butjar avatar fdardenne avatar gromit1811 avatar jadinm avatar louisna avatar mathieu-cosyns-student avatar maxmawt avatar oliviertilmans avatar omar2535 avatar stoza avatar twirtgen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ipmininet's Issues

Moving from Quagga to FRRouting

FRRouting is more actively developed than Quagga, so we should support it.

It requires changes to the installation script and to the BGP configuration:
"nexthop self all" is not understood while "nexthop self force" means the same thing.

Add documentation on IPMininet execution flow and architecture

Execution flow:

  1. First pass of addressing and interface names
  2. Initialization of deamon configurations
  3. Call of post_build method that allow specific changes to the topology after address assignation and daemon creation
  4. Finalize daemon configurations and validate them ('dry-run')
  5. Start daemons

Is it possible to unbuffer sys.stdin for a node's shell process

Hi,
I'm experiencing a situation with exaBGP daemon in IPMininet. In my IPMininet topology, I've configured one of the nodes with
exaBGP. The exaBGP daemon has two processes announce-routes and receive-routes which both have two python scripts sender.py and receiver.py respectively. sender.py announce the routes to the exaBGP peer and receiver.py receives and parses all BGP messages while receiver.py receives and processes the BGP messages generated.

sender.py looks somewhat like this

import sys
import time

if __name__ == '__main__':
     while True:
            # get route 
            sys.stdout.write('neighbor 172.16.2.20 announce attribute next-hop self med 150 origin incomplete nlri 100.30.0.0/16 100.40.0.0/16'
            sys.stdout.flush()
            time.sleep(0.1)

receiver.py looks somewhat like this

import sys
import time
import json

 if __name__ == '__main__':
     sys.stderr = open('/tmp/exabgp-receiver.log', 'a+') 
     unbuffered_stdin = os.fdopen(sys.stdin.fileno(), 'r', buffering=1)
     while True:
           line = unbuffered_stdin.readline().strip()
           try:
                 jsonline = json.loads(line)
           except json.decoder.JSONDecodeError as e:
                sys.stderr.write("Error\n")
           else:
                  # process and write actual BGP message
                  sys.stderr.write(str(jsonline) + '\n')
           sys.stderr.flush()

If I run the network/topology and I trigger a link failure about four times which causes a bunch of BGP updates and withdrawal, the receiver.py script hangs and does not process any message again. However, if I run the topology with IPCLI() and run exabgp from the shell of the host with xterm, the script does not hang. This makes me think there is something buffering sys.stdin and sys.stdout when the topology is not run in interactive CLI mode. I was wondering if there is a way to turn off buffering or get around this ? Or if this has been encountered before ?

IPMininet version is 0.9, python version 3.6

set_local_pref not flexible enough

Hi,

The set_local_pref function from bgp.py aims to change the local-preference attribute if the route matches the community or an AccessList.

def set_local_pref(self, local_pref: int, from_peer: str,

To do so, the function creates a route-map in the router and links this route-map with the "from_peer" neighbor.

However, I noticed some problems:

  • The new route-map linked to the neighbor blocks all the other routes that do not match the CommunityList/AccessList.
  • We cannot set the same route-map with different orders.
  • If we try to set multiple local-pref with multiple Communities, it does not add a new route-map with different orders but appends the new "match" condition and appends the new "set local-preference" in the existing route-map.

What I suggest as a solution and that I applied in the project is to give more flexibility to this function :

  • An optional parameter to define the name, the function will format it as "name+adressFamily". If None is given, take the actual strategy (check if an existing route-map can take the "match" and the "set local-preference" - if not, a new route-map with the name rm%d is created)
  • An optional parameter to define the order (actually hardcoded to 10)

With those two new parameters, the user can now define a succession of route-maps to define multiple local-pref matching some communities and finally set a default local-pref so that these route maps do not block others route.

If this solution is accepted, I can do a pull request for my implementation to solve these issues. If a better solution is proposed, I am willing to volunteer for the implementation of that one.

BGP default permit filters collide with autogenerated route map names

While making a custom BGP topology I tried something like the following, where r2 is running the standard BGP daemon:

r2.get_config(BGP).deny(from_peer=r1, matching=(
    PrefixList(family="ipv4", entries=("192.168.0.0/16",)),
))
ebgp_session(self, r1, r2)

This generates the following filters in /tmp/bgpd_r2.cfg:

ip prefix-list pfxl1 permit 10.10.0.0/16  
ip prefix-list hello-world-v4 permit 0.0.0.0/0 le 32 
ipv6 prefix-list hello-world-v6 permit ::/0 le 128 


route-map r1-ipv4-in deny 10
    match ip address prefix-list pfxl1
!
!
route-map r1-ipv4-out permit 65535
    match ip address prefix-list hello-world-v4
!
!

If I remove my deny, I got these filters instead:

ip prefix-list hello-world-v4 permit 0.0.0.0/0 le 32 
ipv6 prefix-list hello-world-v6 permit ::/0 le 128 


route-map r1-ipv4-in permit 65535
    match ip address prefix-list hello-world-v4
!ame="deny-1", 
!
route-map r1-ipv4-out permit 65535
    match ip address prefix-list hello-world-v4
!
!

This happens because neither the default permit /0 filters or my deny filter explicitly specified a name, so rm_name came up with the same autogenerated name for both, and they overwrote each other. Manually specifying a name for my filter fixed it. The easiest solution is really just to give the default filters a custom name like their prefix list already has, but there might also be merit to adding an autoincrement to rm_name?

While looking further into this I came this bit of code which is correctly merging the two route maps. Then when it comes time to build the config file here it's explicitly removing the default policy, hence me only getting one. This is probably fine when you're expecting it, though I'm not sure it's correctly handling the case when one's permit and one's deny? Not entirely sure the intended behavior here.

Add proper dry_run for OpenR

Thanks for this!
We'll eventually work on the dry_run if that ever creates an issue in the future.

Originally posted by @oliviertilmans in #18 (comment)

The dry_run for OpenR currently only calls the openr daemon with --version since it doesn't quit after parsing the config.

Impossible to use BBP RouteMapEntry call_action and exit_policy

As mentioned in #107 and #99. I don't think that in interface to configure BGP route maps is good.

I was looking for a way to configure exit_policy. I was not able to find a method in bgp.py to do that so I build a work around.

  def route_map_add_exit_policy(
                                router: RouterDescription,
                                route_map_name: str,
                                route_map_order: str,
                                exit_policy: Optional[str] = None):
      """
      ipmininet does not have a interface to add exit policies on route maps!
      This is a hacky why to do it.
      """
      route_maps = router.get_config(BGP).topo.getNodeInfo(
          router, 'bgp_route_maps', list)

      for route_map in route_maps:
          if route_map_name == route_map.name:
              for order, route_map_entry in route_map.entries.items():
                  if route_map_order == order:
                      route_map_entry.exit_policy = exit_policy

When I configure a router with this function and I start, an error occurs.

Couldnt render a config file( bgpd.mako )

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/ipmininet/router/config/base.py", line 334, in render
    cfg_content[filename] = template.render(**kwargs)
  File "/usr/local/lib/python3.8/dist-packages/mako/template.py", line 473, in render
    return runtime._render(self, self.callable_, args, data)
  File "/usr/local/lib/python3.8/dist-packages/mako/runtime.py", line 878, in _render
    _render_context(
  File "/usr/local/lib/python3.8/dist-packages/mako/runtime.py", line 920, in _render_context
    _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)
  File "/usr/local/lib/python3.8/dist-packages/mako/runtime.py", line 947, in _exec_template
    callable_(context, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/ipmininet/router/config/templates/bgpd.mako", line 104, in render_body
    on-match ${rm.exit_policy}
AttributeError: 'RouteMap' object has no attribute 'exit_policy'

Examples for running custom topology

Hi Olivier,

Thank you for implementing this extension. I have been searching endlessly on the internet to find an implementation of an IPv6 Router.

I really want to use your library, but I am really quite unfamiliar with Mininet. I am trying to run your main file from examples, but I can't. Every time i get this error:
*** Adding Routers:
Could not find an executable for a daemon!Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/dist-packages/ipmininet/examples/main.py", line 62, in
net = IPNet(topo=TOPOSargs.topo, **NET_ARGS.get(args.topo, {}))
File "/usr/local/lib/python2.7/dist-packages/ipmininet/ipnet.py", line 76, in init
*args, **kwargs)
File "build/bdist.linux-x86_64/egg/mininet/net.py", line 174, in init
File "/usr/local/lib/python2.7/dist-packages/ipmininet/ipnet.py", line 218, in build
super(IPNet, self).build()
File "build/bdist.linux-x86_64/egg/mininet/net.py", line 502, in build
File "/usr/local/lib/python2.7/dist-packages/ipmininet/ipnet.py", line 105, in buildFromTopo
self.addRouter(routerName, **topo.nodeInfo(routerName))
File "/usr/local/lib/python2.7/dist-packages/ipmininet/ipnet.py", line 88, in addRouter
r = cls(name, **defaults)
File "/usr/local/lib/python2.7/dist-packages/ipmininet/router/__router.py", line 93, in init
self.config = config[0](self, **config[1])
File "/usr/local/lib/python2.7/dist-packages/ipmininet/router/config/base.py", line 38, in init
map(self.register_daemon, daemons)
File "/usr/local/lib/python2.7/dist-packages/ipmininet/router/config/base.py", line 94, in register_daemon
require_cmd(cls.NAME, 'Could not find an executable for a daemon!')
File "/usr/local/lib/python2.7/dist-packages/ipmininet/utils.py", line 35, in require_cmd
raise RuntimeError('[%s] is not available in $PATH' % cmd)
RuntimeError: [radvd] is not available in $PATH

Could you maybe add examples as to how to create a simple topology that can be run the same way that a Mininet topology can be run through a python script?

citation

Would be nice to add a CITATION.bib containing

@Article{bonaventure2020open,
title={Open educational resources for computer networking},
author={Bonaventure, Olivier and De Coninck, Quentin and Duch{^e}ne, Fabien and Gego, Anthony and Jadin, Mathieu and Michel, Fran{\c{c}}ois and Piraux, Maxime and Poncin, Chantal and Tilmans, Olivier},
journal={ACM SIGCOMM Computer Communication Review},
volume={50},
number={3},
pages={38--45},
year={2020},
publisher={ACM New York, NY, USA}
}

__route.py create wrong command to startup daemon

origin __route.py generate command

"zebra -f /tmp/zebra_as1ra.cfg -i /tmp/zebra_as1ra.pid -z /tmp/quagga_as1ra.api -u root -k"

the argument "-k" cannot be identified, and then the bgpd cannot startup
I use [:-2] to split the command string but it's a temporary method.
And, I use the latest ipmininet code

Please create a new release of VM

I am using the provided VM image to work with IPMininet, however, when trying to use the NetworkCapture Overlay, it's not working, as the latest release 1.0 was created before this overlay was included, and no release has been cut since.

Add a "smart" overlay helper in IPTopo

Looking at https://github.com/cnp3/ipmininet/pull/43/files#diff-d4f7df1cbb97666028a98c2be8e465c1R222, and the other types of overlay we have, one could ease-up their use by adding an helper function in IPTopo directly.

This requires to:

  • Catch _getattr calls in IPTopo to detect 'unknown attributes'
  • Check the name of said unknown attribute against a list of known overlays
  • Return a wrapper object whose call creates the wanted overlay

Rought (untested) code below

class OverlayWrapper(object):
    def __init__(self, ov):
        self.ov = ov
    def __call__(self, *a, **kw):
        return self.ov(*a, **kw)

class IPTopo(object):

    OVERLAYS = {cls.__name__: OverlayWrapper(cls) for cls in (Subnet, ...))

    [...]
    def __getattr__(self, name):
        if name.startsWith('add'):
            try:
                return self.OVERLAYS[name[3:]]
            except KeyError:
                pass
         raise AttributeError('%s is neither a method of IPTopo nor refer to a known overlay' % name)    

Cannot install IPmininet

Using sudo pip3 install --upgrade git+https://github.com/cnp3/[email protected] gets this error

     Package cgroup-bin is not available, but is referred to by another package.                                                                           
  This may mean that the package is missing, has been obsoleted, or         
  is only available from another source                                     
  However the following packages replace it:                                
    cgroup-tools                                                            
                                                                            
  Package pyflakes is not available, but is referred to by another package. 
  This may mean that the package is missing, has been obsoleted, or         
  is only available from another source                                     
  However the following packages replace it:                                
    python3-pyflakes pyflakes3                                              
                                                                            
  E: Package 'cgroup-bin' has no installation candidate                     
  E: Package 'pyflakes' has no installation candidate   

and also :

    error: [Errno 17] File exists: '/tmp/pip-req-build-0_tacwvi/mininet_dependencies'                                                                   
    ----------------------------------------                                
ERROR: Command errored out with exit status 1: /usr/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-0_tacwvi/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-0_tacwvi/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-ip6tu0od/install-record.txt --single-version-externally-managed --compile --install-headers /usr/local/include/python3.9/ipmininet Check the logs for full command output.   

Any suggestion on how to fix it and install IPmininet?

the default port of bgpd is set as 1? how to modify it

generally the bgpd port is 179, however i see it is set as 1 by netstat -anpt
And i debug the __route.py, I see this: it seems that port is 179
(Pdb) p d.startup_line
'bgpd -f /tmp/bgpd_as1ra.cfg -i /tmp/bgpd_as1ra.pid -z /tmp/quagga_as1ra.api -u root -p 179'
(Pdb) n

but when I run xterm as1r1 and netstat -anpt, there is not 179 open, just 1, 2605 for bgpd, and 2601 for zebrad
how to modify it, thanks

[OpenR] The OpenR install script does not work on Ubuntu 20.04

The OpenR install script does not work on Ubuntu 20.04.

Though it was not sufficient, the first steps to debug it is to remove python2 dependencies and update gcc version:

diff --git a/ipmininet/install/build_openr-rc-20190419-11514.sh b/ipmininet/install/build_openr-rc-20190419-11514.sh
index 3823a67..b1f3264 100755
--- a/ipmininet/install/build_openr-rc-20190419-11514.sh
+++ b/ipmininet/install/build_openr-rc-20190419-11514.sh
@@ -3,9 +3,9 @@
 set -exo pipefail
 ### Install packages for Debian-based OS ###
 
-apt-get update && apt-get install -yq autoconf-archive bison build-essential cmake curl flex git gperf joe libboost-all-dev libcap-dev libdouble-conversion-dev libevent-dev libgflags-dev libgoogle-glog-dev libkrb5-dev libpcre3-dev libpthread-stubs0-dev libnuma-dev libsasl2-dev libsnappy-dev libsqlite3-dev libssl-dev libtool netcat-openbsd pkg-config sudo unzip wget python3-venv python-setuptools python3-setuptools python-pip python3-pip ccache
-apt-get install -yq gcc-'5' g++-'5'
-update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-'5' 40 --slave /usr/bin/g++ g++ /usr/bin/g++-'5'
+apt-get update && apt-get install -yq autoconf-archive bison build-essential cmake curl flex git gperf joe libboost-all-dev libcap-dev libdouble-conversion-dev libevent-dev libgflags-dev libgoogle-glog-dev libkrb5-dev libpcre3-dev libpthread-stubs0-dev libnuma-dev libsasl2-dev libsnappy-dev libsqlite3-dev libssl-dev libtool netcat-openbsd pkg-config sudo unzip wget python3-venv python3-setuptools python3-pip ccache
+apt-get install -yq gcc-'7' g++-'7'
+update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-'7' 40 --slave /usr/bin/g++ g++ /usr/bin/g++-'7'
 update-alternatives --config gcc
 
 FOLLY_REV="3ceffd7d145be3c85a2aae39f99eb86ea730bdcc"

fizz still cannot be compiled.

OpenR doesnt work

Hey, im not an expert on this, but i've been trying to implement OpenR into my ipmininet network, but even running the example script of OpenR, i still having the following issue:

net = IPNet(topo=topo,
File "/usr/local/lib/python3.10/dist-packages/ipmininet/ipnet.py", line 83, in init
super().init(ipBase=ipBase, host=host, switch=switch, link=link,
File "/usr/lib/python3/dist-packages/mininet/net.py", line 178, in init
self.build()
File "/usr/local/lib/python3.10/dist-packages/ipmininet/ipnet.py", line 206, in build
super().build()
File "/usr/lib/python3/dist-packages/mininet/net.py", line 508, in build
self.buildFromTopo( self.topo )
File "/usr/local/lib/python3.10/dist-packages/ipmininet/ipnet.py", line 113, in buildFromTopo
self.addRouter(routerName, **topo.nodeInfo(routerName))
File "/usr/local/lib/python3.10/dist-packages/ipmininet/ipnet.py", line 96, in addRouter
r = cls(name, **defaults)
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/__router.py", line 284, in init
super().init(name,
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/__router.py", line 257, in init
super().init(name, config=config, *args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/__router.py", line 110, in init
self.nconfig = config[0](self, **config[1])
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/config/base.py", line 498, in init
super().init(node, daemons=daemon_list, *args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/config/base.py", line 189, in init
super().init(node, sysctl=self._sysctl, *args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/config/base.py", line 53, in init
self.register_daemon(d)
File "/usr/local/lib/python3.10/dist-packages/ipmininet/router/config/base.py", line 119, in register_daemon
require_cmd(cls.NAME, 'Could not find an executable for a daemon!')
File "/usr/local/lib/python3.10/dist-packages/ipmininet/utils.py", line 43, in require_cmd
raise RuntimeError('[%s] is not available in $PATH' % cmd)
RuntimeError: [openr] is not available in $PATH

Pin mininet/... version

The current setup.py script lists dependencies, but not their version.

It would make sense to explicitly pin the version used by ipmininet to ensure that future updates don't break things...

Out of all the dependencies, I think we should:

  • Pin mininet to an exact version
  • restrict mako to a major version
  • specify a minimum version for everything else

Is mininet even on pypi at all? If not, we can add in the setup script how to install the particular version we require (so that issuing 'setup.py install' is the one-liner to get ipmininet running)

Abstraction for interface parameters

I think that it would be interesting to have an abstraction for interface parameters (IP addresses, tc parameters, radvd parameters,...) like with have for daemons (router.addDaemon()).

Instead of

self.addLink(r1, r2, params1={"ip": ("2001:1341::1/64", "2001:2141::1/64"), "delay": "1ms","bw": 10}, params2={"ip": ("2001:1341::2/64", "2001:2141::2/64"), "delay": "1ms","bw": 10})

we could have

l = self.addLink(r1, r2)
l[r1].addParams(ip=("2001:1341::1/64", "2001:2141::1/64"), delay="1ms", bw=10)
l[r2].addParams(ip=("2001:1341::2/64", "2001:2141::2/64"), delay="1ms", bw=10)

or when we have parameters for both interfaces

l.addSymParams(delay="1ms", bw=10)

We could also have a separate abstraction for adding IP subnets (with first interface address always ending by ::1 and the second one ending by ::2)

l.addSubnets("2001:1341::/64", "2001:2141::/64")

Do you have any though on this @oliviertilmans ?

Is adding a OpenFlow Switch in a network possbile?

I would like to know if I can add a Openflow Switch to my topology, like in mininet. In mininet I have the problem, that I cannot assign ipv6 addresses, more like it does not work, but I need the ovs functionality.

Can't open the srv6 example correctly.

Sorry to interrupt. When I tried to start the srv6 case, the following error occurred. If possible, please help me solve the problem. Thank you very much

vihanchou@Ubuntu18:~/Desktop/SRv6$ sudo python -m ipmininet.examples --topo=ipv6_segment_routing

*** Adding Routers:
r1 r2 r3 r4 r5 r6
*** Creating network
*** Adding hosts:
h1 h3 h4 h6
*** Adding switches:

*** Adding links:
(h1, r1) (h3, r3) (h4, r4) (h6, r6) (r1, r2) (r1, r6) (r2, r3) (r2, r5) (r3, r4) (r4, r5) (r5, r6)
*** Configuring hosts
h1 h3 h4 h6
*** Found 17 broadcast domains
*** Allocating IPv4 addresses
*** Allocating IPv6 addresses
*** Starting controller

*** Starting 0 switches

*** Starting, 6 routers
r1 ospf6d configuration check failed [rcode: 1 ]
stdout:
stderr: *** Error reading config: There is no such command.
*** Error occurred processing line 47, below:
ospf6 router-id 192.168.11.2

Config checks failed, aborting!*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes
killall controller ofprotocol ofdatapath ping nox_corelt-nox_core ovs-openflowd ovs-controllerovs-testcontroller udpbwtest mnexec ivs ryu-manager 2> /dev/null
killall -9 controller ofprotocol ofdatapath ping nox_corelt-nox_core ovs-openflowd ovs-controllerovs-testcontroller udpbwtest mnexec ivs ryu-manager 2> /dev/null
pkill -9 -f "sudo mnexec"
*** Removing junk from /tmp
rm -f /tmp/vconn* /tmp/vlogs* /tmp/.out /tmp/.log
*** Removing old X11 tunnels
*** Removing excess kernel datapaths
ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'
*** Removing OVS datapaths
ovs-vsctl --timeout=1 list-br
ovs-vsctl --timeout=1 list-br
*** Removing all links of the pattern foo-ethX
ip link show | egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'
ip link show
*** Killing stale mininet node processes
pkill -9 -f mininet:
*** Shutting down stale tunnels
pkill -9 -f Tunnel=Ethernet
pkill -9 -f .ssh/mn
rm -f ~/.ssh/mn/*
*** Cleanup complete.

[Install failed] Can't install in ubuntu 22.04

/bin/bash ./libtool --tag=CC --mode=link gcc -g -O2 -Wall -I/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/openflow/include -Wshadowpkg-config --cflags libconfig-static -Wl,-E -L/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/openflow/libpkg-config --libs libconfig-o oflops channel_info.o context.o control.o module_run.o module_default.o oflops.o oflops_pcap.o timer_event.o msg.o log.o traffic_generator.o usage.o -ldl -lpcap -lnetsnmp -loflops_test -lpthread libtool: link: gcc -g -O2 -Wall -I/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/openflow/include -Wshadow -Wl,-E -o oflops channel_info.o context.o control.o module_run.o module_default.o oflops.o oflops_pcap.o timer_event.o msg.o log.o traffic_generator.o usage.o -L/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/openflow/lib -ldl -lpcap /tmp/pip-req-build-i1w9m5u1/mininet_dependencies/oflops/.libs/liboflops_test.a -lconfig -lnetsnmp -lpthread /usr/bin/ld: /tmp/pip-req-build-i1w9m5u1/mininet_dependencies/oflops/.libs/liboflops_test.a(wc_event.o): in functionevent_loop':
/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/oflops/wc_event.c:399: undefined reference to `pthread_yield'
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:589: oflops] Error 1
make[2]: Leaving directory '/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/oflops'
make[1]: *** [Makefile:659: all-recursive] Error 1
make[1]: Leaving directory '/tmp/pip-req-build-i1w9m5u1/mininet_dependencies/oflops'
make: *** [Makefile:445: all] Error 2
[end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for ipmininet
Running setup.py clean for ipmininet
Failed to build ipmininet
Installing collected packages: ipmininet
Running setup.py install for ipmininet ... error
error: subprocess-exited-with-error

× Running setup.py install for ipmininet did not run successfully.
│ exit code: 1
╰─> [21 lines of output]
/usr/lib/python3/dist-packages/pkg_resources/init.py:116: PkgResourcesDeprecationWarning: 0.1.43ubuntu1 is an invalid version and will not be supported in a future release
warnings.warn(
/usr/lib/python3/dist-packages/pkg_resources/init.py:116: PkgResourcesDeprecationWarning: 1.1build1 is an invalid version and will not be supported in a future release
warnings.warn(
/usr/lib/python3/dist-packages/setuptools/installer.py:27: SetuptoolsDeprecationWarning: setuptools.installer is deprecated. Requirements should be satisfied by a PEP 517 installer.
warnings.warn(
running install
/usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
DISTRIB_ID=Ubuntu
DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"

  *** pip3 -V
  
  *** apt-get update
  Hit:1 http://us.archive.ubuntu.com/ubuntu jammy InRelease
  Hit:2 http://us.archive.ubuntu.com/ubuntu jammy-updates InRelease
  Hit:3 http://us.archive.ubuntu.com/ubuntu jammy-backports InRelease
  Hit:4 http://us.archive.ubuntu.com/ubuntu jammy-security InRelease
  Reading package lists...
  error: [Errno 17] File exists: '/tmp/pip-req-build-i1w9m5u1/mininet_dependencies'
  [end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

× Encountered error while trying to install package.
╰─> ipmininet

note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
root@ubuntu2204siqian1 ipmininet (master) # uname -a
Linux ubuntu2204siqian1 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu2204siqian1 ipmininet (master) #
install failled with sudo pip install --upgrade git+https://github.com/cnp3/[email protected]`

Various pitfalls when trying to use complex BGP filters

So I want to write something like the following to the bgpd config (with a more complex prefix list in practice):

router bgp 200
    ...
    address-family ipv4 unicast
        neighbor 192.168.100.1 route-map r1-ipv4-in in
...

ip prefix-list inbound-filter deny 192.168.0.0/16 ge 16
ip prefix-list inbound-filter permit 0.0.0.0/0 le 32

route-map r1-ipv4-in permit 10
    match ip address prefix-list inbound-filter
!

I ran into a number of pitfalls trying to do this, though I did eventually get something working. I figure it's good to list these anyway, even if only as a resource to point other to.

Summary:

  1. Prefix lists are always permit, there's no way to add a deny entry, use a deny route map instead
  2. You can only properly pass the filter functions a single prefix list, even though they allegedly take a tuple
  3. You can't give multiple prefix lists the same name
  4. The order does not autoincrement between filtering calls which using the same route map name (i.e. the autogenerated one)
  5. If you have multiple different route map names all going the same direction, only the last one (including the autogenerated defaults) gets applied

Examples

        r2.get_config(BGP).permit(from_peer=r1, matching=(
            PrefixList(name="inbound-filter", family="ipv4", entries=(
                PrefixListEntry("192.168.1.0/24", ge=24),
                PrefixListEntry("192.168.2.0/24", ge=24),
            )),
            PrefixList(name="inbound-filter", family="ipv4", entries=(
                PrefixListEntry("192.168.3.0/24", ge=24),
            )),
            PrefixList(name="inbound-filter-2", family="ipv4", entries=(
                PrefixListEntry("192.168.4.0/24", ge=24),
            )),
        ))

This generates the following (ignoring the default prefix lists/route maps):

ip prefix-list inbound-filter permit 192.168.1.0/24  ge 24
ip prefix-list inbound-filter permit 192.168.2.0/24  ge 24
ip prefix-list inbound-filter-2 permit 192.168.4.0/24  ge 24

route-map r1-ipv4-in permit 10
   match ip address prefix-list inbound-filter
   match ip address prefix-list inbound-filter
   match ip address prefix-list inbound-filter-2
!

Firstly, trying to write the same prefix list twice results in only the first being written. This is kind of a "don't do that then" situation, but figured it's worth noting, I accidentally ran into when I forgot entries was a tuple. The first inbound-filter prefix list is written to file perfectly fine however. The other thing worth noting here is that it adds every prefix list as it's own match statement to the route map, when bgpd only accepts the last.

r2# show route-map r1-ipv4-in
BGP:
route-map: r1-ipv4-in Invoked: 0 Optimization: enabled Processed Change: false
 permit, sequence 10 Invoked 0
  Match clauses:
    ip address prefix-list inbound-filter-2
  Set clauses:

This is the same sort of "don't do that then" type situation, but again it's something I blindly ran into.

Now trying to add a deny entry:
Generates:

        r2.get_config(BGP).permit(from_peer=r1, matching=(
            PrefixList(name="inbound-filter-permit", family="ipv4", entries=(
                PrefixListEntry("192.168.1.0/24", ge=24),
                PrefixListEntry("192.168.2.0/24", ge=24),
            )),
        ))
        r2.get_config(BGP).deny(from_peer=r1, matching=(
            PrefixList(name="inbound-filter-deny", family="ipv4", entries=(
                PrefixListEntry("192.168.3.0/24", ge=24),
            )),
        ))
ip prefix-list inbound-filter-permit permit 192.168.1.0/24  ge 24
ip prefix-list inbound-filter-permit permit 192.168.2.0/24  ge 24
ip prefix-list inbound-filter-deny permit 192.168.3.0/24  ge 24

route-map r1-ipv4-in deny 10
    match ip address prefix-list inbound-filter-deny
!

Because neither filter explicitly specified a name, they both got the same autogenerated one, and neither explicitly specified an order so they they both used the same default one. In this case only the last call is added to the route map.

Another issue you see in this case is that the deny only applies to the route map - there's no way for a prefix list to get a deny entry.

Giving both filters names leads to another interesting situation.

    address-family ipv4 unicast
        neighbor 192.168.100.1 route-map inbound-permit in
        neighbor 192.168.100.1 route-map inbound-deny in
        neighbor 192.168.100.1 route-map r1-ipv4-in in
...

ip prefix-list inbound-filter permit 192.168.1.0/24  ge 24
ip prefix-list inbound-filter permit 192.168.2.0/24  ge 24
ip prefix-list hello-world-v4 permit 0.0.0.0/0 le 32 

route-map inbound-permit permit 10
    match ip address prefix-list inbound-filter
!
!
route-map inbound-deny deny 10
    match ip address prefix-list inbound-filter
!
!
route-map r1-ipv4-in permit 65535
    match ip address prefix-list hello-world-v4
!

Each different name gets added to the file separately as it's own route map, and it tries to apply all of them to the neighbor. Bgpd again only uses the last one however - the default in this case.

If we go back to the autogenerated name, but use different orders, we get closest to what I initially wanted.

        r2.get_config(BGP).permit(order=10, from_peer=r1, matching=(
            PrefixList(name="inbound-filter-permit", family="ipv4", entries=(
                PrefixListEntry("192.168.1.0/24", ge=24),
                PrefixListEntry("192.168.2.0/24", ge=24),
            )),
        ))
        r2.get_config(BGP).deny(order=15, from_peer=r1, matching=(
            PrefixList(name="inbound-filter-deny", family="ipv4", entries=(
                PrefixListEntry("192.168.3.0/24", ge=24),
            )),
        ))
ip prefix-list inbound-filter-permit permit 192.168.1.0/24  ge 24
ip prefix-list inbound-filter-permit permit 192.168.2.0/24  ge 24
ip prefix-list inbound-filter-deny permit 192.168.3.0/24  ge 24

route-map r1-ipv4-in permit 10
    match ip address prefix-list inbound-filter-permit
!
route-map r1-ipv4-in deny 15
    match ip address prefix-list inbound-filter-deny
!

Adapting this eventually led me to the behavior I wanted.

Hosts can't ping each other in a simple topology.

Hello I am new to ipmininet. I tried a very simple topology, but the hosts can't successfully ping each other. I really need help, thank you!

#!/usr/bin/python3

import sys
import os
import getopt
import subprocess


from ipmininet.iptopo import IPTopo
from ipmininet.ipnet import IPNet
from ipmininet.cli import IPCLI
from ipmininet.topologydb import TopologyDB


class MyTopology(IPTopo):
    def __init__(self, *args, **kwargs):
        self.switch_count = 0
        super().__init__(*args, **kwargs)

    def build(self, *args, **kwargs):
        r1 = self.addRouter("r1")
        r2 = self.addRouter("r2")

        h1 = self.addHost("h1")
        h2 = self.addHost("h2")

        self.addLink(r1, r2)
        self.addLink(h1, r1)
        self.addLink(r2, h2)

        super().build(*args, **kwargs)

    def ping_all(self, net):
        h1 = net.get('h1')
        h2 = net.get('h2')
        h1.defaultIntf().updateIP6()
        h2.defaultIntf().updateIP6()
        print(h1.cmd("ping -c 3 "+ h2.defaultIntf().ip6))
        print(h2.cmd("ping -c 3 "+ h1.defaultIntf().ip6))



def main():
    exp = MyTopology()
    net = IPNet(topo=exp, use_v4=False, use_v6=True)

    db = TopologyDB(net=net)
    db_path = "topologydb.json"
    db.save(db_path)

    try:
        net.start()
        exp.ping_all(net)

    finally:
        net.stop()



if __name__ == '__main__':
    try:
        main()
    except:
        print("!"*80)
        print("Exception! Cleaning!")
        print("!"*80)
        import traceback
        traceback.print_exc()
        subprocess.call('sudo python3 -m ipmininet.clean', shell=True)

Does ipmininet available for both SDN(by openflow ) and SRv6?

Is there any switching device in ipmininet that supports both openflow and srv6? In other words, if the switching device detects srv6 packets, it will forward them by segment routing, and when it detects other packets, it will forward them by openflow policy. Does the switch or router of ipmininet support such a function? I'm looking forward to your reply. Thank you

How to modify FRRouting configuration file settings?

Hello I am new to ipmininet. I want to know how to use VTY shell to view the configuration of each router in a simple topology. I tried the example file static_routing.py. Whenever I access the CLI of any router and use vtysh, it always shows the configuration file of the router with the highest number. I would like to know how to change this so that each router corresponds to its own configuration file and can display and perform routing operations.
r1.addDaemon(STATIC, static_routes=[StaticRoute("2042:2b::/64", "2042:12::2"), StaticRoute("10.62.0.0/24", "10.12.0.2")]) r2.addDaemon(STATIC, static_routes=[StaticRoute("2042:1a::/64", "2042:12::1"), StaticRoute("10.51.0.0/24", "10.12.0.1")])
The image below shows that I have opened the terminal for router r1 and used vtysh, but it is displaying the routing information for r2.

q

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.