Simplify port specification.

For the moment, I've removed the ability to specify
a dict of options without using **. This is a slightly
unfortunate trade-off since it simplifies implementation
at the expense of making the API slightly less convenient
(if somewhat more consistent.)
This commit is contained in:
Bob Lantz
2012-03-25 15:39:18 -07:00
parent 2d924f8a65
commit e1246c3741
2 changed files with 54 additions and 79 deletions
+1 -5
View File
@@ -269,11 +269,7 @@ class Mininet( object ):
src, dst = self.nameToNode[ srcName ], self.nameToNode[ dstName ] src, dst = self.nameToNode[ srcName ], self.nameToNode[ dstName ]
params = topo.linkInfo( srcName, dstName ) params = topo.linkInfo( srcName, dstName )
srcPort, dstPort = topo.port( srcName, dstName ) srcPort, dstPort = topo.port( srcName, dstName )
if not params: self.addLink( src, dst, srcPort, dstPort, **params )
params = {}
params.setdefault( 'port1', srcPort)
params.setdefault( 'port2', dstPort)
self.addLink( src, dst, **params )
info( '(%s, %s) ' % ( src.name, dst.name ) ) info( '(%s, %s) ' % ( src.name, dst.name ) )
info( '\n' ) info( '\n' )
+52 -73
View File
@@ -30,83 +30,73 @@ class Topo(object):
self.node_info = {} self.node_info = {}
self.link_info = {} # (src, dst) tuples hash to EdgeInfo objects self.link_info = {} # (src, dst) tuples hash to EdgeInfo objects
self.hopts = {} if hopts is None else hopts self.hopts = {} if hopts is None else hopts
self.sopts = {} if sopts is None else lopts self.sopts = {} if sopts is None else sopts
self.lopts = {} if lopts is None else lopts self.lopts = {} if lopts is None else lopts
self.ports = {} # ports[src][dst] is port on src that connects to dst self.ports = {} # ports[src][dst] is port on src that connects to dst
def add_node(self, name, *args, **opts): def add_node(self, name, **opts):
"""Add Node to graph. """Add Node to graph.
add_node('name', dict) <or> add_node('name', **opts)
name: name name: name
args: dict of node options opts: node options
opts: node options""" returns: node name"""
self.g.add_node(name) self.g.add_node(name)
if args and type(args[0]) is dict:
opts = args[0]
self.node_info[name] = opts self.node_info[name] = opts
return name return name
def add_host(self, name, *args, **opts): def add_host(self, name, **opts):
"""Convenience method: Add host to graph. """Convenience method: Add host to graph.
add_host('name', dict) <or> add_host('name', **opts) name: host name
name: name opts: host options
args: dict of node options returns: host name"""
opts: node options"""
if not opts and self.hopts: if not opts and self.hopts:
opts = self.hopts opts = self.hopts
return self.add_node(name, *args, **opts) return self.add_node(name, **opts)
def add_switch(self, name, **opts): def add_switch(self, name, **opts):
"""Convenience method: Add switch to graph. """Convenience method: Add switch to graph.
add_switch('name', dict) <or> add_switch('name', **opts) name: switch name
name: name opts: switch options
args: dict of node options returns: switch name"""
opts: node options"""
if not opts and self.sopts: if not opts and self.sopts:
opts = self.sopts opts = self.sopts
result = self.add_node(name, is_switch=True, **opts) result = self.add_node(name, is_switch=True, **opts)
return result return result
def add_link(self, src, dst, *args, **opts): def add_link(self, node1, node2, port1=None, port2=None,
"""Add link (Node, Node) to topo. *default, **opts):
add_link(src, dst, dict) <or> add_link(src, dst, **opts) """node1, node2: nodes to link together
src: src name port1, port2: ports (optional)
dst: dst name opts: link options (optional)
args: dict of node options returns: link info key"""
params: link parameters""" if not opts and self.lopts:
src, dst = sorted([src, dst], key=naturalSeq) opts = self.lopts
self.g.add_edge(src, dst) self.add_port(node1, node2, port1, port2)
if args and type(args[0]) is dict: key = tuple(self.sorted([node1, node2]))
opts = args[0] self.link_info[key] = opts
if not opts and self.sopts: self.g.add_edge(*key)
opts = self.sopts return key
self.link_info[(src, dst)] = opts
self.add_port(src, dst)
return src, dst
def add_port(self, src, dst): def add_port(self, src, dst, sport=None, dport=None):
'''Generate port mapping for new edge. '''Generate port mapping for new edge.
@param src source switch name
@param src source switch DPID @param dst destination switch name
@param dst destination switch DPID
''' '''
self.ports.setdefault(src, {})
self.ports.setdefault(dst, {})
# New port: number of outlinks + base
src_base = 1 if self.is_switch(src) else 0 src_base = 1 if self.is_switch(src) else 0
dst_base = 1 if self.is_switch(dst) else 0 dst_base = 1 if self.is_switch(dst) else 0
if src not in self.ports: if sport is None:
self.ports[src] = {} sport = len(self.ports[src]) + src_base
if dst not in self.ports[src]: if dport is None:
# num outlinks dport = len(self.ports[dst]) + dst_base
self.ports[src][dst] = len(self.ports[src]) + src_base self.ports[src][dst] = sport
if dst not in self.ports: self.ports[dst][src] = dport
self.ports[dst] = {}
if src not in self.ports[dst]:
# num outlinks
self.ports[dst][src] = len(self.ports[dst]) + dst_base
def nodes(self, sort=True): def nodes(self, sort=True):
"Return nodes in graph" "Return nodes in graph"
if sort: if sort:
return sorted( self.g.nodes(), key=natural ) return self.sorted( self.g.nodes() )
else: else:
return self.g.nodes() return self.g.nodes()
@@ -137,7 +127,8 @@ class Topo(object):
if not sort: if not sort:
return self.g.edges() return self.g.edges()
else: else:
return sorted( self.g.edges(), key=naturalSeq ) links = [tuple(self.sorted(e)) for e in self.g.edges()]
return sorted( links, key=naturalSeq )
def port(self, src, dst): def port(self, src, dst):
'''Get port number. '''Get port number.
@@ -154,7 +145,7 @@ class Topo(object):
def linkInfo( self, src, dst ): def linkInfo( self, src, dst ):
"Return link metadata" "Return link metadata"
src, dst = sorted((src, dst), key=naturalSeq) src, dst = self.sorted([src, dst])
return self.link_info[(src, dst)] return self.link_info[(src, dst)]
def nodeInfo( self, name ): def nodeInfo( self, name ):
@@ -197,31 +188,19 @@ class SingleSwitchReversedTopo(SingleSwitchTopo):
Useful to verify that Mininet properly handles custom port numberings. Useful to verify that Mininet properly handles custom port numberings.
''' '''
def __init__(self, k=2, **opts):
'''Init.
def port(self, src, dst): @param k number of hosts
'''Get port number. @param enable_all enables all nodes and switches?
@param src source switch DPID
@param dst destination switch DPID
@return tuple (src_port, dst_port):
src_port: port on source switch leading to the destination switch
dst_port: port on destination switch leading to the source switch
''' '''
if src == 1: super(SingleSwitchTopo, self).__init__(**opts)
if dst in range(2, self.k + 2): self.k = k
dst_index = dst - 2 switch = self.add_switch('s1')
highest = self.k - 1 for h in irange(1, k):
return (highest - dst_index, 0) host = self.add_host('h%s' % h)
else: self.add_link(host, switch,
raise Exception('unexpected dst: %i' % dst) port1=0, port2=(k - h + 1))
elif src in range(2, self.k + 2):
if dst == 1:
raise Exception('unexpected dst: %i' % dst)
else:
src_index = src - 2
highest = self.k - 1
return (0, highest - src_index)
class LinearTopo(Topo): class LinearTopo(Topo):
"Linear topology of k switches, with one host per switch." "Linear topology of k switches, with one host per switch."