mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
Add rtnetlink api's for 'bridge vlan' and modify 'bridge vlan' commands
in vlan module to use rtnetlink api Ticket: CM-4173 Reviewed By: Testing Done: Tested new bridge driver svi up/down This does not move all 'bridge vlan' commands to rtnetlink yet.
This commit is contained in:
@@ -103,9 +103,11 @@ class vlan(moduleBase):
|
|||||||
to the bridge """
|
to the bridge """
|
||||||
if self.ipcmd.bridge_is_vlan_aware(bridgename):
|
if self.ipcmd.bridge_is_vlan_aware(bridgename):
|
||||||
if add:
|
if add:
|
||||||
self.ipcmd.bridge_vids_add(bridgename, [vlanid])
|
rtnetlink_api.rtnl_api.bridge_vlan(add=True, dev=bridgename,
|
||||||
|
vid=vlanid, master=False)
|
||||||
else:
|
else:
|
||||||
self.ipcmd.bridge_vids_del(bridgename, [vlanid])
|
rtnetlink_api.rtnl_api.bridge_vlan(add=False, dev=bridgename,
|
||||||
|
vid=vlanid, master=False)
|
||||||
|
|
||||||
def _bridge_vid_check(self, ifaceobj, ifaceobjcurr, bridgename, vlanid):
|
def _bridge_vid_check(self, ifaceobj, ifaceobjcurr, bridgename, vlanid):
|
||||||
""" If the lower device is a vlan aware bridge, check if the vlanid
|
""" If the lower device is a vlan aware bridge, check if the vlanid
|
||||||
|
@@ -28,6 +28,7 @@ RTMGRP_IPV6_ROUTE = 0x400
|
|||||||
RTM_NEWLINK = 16
|
RTM_NEWLINK = 16
|
||||||
RTM_DELLINK = 17
|
RTM_DELLINK = 17
|
||||||
RTM_GETLINK = 18
|
RTM_GETLINK = 18
|
||||||
|
RTM_SETLINK = 19
|
||||||
RTM_NEWADDR = 20
|
RTM_NEWADDR = 20
|
||||||
RTM_DELADDR = 21
|
RTM_DELADDR = 21
|
||||||
RTM_GETADDR = 22
|
RTM_GETADDR = 22
|
||||||
@@ -91,15 +92,6 @@ class Nlmsg(Structure):
|
|||||||
def rta_linkinfo(self, addr, rtas):
|
def rta_linkinfo(self, addr, rtas):
|
||||||
total_len = 0
|
total_len = 0
|
||||||
|
|
||||||
# Start nested linkinfo
|
|
||||||
#rta = Rtattr.from_address(addr)
|
|
||||||
#rta.rta_type = IFLA_LINKINFO
|
|
||||||
#rta.rta_len = RTA_LENGTH(0)
|
|
||||||
#rta_len = NLMSG_ALIGN(rta.rta_len)
|
|
||||||
#total_len += rta_len
|
|
||||||
#addr += rta_len
|
|
||||||
#nest_start_linkinfo = rta
|
|
||||||
|
|
||||||
# Check interface kind
|
# Check interface kind
|
||||||
kind = rtas.get(IFLA_INFO_KIND)
|
kind = rtas.get(IFLA_INFO_KIND)
|
||||||
if kind == 'vlan':
|
if kind == 'vlan':
|
||||||
@@ -130,11 +122,21 @@ class Nlmsg(Structure):
|
|||||||
|
|
||||||
return total_len
|
return total_len
|
||||||
|
|
||||||
def rta_linkinfo_data_vlan(self, addr, rtas):
|
def rta_bridge_vlan_info(self, rta, value):
|
||||||
return self.pack_rtas_new(rtas, addr, self.rta_linkinfo_data_vlan_policy())
|
if value:
|
||||||
|
data = RTA_DATA(rta)
|
||||||
|
memmove(data, addressof(value), sizeof(value))
|
||||||
|
rta.rta_len = RTA_LENGTH(sizeof(value))
|
||||||
|
return rta.rta_len
|
||||||
|
|
||||||
def rta_linkinfo_data(self, addr, rtas):
|
def rta_af_spec(self, addr, rtas):
|
||||||
return self.pack_rtas_new(rtas, addr, self.rta_linkinfo_data_vlan_policy())
|
total_len = 0
|
||||||
|
|
||||||
|
# XXX: Check family (Assumes bridge family for now)
|
||||||
|
rta_len = self.pack_rtas_new(rtas, addr,
|
||||||
|
self.rta_bridge_af_spec_policy())
|
||||||
|
total_len += rta_len
|
||||||
|
return total_len
|
||||||
|
|
||||||
def unpack_rtas(self, which_ones=[]):
|
def unpack_rtas(self, which_ones=[]):
|
||||||
len = self.nlh.nlmsg_len - NLMSG_LENGTH(sizeof(self))
|
len = self.nlh.nlmsg_len - NLMSG_LENGTH(sizeof(self))
|
||||||
@@ -225,10 +227,13 @@ class Nlmsg(Structure):
|
|||||||
return addr
|
return addr
|
||||||
|
|
||||||
def rta_uint8_array(self, rta, value=None):
|
def rta_uint8_array(self, rta, value=None):
|
||||||
if value:
|
|
||||||
assert(False)
|
|
||||||
else:
|
|
||||||
data = RTA_DATA(rta)
|
data = RTA_DATA(rta)
|
||||||
|
if value:
|
||||||
|
s = (c_uint8 * len(value)).from_buffer_copy(value)
|
||||||
|
memmove(data, addressof(s), len(value))
|
||||||
|
rta.rta_len = RTA_LENGTH(len(value))
|
||||||
|
return rta.rta_len
|
||||||
|
else:
|
||||||
array = (c_uint8 * RTA_PAYLOAD(rta))()
|
array = (c_uint8 * RTA_PAYLOAD(rta))()
|
||||||
memmove(array, data, RTA_PAYLOAD(rta))
|
memmove(array, data, RTA_PAYLOAD(rta))
|
||||||
return array
|
return array
|
||||||
@@ -564,6 +569,27 @@ MACVLAN_MODE_VEPA = 2
|
|||||||
MACVLAN_MODE_BRIDGE = 3
|
MACVLAN_MODE_BRIDGE = 3
|
||||||
MACVLAN_MODE_PASSTHRU = 4
|
MACVLAN_MODE_PASSTHRU = 4
|
||||||
|
|
||||||
|
# BRIDGE IFLA_AF_SPEC attributes
|
||||||
|
IFLA_BRIDGE_FLAGS = 0
|
||||||
|
IFLA_BRIDGE_MODE = 1
|
||||||
|
IFLA_BRIDGE_VLAN_INFO = 2
|
||||||
|
|
||||||
|
# BRIDGE_VLAN_INFO flags
|
||||||
|
BRIDGE_VLAN_INFO_MASTER = 1
|
||||||
|
BRIDGE_VLAN_INFO_PVID = 2
|
||||||
|
BRIDGE_VLAN_INFO_UNTAGGED = 4
|
||||||
|
|
||||||
|
# Bridge flags
|
||||||
|
BRIDGE_FLAGS_MASTER = 1
|
||||||
|
BRIDGE_FLAGS_SELF = 2
|
||||||
|
|
||||||
|
class BridgeVlanInfo(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('flags', c_uint16),
|
||||||
|
('vid', c_uint16),
|
||||||
|
('vid_end', c_uint16),
|
||||||
|
]
|
||||||
|
|
||||||
class Ifinfomsg(Nlmsg):
|
class Ifinfomsg(Nlmsg):
|
||||||
|
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@@ -601,6 +627,14 @@ class Ifinfomsg(Nlmsg):
|
|||||||
}
|
}
|
||||||
return fns
|
return fns
|
||||||
|
|
||||||
|
def rta_bridge_af_spec_policy(self):
|
||||||
|
# Assume bridge family for now
|
||||||
|
fns = {
|
||||||
|
IFLA_BRIDGE_FLAGS : self.rta_uint16,
|
||||||
|
IFLA_BRIDGE_VLAN_INFO : self.rta_bridge_vlan_info,
|
||||||
|
}
|
||||||
|
return fns
|
||||||
|
|
||||||
def rta_policy(self):
|
def rta_policy(self):
|
||||||
fns = {
|
fns = {
|
||||||
IFLA_UNSPEC: self.rta_wtf,
|
IFLA_UNSPEC: self.rta_wtf,
|
||||||
@@ -629,7 +663,7 @@ class Ifinfomsg(Nlmsg):
|
|||||||
IFLA_STATS64: self.rta_none,
|
IFLA_STATS64: self.rta_none,
|
||||||
IFLA_VF_PORTS: self.rta_none,
|
IFLA_VF_PORTS: self.rta_none,
|
||||||
IFLA_PORT_SELF: self.rta_none,
|
IFLA_PORT_SELF: self.rta_none,
|
||||||
IFLA_AF_SPEC: self.rta_none,
|
IFLA_AF_SPEC: self.rta_af_spec,
|
||||||
IFLA_GROUP: self.rta_none,
|
IFLA_GROUP: self.rta_none,
|
||||||
IFLA_NET_NS_FD: self.rta_none,
|
IFLA_NET_NS_FD: self.rta_none,
|
||||||
IFLA_EXT_MASK: self.rta_none,
|
IFLA_EXT_MASK: self.rta_none,
|
||||||
@@ -664,7 +698,7 @@ class Ifinfomsg(Nlmsg):
|
|||||||
IFLA_STATS64: self.rta_none,
|
IFLA_STATS64: self.rta_none,
|
||||||
IFLA_VF_PORTS: self.rta_none,
|
IFLA_VF_PORTS: self.rta_none,
|
||||||
IFLA_PORT_SELF: self.rta_none,
|
IFLA_PORT_SELF: self.rta_none,
|
||||||
IFLA_AF_SPEC: self.rta_none,
|
IFLA_AF_SPEC: self.rta_af_spec,
|
||||||
IFLA_GROUP: self.rta_none,
|
IFLA_GROUP: self.rta_none,
|
||||||
IFLA_NET_NS_FD: self.rta_none,
|
IFLA_NET_NS_FD: self.rta_none,
|
||||||
IFLA_EXT_MASK: self.rta_none,
|
IFLA_EXT_MASK: self.rta_none,
|
||||||
@@ -738,6 +772,7 @@ class RtNetlink(Netlink):
|
|||||||
RTM_NEWROUTE: "RTM_NEWROUTE",
|
RTM_NEWROUTE: "RTM_NEWROUTE",
|
||||||
RTM_DELROUTE: "RTM_DELROUTE",
|
RTM_DELROUTE: "RTM_DELROUTE",
|
||||||
RTM_NEWLINK: "RTM_NEWLINK",
|
RTM_NEWLINK: "RTM_NEWLINK",
|
||||||
|
RTM_SETLINK: "RTM_SETLINK",
|
||||||
RTM_DELLINK: "RTM_DELLINK",
|
RTM_DELLINK: "RTM_DELLINK",
|
||||||
RTM_GETLINK: "RTM_GETLINK",
|
RTM_GETLINK: "RTM_GETLINK",
|
||||||
RTM_NEWADDR: "RTM_NEWADDR",
|
RTM_NEWADDR: "RTM_NEWADDR",
|
||||||
@@ -769,6 +804,7 @@ class RtNetlink(Netlink):
|
|||||||
RTM_DELROUTE: Rtmsg,
|
RTM_DELROUTE: Rtmsg,
|
||||||
RTM_GETROUTE: Rtmsg,
|
RTM_GETROUTE: Rtmsg,
|
||||||
RTM_NEWLINK: Ifinfomsg,
|
RTM_NEWLINK: Ifinfomsg,
|
||||||
|
RTM_SETLINK: Ifinfomsg,
|
||||||
RTM_DELLINK: Ifinfomsg,
|
RTM_DELLINK: Ifinfomsg,
|
||||||
RTM_GETLINK: Rtgenmsg,
|
RTM_GETLINK: Rtgenmsg,
|
||||||
RTM_NEWADDR: Ifaddrmsg,
|
RTM_NEWADDR: Ifaddrmsg,
|
||||||
@@ -814,53 +850,11 @@ class RtNetlink(Netlink):
|
|||||||
nlmsg = self.nlmsg(nlh)
|
nlmsg = self.nlmsg(nlh)
|
||||||
|
|
||||||
nlh.nlmsg_len += nlmsg.pack_extra(extra, nlh_p + nlh.nlmsg_len)
|
nlh.nlmsg_len += nlmsg.pack_extra(extra, nlh_p + nlh.nlmsg_len)
|
||||||
nlh.nlmsg_len += nlmsg.pack_rtas_new(rtas, nlh_p + nlh.nlmsg_len, nlmsg.rta_policy())
|
nlh.nlmsg_len += nlmsg.pack_rtas_new(rtas, nlh_p + nlh.nlmsg_len,
|
||||||
|
nlmsg.rta_policy())
|
||||||
#self.dump(nlh)
|
#self.dump(nlh)
|
||||||
self.sendall(string_at(nlh_p, nlh.nlmsg_len))
|
self.sendall(string_at(nlh_p, nlh.nlmsg_len))
|
||||||
self.seq += 1
|
self.seq += 1
|
||||||
|
|
||||||
token = (pid, seq)
|
token = (pid, seq)
|
||||||
return token
|
return token
|
||||||
|
|
||||||
def rta_linkinfo_policy(self):
|
|
||||||
fns = {
|
|
||||||
[IFLA_INFO_KIND] : self.rta_string,
|
|
||||||
[IFLA_INFO_DATA] : self.rta_linkinfo_data,
|
|
||||||
}
|
|
||||||
return fns
|
|
||||||
|
|
||||||
def rta_policy(self):
|
|
||||||
fns = {
|
|
||||||
IFLA_UNSPEC: self.rta_wtf,
|
|
||||||
IFLA_ADDRESS: self.rta_uint8_array,
|
|
||||||
IFLA_BROADCAST: self.rta_uint8_array,
|
|
||||||
IFLA_IFNAME: self.rta_string,
|
|
||||||
IFLA_MTU: self.rta_uint32,
|
|
||||||
IFLA_LINK: self.rta_uint32,
|
|
||||||
IFLA_QDISC: self.rta_string,
|
|
||||||
IFLA_STATS: self.rta_none,
|
|
||||||
IFLA_COST: self.rta_none,
|
|
||||||
IFLA_PRIORITY: self.rta_none,
|
|
||||||
IFLA_MASTER: self.rta_uint32,
|
|
||||||
IFLA_WIRELESS: self.rta_none,
|
|
||||||
IFLA_PROTINFO: self.rta_none,
|
|
||||||
IFLA_TXQLEN: self.rta_uint32,
|
|
||||||
IFLA_MAP: self.rta_none,
|
|
||||||
IFLA_WEIGHT: self.rta_uint32,
|
|
||||||
IFLA_OPERSTATE: self.rta_uint8,
|
|
||||||
IFLA_LINKMODE: self.rta_uint8,
|
|
||||||
IFLA_LINKINFO: self.rta_linkinfo,
|
|
||||||
IFLA_NET_NS_PID: self.rta_uint32,
|
|
||||||
IFLA_IFALIAS: self.rta_string,
|
|
||||||
IFLA_NUM_VF: self.rta_uint32,
|
|
||||||
IFLA_VFINFO_LIST: self.rta_none,
|
|
||||||
IFLA_STATS64: self.rta_none,
|
|
||||||
IFLA_VF_PORTS: self.rta_none,
|
|
||||||
IFLA_PORT_SELF: self.rta_none,
|
|
||||||
IFLA_AF_SPEC: self.rta_none,
|
|
||||||
IFLA_GROUP: self.rta_none,
|
|
||||||
IFLA_NET_NS_FD: self.rta_none,
|
|
||||||
IFLA_EXT_MASK: self.rta_none,
|
|
||||||
}
|
|
||||||
return fns;
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
from os import getpid
|
from os import getpid
|
||||||
from socket import AF_UNSPEC
|
from socket import AF_UNSPEC
|
||||||
|
from socket import AF_BRIDGE
|
||||||
from iff import IFF_UP
|
from iff import IFF_UP
|
||||||
from rtnetlink import *
|
from rtnetlink import *
|
||||||
import os
|
import os
|
||||||
@@ -104,4 +105,133 @@ class rtnetlinkApi(RtNetlink):
|
|||||||
token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||||
self.process_wait([token])
|
self.process_wait([token])
|
||||||
|
|
||||||
|
def link_set_hwaddress(self, ifname, hwaddress):
|
||||||
|
flags = 0
|
||||||
|
self.logger.info('rtnetlink: setting link hwaddress %s %s' %(ifname, hwaddress))
|
||||||
|
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||||
|
return
|
||||||
|
|
||||||
|
flags &= ~IFF_UP
|
||||||
|
ifm = Ifinfomsg(AF_UNSPEC, ifi_change=IFF_UP)
|
||||||
|
rtas = {IFLA_IFNAME: ifname,
|
||||||
|
IFLA_ADDRESS : str(bytearray([int(a,16) for a in hwaddress.split(':')]))}
|
||||||
|
|
||||||
|
self.logger.info(rtas)
|
||||||
|
|
||||||
|
token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||||
|
self.process_wait([token])
|
||||||
|
|
||||||
|
def addr_add(self, ifname, address, broadcast=None, peer=None, scope=None,
|
||||||
|
preferred_lifetime=None):
|
||||||
|
self.logger.info('rtnetlink: setting address')
|
||||||
|
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
ifindex = self.get_ifindex(link)
|
||||||
|
except Exception, e:
|
||||||
|
raise Exception('cannot determine ifindex for link %s (%s)'
|
||||||
|
%(link, str(e)))
|
||||||
|
ifa_scope = RT_SCOPE_
|
||||||
|
if scope:
|
||||||
|
if scope == "universe":
|
||||||
|
ifa_scope = RT_SCOPE_UNIVERSE
|
||||||
|
elif scope == "site":
|
||||||
|
ifa_scope = RT_SCOPE_SITE
|
||||||
|
elif scope == "link":
|
||||||
|
ifa_scope = RT_SCOPE_LINK
|
||||||
|
elif scope == "host":
|
||||||
|
ifa_scope = RT_SCOPE_HOST
|
||||||
|
elif scope == "nowhere":
|
||||||
|
ifa_scope = RT_SCOPE_NOWHERE
|
||||||
|
rtas = {IFLA_ADDRESS: ifname}
|
||||||
|
|
||||||
|
ifa = Ifaddrmsg(AF_UNSPEC, ifa_scope=ifa_scope, ifa_index=ifindex)
|
||||||
|
|
||||||
|
token = self.request(RTM_NEWADDR, NLM_F_REQUEST | NLM_F_ACK, ifa, rtas)
|
||||||
|
self.process_wait([token])
|
||||||
|
|
||||||
|
def link_set_many(self, ifname, ifattrs):
|
||||||
|
_ifattr_to_rta_map = {'dev' : IFLA_NAME,
|
||||||
|
'address' : IFLA_ADDRESS,
|
||||||
|
'broadcast' : IFLA_BROADCAST,
|
||||||
|
'mtu' : IFLA_MTU,
|
||||||
|
'master' : IFLA_MASTER}
|
||||||
|
flags = 0
|
||||||
|
ifi_change = IFF_UP
|
||||||
|
rtas = {}
|
||||||
|
self.logger.info('rtnetlink: setting link %s %s' %(ifname, state))
|
||||||
|
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||||
|
return
|
||||||
|
if not ifattrs:
|
||||||
|
return
|
||||||
|
state = ifattrs.get('state')
|
||||||
|
if state == 'up':
|
||||||
|
flags |= IFF_UP
|
||||||
|
elif state == 'down':
|
||||||
|
flags &= ~IFF_UP
|
||||||
|
else:
|
||||||
|
ifi_change = 0
|
||||||
|
|
||||||
|
if ifi_change:
|
||||||
|
ifm = Ifinfomsg(AF_UNSPEC, ifi_change=IFF_UP, ifi_flags=flags)
|
||||||
|
else:
|
||||||
|
ifm = Ifinfomsg(AF_UNSPEC)
|
||||||
|
|
||||||
|
for attr, attrval in ifattrs.items():
|
||||||
|
rta_attr = _ifattr_to_rta_map.get(attr)
|
||||||
|
if rta_attr:
|
||||||
|
if attr == 'hwaddress':
|
||||||
|
rtas[rta_attr] = str(bytearray([int(a,16) for a in attrval.split(':')]))
|
||||||
|
else:
|
||||||
|
rtas[rta_attr] = attrval
|
||||||
|
|
||||||
|
token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||||
|
self.process_wait([token])
|
||||||
|
|
||||||
|
def bridge_vlan(self, add=True, vid=None, dev=None, pvid=False,
|
||||||
|
untagged=False, master=True):
|
||||||
|
flags = 0
|
||||||
|
vflags = 0
|
||||||
|
if not vid or not dev:
|
||||||
|
return
|
||||||
|
self.logger.info('rtnetlink: bridge vlan add vid %s %s %s dev %s %s'
|
||||||
|
%(vid, 'untagged' if untagged else '',
|
||||||
|
'pvid' if pvid else '', dev,
|
||||||
|
'self' if self else ''))
|
||||||
|
if ifupdownmain.ifupdownFlags.DRYRUN:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
ifindex = self.get_ifindex(dev)
|
||||||
|
except Exception, e:
|
||||||
|
raise Exception('cannot determine ifindex for dev %s (%s)'
|
||||||
|
%(dev, str(e)))
|
||||||
|
if not master:
|
||||||
|
flags = BRIDGE_FLAGS_SELF
|
||||||
|
|
||||||
|
if pvid:
|
||||||
|
vflags = BRIDGE_VLAN_INFO_PVID
|
||||||
|
vflags |= BRIDGE_VLAN_INFO_UNTAGGED
|
||||||
|
elif untagged:
|
||||||
|
vflags |= BRIDGE_VLAN_INFO_UNTAGGED
|
||||||
|
|
||||||
|
ifm = Ifinfomsg(AF_BRIDGE, ifi_index=ifindex)
|
||||||
|
rtas = {IFLA_AF_SPEC: {
|
||||||
|
IFLA_BRIDGE_FLAGS: flags,
|
||||||
|
IFLA_BRIDGE_VLAN_INFO : BridgeVlanInfo(vflags, int(vid), int(vid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if add:
|
||||||
|
token = self.request(RTM_SETLINK,
|
||||||
|
NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||||
|
else:
|
||||||
|
token = self.request(RTM_DELLINK,
|
||||||
|
NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
|
||||||
|
self.process_wait([token])
|
||||||
|
|
||||||
|
def bridge_vlan_many(self, add=True, vids=[], dev=None, pvid=False,
|
||||||
|
untagged=False, master=True):
|
||||||
|
for v in vids:
|
||||||
|
self.bridge_vlan_add(add, v, dev, ispvid, isuntagged, master)
|
||||||
|
|
||||||
rtnl_api = rtnetlinkApi(os.getpid())
|
rtnl_api = rtnetlinkApi(os.getpid())
|
||||||
|
Reference in New Issue
Block a user