]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/rtnetlink_api.py
Merge 'vlan filtering bridge + vxlan + mlag + vrr' support from internal
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / rtnetlink_api.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 #
5 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
6 #
7 #
8
9 from os import getpid
10 from socket import AF_UNSPEC
11 from socket import AF_BRIDGE
12 from iff import IFF_UP
13 from rtnetlink import *
14 import os
15 import ifupdownmain
16
17 class rtnetlinkApi(RtNetlink):
18
19 bind_done = False
20
21 def __init__(self, pid):
22 RtNetlink.__init__(self, pid)
23 self.logger = logging.getLogger('ifupdown.' +
24 self.__class__.__name__)
25 self.bind(0, None)
26 self.bind_done = True
27 self.ifindexmap = {}
28
29 def do_bind(self):
30 if self.bind_done:
31 return True
32 self.bind(0, None)
33 self.bind_done = True
34
35 def get_ifindex(self, ifname):
36 ifindex = self.ifindexmap.get(ifname)
37 if not ifindex:
38 with open('/sys/class/net/%s/ifindex' %ifname, 'r') as f:
39 ifindex = int(f.read())
40 self.ifindexmap[ifname] = ifindex
41 return ifindex
42
43 def create_vlan(self, link, ifname, vlanid):
44 self.logger.info('rtnetlink: creating vlan interface %s' %ifname)
45 if ifupdownmain.ifupdownFlags.DRYRUN:
46 return
47 try:
48 ifindex = self.get_ifindex(link)
49 except Exception, e:
50 raise Exception('cannot determine ifindex for link %s (%s)'
51 %(link, str(e)))
52
53 ifm = Ifinfomsg(AF_UNSPEC)
54 rtas = {IFLA_IFNAME: ifname,
55 IFLA_LINK : ifindex,
56 IFLA_LINKINFO : {
57 IFLA_INFO_KIND : 'vlan',
58 IFLA_INFO_DATA : {
59 IFLA_VLAN_ID : vlanid,
60 }
61 }
62 }
63 token = self.request(RTM_NEWLINK,
64 NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
65 self.process_wait([token])
66
67 def create_macvlan(self, ifname, link, mode='private'):
68 self.logger.info('rtnetlink: creating macvlan interface %s' %ifname)
69 if ifupdownmain.ifupdownFlags.DRYRUN:
70 return
71 try:
72 ifindex = self.get_ifindex(link)
73 except Exception, e:
74 raise Exception('cannot determine ifindex for link %s (%s)'
75 %(link, str(e)))
76
77 ifm = Ifinfomsg(AF_UNSPEC)
78 rtas = {IFLA_IFNAME: ifname,
79 IFLA_LINK : ifindex,
80 IFLA_LINKINFO : {
81 IFLA_INFO_KIND : 'macvlan',
82 IFLA_INFO_DATA : {
83 IFLA_MACVLAN_MODE : MACVLAN_MODE_PRIVATE,
84 }
85 }
86 }
87 token = self.request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_REQUEST |
88 NLM_F_ACK, ifm, rtas)
89 self.process_wait([token])
90
91 def link_set(self, ifname, state):
92 flags = 0
93 self.logger.info('rtnetlink: setting link %s %s' %(ifname, state))
94 if ifupdownmain.ifupdownFlags.DRYRUN:
95 return
96
97 if state == "up":
98 flags |= IFF_UP
99 else:
100 flags &= ~IFF_UP
101
102 ifm = Ifinfomsg(AF_UNSPEC, ifi_change=IFF_UP, ifi_flags=flags)
103 rtas = {IFLA_IFNAME: ifname}
104
105 token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
106 self.process_wait([token])
107
108 def link_set_hwaddress(self, ifname, hwaddress):
109 flags = 0
110 self.logger.info('rtnetlink: setting link hwaddress %s %s' %(ifname, hwaddress))
111 if ifupdownmain.ifupdownFlags.DRYRUN:
112 return
113
114 flags &= ~IFF_UP
115 ifm = Ifinfomsg(AF_UNSPEC, ifi_change=IFF_UP)
116 rtas = {IFLA_IFNAME: ifname,
117 IFLA_ADDRESS : str(bytearray([int(a,16) for a in hwaddress.split(':')]))}
118
119 self.logger.info(rtas)
120
121 token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
122 self.process_wait([token])
123
124 def addr_add(self, ifname, address, broadcast=None, peer=None, scope=None,
125 preferred_lifetime=None):
126 self.logger.info('rtnetlink: setting address')
127 if ifupdownmain.ifupdownFlags.DRYRUN:
128 return
129
130 try:
131 ifindex = self.get_ifindex(link)
132 except Exception, e:
133 raise Exception('cannot determine ifindex for link %s (%s)'
134 %(link, str(e)))
135 ifa_scope = RT_SCOPE_
136 if scope:
137 if scope == "universe":
138 ifa_scope = RT_SCOPE_UNIVERSE
139 elif scope == "site":
140 ifa_scope = RT_SCOPE_SITE
141 elif scope == "link":
142 ifa_scope = RT_SCOPE_LINK
143 elif scope == "host":
144 ifa_scope = RT_SCOPE_HOST
145 elif scope == "nowhere":
146 ifa_scope = RT_SCOPE_NOWHERE
147 rtas = {IFLA_ADDRESS: ifname}
148
149 ifa = Ifaddrmsg(AF_UNSPEC, ifa_scope=ifa_scope, ifa_index=ifindex)
150
151 token = self.request(RTM_NEWADDR, NLM_F_REQUEST | NLM_F_ACK, ifa, rtas)
152 self.process_wait([token])
153
154 def link_set_many(self, ifname, ifattrs):
155 _ifattr_to_rta_map = {'dev' : IFLA_NAME,
156 'address' : IFLA_ADDRESS,
157 'broadcast' : IFLA_BROADCAST,
158 'mtu' : IFLA_MTU,
159 'master' : IFLA_MASTER}
160 flags = 0
161 ifi_change = IFF_UP
162 rtas = {}
163 self.logger.info('rtnetlink: setting link %s %s' %(ifname, state))
164 if ifupdownmain.ifupdownFlags.DRYRUN:
165 return
166 if not ifattrs:
167 return
168 state = ifattrs.get('state')
169 if state == 'up':
170 flags |= IFF_UP
171 elif state == 'down':
172 flags &= ~IFF_UP
173 else:
174 ifi_change = 0
175
176 if ifi_change:
177 ifm = Ifinfomsg(AF_UNSPEC, ifi_change=IFF_UP, ifi_flags=flags)
178 else:
179 ifm = Ifinfomsg(AF_UNSPEC)
180
181 for attr, attrval in ifattrs.items():
182 rta_attr = _ifattr_to_rta_map.get(attr)
183 if rta_attr:
184 if attr == 'hwaddress':
185 rtas[rta_attr] = str(bytearray([int(a,16) for a in attrval.split(':')]))
186 else:
187 rtas[rta_attr] = attrval
188
189 token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
190 self.process_wait([token])
191
192 def bridge_vlan(self, add=True, vid=None, dev=None, pvid=False,
193 untagged=False, master=True):
194 flags = 0
195 vflags = 0
196 if not vid or not dev:
197 return
198 self.logger.info('rtnetlink: bridge vlan add vid %s %s %s dev %s %s'
199 %(vid, 'untagged' if untagged else '',
200 'pvid' if pvid else '', dev,
201 'self' if self else ''))
202 if ifupdownmain.ifupdownFlags.DRYRUN:
203 return
204 try:
205 ifindex = self.get_ifindex(dev)
206 except Exception, e:
207 raise Exception('cannot determine ifindex for dev %s (%s)'
208 %(dev, str(e)))
209 if not master:
210 flags = BRIDGE_FLAGS_SELF
211
212 if pvid:
213 vflags = BRIDGE_VLAN_INFO_PVID
214 vflags |= BRIDGE_VLAN_INFO_UNTAGGED
215 elif untagged:
216 vflags |= BRIDGE_VLAN_INFO_UNTAGGED
217
218 ifm = Ifinfomsg(AF_BRIDGE, ifi_index=ifindex)
219 rtas = {IFLA_AF_SPEC: {
220 IFLA_BRIDGE_FLAGS: flags,
221 IFLA_BRIDGE_VLAN_INFO : BridgeVlanInfo(vflags, int(vid), int(vid))
222 }
223 }
224 if add:
225 token = self.request(RTM_SETLINK,
226 NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
227 else:
228 token = self.request(RTM_DELLINK,
229 NLM_F_REQUEST | NLM_F_ACK, ifm, rtas)
230 self.process_wait([token])
231
232 def bridge_vlan_many(self, add=True, vids=[], dev=None, pvid=False,
233 untagged=False, master=True):
234 for v in vids:
235 self.bridge_vlan_add(add, v, dev, ispvid, isuntagged, master)
236
237 rtnl_api = rtnetlinkApi(os.getpid())