backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / vrrp / monitor_linux.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import contextlib
18 import socket
19 import struct
20
21 from ryu.controller import handler
22 from ryu.ofproto import ether
23 from ryu.ofproto import inet
24 from ryu.lib import addrconv
25 from ryu.lib import hub
26 from ryu.lib.packet import arp
27 from ryu.lib.packet import vrrp
28 from ryu.services.protocols.vrrp import monitor
29 from ryu.services.protocols.vrrp import event as vrrp_event
30 from ryu.services.protocols.vrrp import utils
31
32
33 # Those are not defined in socket module
34 SS_MAXSIZE = 128
35 MCAST_JOIN_GROUP = 42
36 MCAST_LEAVE_GROUP = 45
37 PACKET_ADD_MEMBERSHIP = 1
38 PACKET_DROP_MEMBERSHIP = 2
39 PACKET_MR_MULTICAST = 0
40 SOL_PACKET = 263
41
42
43 def if_nametoindex(ifname):
44     filename = '/sys/class/net/' + ifname + '/ifindex'
45     with contextlib.closing(open(filename)) as f:
46         for line in f:
47             return int(line)
48
49
50 @monitor.VRRPInterfaceMonitor.register(vrrp_event.VRRPInterfaceNetworkDevice)
51 class VRRPInterfaceMonitorNetworkDevice(monitor.VRRPInterfaceMonitor):
52     """
53     This module uses raw socket so that privilege(CAP_NET_ADMIN capability)
54     is required.
55     """
56
57     def __init__(self, *args, **kwargs):
58         super(VRRPInterfaceMonitorNetworkDevice, self).__init__(*args,
59                                                                 **kwargs)
60         self.__is_active = True
61         config = self.config
62         if config.is_ipv6:
63             family = socket.AF_INET6
64             ether_type = ether.ETH_TYPE_IPV6
65             mac_address = vrrp.vrrp_ipv6_src_mac_address(config.vrid)
66         else:
67             family = socket.AF_INET
68             ether_type = ether.ETH_TYPE_IP
69             mac_address = vrrp.vrrp_ipv4_src_mac_address(config.vrid)
70         # socket module doesn't define IPPROTO_VRRP
71         self.ip_socket = socket.socket(family, socket.SOCK_RAW,
72                                        inet.IPPROTO_VRRP)
73
74         self.packet_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
75                                            socket.htons(ether_type))
76         self.packet_socket.bind((self.interface.device_name, ether_type,
77                                  socket.PACKET_MULTICAST,
78                                  arp.ARP_HW_TYPE_ETHERNET,
79                                  addrconv.mac.text_to_bin(mac_address)))
80
81         self.ifindex = if_nametoindex(self.interface.device_name)
82
83     def start(self):
84         # discard received packets before joining multicast membership
85         packet_socket = self.packet_socket
86         packet_socket.setblocking(0)
87         with hub.Timeout(0.1, False):
88             while True:
89                 try:
90                     packet_socket.recv(1500)
91                 except socket.error:
92                     break
93         packet_socket.setblocking(1)
94
95         self._join_multicast_membership(True)
96         self._join_vrrp_group(True)
97         super(VRRPInterfaceMonitorNetworkDevice, self).start()
98         self.threads.append(hub.spawn(self._recv_loop))
99
100     def stop(self):
101         self.__is_active = False
102         super(VRRPInterfaceMonitorNetworkDevice, self).stop()
103
104     # we assume that the structures in the following two functions for
105     # multicast are aligned in the same way on all the archtectures.
106     def _join_multicast_membership(self, join_leave):
107         config = self.config
108         if config.is_ipv6:
109             mac_address = vrrp.vrrp_ipv6_src_mac_address(config.vrid)
110         else:
111             mac_address = vrrp.vrrp_ipv4_src_mac_address(config.vrid)
112         if join_leave:
113             add_drop = PACKET_ADD_MEMBERSHIP
114         else:
115             add_drop = PACKET_DROP_MEMBERSHIP
116         # struct packet_mreq {
117         #     int mr_ifindex;
118         #     unsigned short mr_type;
119         #     unsigned short mr_alen;
120         #     unsigned char  mr_mr_address[8];
121         # };
122         packet_mreq = struct.pack('IHH8s', self.ifindex,
123                                   PACKET_MR_MULTICAST, 6,
124                                   addrconv.mac.text_to_bin(mac_address))
125         self.packet_socket.setsockopt(SOL_PACKET, add_drop, packet_mreq)
126
127     def _join_vrrp_group(self, join_leave):
128         if join_leave:
129             join_leave = MCAST_JOIN_GROUP
130         else:
131             join_leave = MCAST_LEAVE_GROUP
132
133         # struct group_req {
134         #     __u32 gr_interface;  /* interface index */
135         #     struct __kernel_sockaddr_storage gr_group; /* group address */
136         # };
137         group_req = struct.pack('I', self.ifindex)
138         # padding to gr_group. This is environment dependent
139         group_req += b'\x00' * (struct.calcsize('P') - struct.calcsize('I'))
140         if self.config.is_ipv6:
141             # struct sockaddr_in6 {
142             #     sa_family_t     sin6_family;   /* AF_INET6 */
143             #     in_port_t       sin6_port;     /* port number */
144             #     uint32_t        sin6_flowinfo; /* IPv6 flow information */
145             #     struct in6_addr sin6_addr;     /* IPv6 address */
146             #     uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
147             # };
148             # struct in6_addr {
149             #     unsigned char   s6_addr[16];   /* IPv6 address */
150             # };
151             family = socket.IPPROTO_IPV6
152             sockaddr = struct.pack('H', socket.AF_INET6)
153             sockaddr += struct.pack('!H', 0)
154             sockaddr += struct.pack('!I', 0)
155             sockaddr += addrconv.ipv6.text_to_bin(vrrp.VRRP_IPV6_DST_ADDRESS)
156             sockaddr += struct.pack('I', 0)
157         else:
158             # #define __SOCK_SIZE__   16 /* sizeof(struct sockaddr) */
159             # struct sockaddr_in {
160             #   __kernel_sa_family_t  sin_family;     /* Address family */
161             #   __be16                sin_port;       /* Port number */
162             #   struct in_addr        sin_addr;       /* Internet address */
163             #   /* Pad to size of `struct sockaddr'. */
164             #   unsigned char         __pad[__SOCK_SIZE__ - sizeof(short int) -
165             #           sizeof(unsigned short int) - sizeof(struct in_addr)];
166             # };
167             # struct in_addr {
168             #     __be32  s_addr;
169             # };
170             family = socket.IPPROTO_IP
171             sockaddr = struct.pack('H', socket.AF_INET)
172             sockaddr += struct.pack('!H', 0)
173             sockaddr += addrconv.ipv4.text_to_bin(vrrp.VRRP_IPV4_DST_ADDRESS)
174
175         sockaddr += b'\x00' * (SS_MAXSIZE - len(sockaddr))
176         group_req += sockaddr
177
178         self.ip_socket.setsockopt(family, join_leave, group_req)
179         return
180
181     def _recv_loop(self):
182         packet_socket = self.packet_socket
183         packet_socket.settimeout(1.3)       # to check activeness periodically
184         try:
185             while self.__is_active:
186                 try:
187                     buf = packet_socket.recv(128)
188                 except socket.timeout:
189                     self.logger.debug('timeout')
190                     continue
191                 except:
192                     self.logger.error('recv failed')
193                     continue
194                 if len(buf) == 0:
195                     self.__is_active = False
196                     break
197
198                 self.logger.debug('recv buf')
199                 self._send_vrrp_packet_received(buf)
200         finally:
201             self._join_vrrp_group(False)
202             self._join_multicast_membership(False)
203
204     @handler.set_ev_handler(vrrp_event.EventVRRPTransmitRequest)
205     def vrrp_transmit_request_handler(self, ev):
206         self.logger.debug('send')
207         try:
208             self.packet_socket.sendto(ev.data,
209                                       (self.interface.device_name, 0))
210         except:
211             self.logger.error('send failed')
212
213     def _initialize(self):
214         # nothing
215         pass
216
217     def _shutdown(self):
218         self.__is_active = False