Commit 39080516 authored by Italo Cunha's avatar Italo Cunha Committed by Peter V. Saveliev

Sort addresses in IPaddrSet

Primary and secondary addresses depend on the order in which they
are added to an interface [1] .  This commit makes pyroute2 add IP
addresses in the same order Interface.add_ip is called.

This is achieved by changing LinkedSet.raw from a plain dict to an
OrderedDict and by reimplementing the set operators to preserve
ordering.

 [1] iproute2 docs: http://baturin.org/docs/iproute2/#Notes
parent 93b7874b
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
''' '''
import struct import struct
import threading import threading
from collections import OrderedDict
from socket import inet_pton from socket import inet_pton
from socket import AF_INET from socket import AF_INET
from socket import AF_INET6 from socket import AF_INET6
...@@ -35,7 +36,7 @@ class LinkedSet(set): ...@@ -35,7 +36,7 @@ class LinkedSet(set):
self.target = threading.Event() self.target = threading.Event()
self.targets = {self.target: _check_default_target} self.targets = {self.target: _check_default_target}
self._ct = None self._ct = None
self.raw = {} self.raw = OrderedDict()
self.links = [] self.links = []
self.exclusive = set() self.exclusive = set()
...@@ -217,3 +218,70 @@ class IPaddrSet(LinkedSet): ...@@ -217,3 +218,70 @@ class IPaddrSet(LinkedSet):
return self.raw[key] return self.raw[key]
else: else:
TypeError('wrong key type') TypeError('wrong key type')
class SortedIPaddrSet(IPaddrSet):
def __init__(self, *argv, **kwarg):
super(SortedIPaddrSet, self).__init__(*argv, **kwarg)
if argv and isinstance(argv[0], SortedIPaddrSet):
# Re-initialize self.raw from argv[0].raw to preserve order:
self.raw = OrderedDict(argv[0].raw)
def __and__(self, other):
nset = SortedIPaddrSet(self)
return nset.__iand__(other)
def __iand__(self, other):
for key in self.raw:
if key not in other:
self.remove(key)
return self
def __rand__(self, other):
return self.__and__(other)
def __xor__(self, other):
nset = SortedIPaddrSet(self)
return nset.__ixor__(other)
def __ixor__(self, other):
if not isinstance(other, SortedIPaddrSet):
return RuntimeError('SortedIPaddrSet instance required')
xor_keys = set(self.raw.keys()) ^ set(other.raw.keys())
for key in xor_keys:
if key in self:
self.remove(key)
else:
self.add(key, raw=other.raw[key], cascade=False)
return self
def __rxor__(self, other):
return self.__xor__(other)
def __or__(self, other):
nset = SortedIPaddrSet(self)
return nset.__ior__(other)
def __ior__(self, other):
if not isinstance(other, SortedIPaddrSet):
return RuntimeError('SortedIPaddrSet instance required')
for key, value in other.raw.items():
if key not in self:
self.add(key, raw=value, cascade=False)
return self
def __ror__(self, other):
return self.__or__(other)
def __sub__(self, other):
nset = SortedIPaddrSet(self)
return nset.__isub__(other)
def __isub__(self, other):
for key in other:
if key in self:
self.remove(key)
return self
def __iter__(self):
return iter(self.raw)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment