1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 VRRP packet parser/serializer
20 [RFC 3768] VRRP v2 packet format::
23 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25 |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs|
26 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 | Auth Type | Adver Int | Checksum |
28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 | Authentication Data (1) |
38 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 | Authentication Data (2) |
40 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 [RFC 5798] VRRP v3 packet format::
46 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
47 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 | IPv4 Fields or IPv6 Fields |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr|
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 |(rsvd) | Max Adver Int | Checksum |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 from ryu.lib.packet import ethernet
72 from ryu.lib.packet import ether_types as ether
73 from ryu.lib.packet import in_proto as inet
74 from ryu.lib.packet import ipv4
75 from ryu.lib.packet import ipv6
76 from ryu.lib.packet import packet
77 from ryu.lib.packet import packet_base
78 from ryu.lib.packet import packet_utils
79 from ryu.lib.packet import vlan
80 from ryu.lib import addrconv
84 # the LSB 8 bits is used for VRID
85 VRRP_IPV4_SRC_MAC_ADDRESS_FMT = '00:00:5E:00:01:%02x'
86 VRRP_IPV4_DST_MAC_ADDRESS = '01:00:5E:00:00:12'
87 VRRP_IPV4_DST_ADDRESS = '224.0.0.18'
91 def vrrp_ipv4_src_mac_address(vrid):
92 return VRRP_IPV4_SRC_MAC_ADDRESS_FMT % vrid
96 # the LSB 8 bits is used for VRID
97 VRRP_IPV6_SRC_MAC_ADDRESS_FMT = '00:00:5E:00:02:%02x'
98 VRRP_IPV6_DST_MAC_ADDRESS = '33:33:00:00:00:12'
99 VRRP_IPV6_DST_ADDRESS = 'ff02::12'
100 VRRP_IPV6_HOP_LIMIT = 255
103 def vrrp_ipv6_src_mac_address(vrid):
104 return VRRP_IPV6_SRC_MAC_ADDRESS_FMT % vrid
107 VRRP_VERSION_SHIFT = 4
111 def vrrp_from_version_type(version_type):
112 return (version_type >> VRRP_VERSION_SHIFT, version_type & VRRP_TYPE_MASK)
115 def vrrp_to_version_type(version, type_):
116 return (version << VRRP_VERSION_SHIFT) | type_
124 VRRP_TYPE_ADVERTISEMENT = 1
126 # VRRP VRID: 0 isn't used
131 VRRP_PRIORITY_MIN = 0
132 VRRP_PRIORITY_MAX = 255
133 VRRP_PRIORITY_RELEASE_RESPONSIBILITY = 0
134 VRRP_PRIORITY_BACKUP_MIN = 1
135 VRRP_PRIORITY_BACKUP_DEFAULT = 100
136 VRRP_PRIORITY_BACKUP_MAX = 254
137 VRRP_PRIORITY_ADDRESS_OWNER = 255
139 # VRRP auth type (VRRP v2 only)
140 VRRP_AUTH_NO_AUTH = 0
141 VRRP_AUTH_RESERVED1 = 1
142 VRRP_AUTH_RESERVED2 = 2
145 VRRP_AUTH_DATA = (VRRP_AUTH_DATA1, VRRP_AUTH_DATA2)
147 # VRRP Max advertisement interval
148 VRRP_MAX_ADVER_INT_DEFAULT_IN_SEC = 1 # 1 second
150 VRRP_V3_MAX_ADVER_INT_MASK = 0xfff # in centiseconds
151 VRRP_V3_MAX_ADVER_INT_DEFAULT = 100 # = 1 second
152 VRRP_V3_MAX_ADVER_INT_MIN = 1 # don't allow 0
153 VRRP_V3_MAX_ADVER_INT_MAX = 0xfff
155 VRRP_V2_MAX_ADVER_INT_MASK = 0xff # in seconds
156 VRRP_V2_MAX_ADVER_INT_DEFAULT = 1 # 1 second
157 VRRP_V2_MAX_ADVER_INT_MIN = 1 # don't allow 0
158 VRRP_V2_MAX_ADVER_INT_MAX = 0xff
161 def is_ipv6(ip_address):
162 assert type(ip_address) == str
164 addrconv.ipv4.text_to_bin(ip_address)
166 addrconv.ipv6.text_to_bin(ip_address) # sanity
171 def ip_text_to_bin(ip_text):
173 return addrconv.ipv6.text_to_bin(ip_text)
175 return addrconv.ipv4.text_to_bin(ip_text)
178 # This is used for master selection
179 def ip_address_lt(ip1, ip2):
180 return ip_text_to_bin(ip1) < ip_text_to_bin(ip2)
183 class vrrp(packet_base.PacketBase):
184 """The base class for VRRPv2 (RFC 3768) and VRRPv3 (RFC 5798)
185 header encoder/decoder classes.
187 Unlike other ryu.lib.packet.packet_base.PacketBase derived classes,
188 This class should not be directly instantiated by user.
190 An instance has the following attributes at least.
191 Most of them are same to the on-wire counterparts but in host byte order.
193 ============== ====================
194 Attribute Description
195 ============== ====================
198 vrid Virtual Rtr ID (VRID)
200 count_ip Count IPvX Addr. \
201 Calculated automatically when encoding.
202 max_adver_int Maximum Advertisement Interval (Max Adver Int)
204 Calculated automatically when encoding.
205 ip_addresses IPvX Address(es). A python list of IP addresses.
206 auth_type Authentication Type (only for VRRPv2)
207 auth_data Authentication Data (only for VRRPv2)
208 ============== ====================
211 _VERSION_PACK_STR = '!B'
212 _IPV4_ADDRESS_PACK_STR_RAW = '4s'
213 _IPV4_ADDRESS_PACK_STR = '!' + _IPV4_ADDRESS_PACK_STR_RAW
214 _IPV4_ADDRESS_LEN = struct.calcsize(_IPV4_ADDRESS_PACK_STR)
215 _IPV6_ADDRESS_LEN = 16
216 _IPV6_ADDRESS_PACK_STR_RAW = '%ds' % _IPV6_ADDRESS_LEN
217 _IPV6_ADDRESS_PACK_STR = '!' + _IPV6_ADDRESS_PACK_STR_RAW
218 _IPV6_ADDRESS_LEN = struct.calcsize(_IPV6_ADDRESS_PACK_STR)
221 _SEC_IN_MAX_ADVER_INT_UNIT = {}
224 def get_payload(packet_):
229 for protocol in packet_:
230 if isinstance(protocol, ipv4.ipv4) or isinstance(protocol,
234 if isinstance(packet_.protocols[idx + 1], vrrp):
235 may_vrrp = packet_.protocols[idx + 1]
240 if may_ip and may_vrrp:
241 return may_ip, may_vrrp
246 def register_vrrp_version(cls, version,
247 sec_in_max_adver_int_unit):
248 def _register_vrrp_version(cls_):
249 cls._VRRP_VERSIONS[version] = cls_
250 cls._SEC_IN_MAX_ADVER_INT_UNIT[version] = sec_in_max_adver_int_unit
252 return _register_vrrp_version
255 def sec_to_max_adver_int(version, seconds):
256 return int(seconds * vrrp._SEC_IN_MAX_ADVER_INT_UNIT[version])
259 def max_adver_int_to_sec(version, max_adver_int):
260 return float(max_adver_int) / vrrp._SEC_IN_MAX_ADVER_INT_UNIT[version]
262 def __init__(self, version, type_, vrid, priority, count_ip,
263 max_adver_int, checksum, ip_addresses,
265 # auth_type/auth_data is for vrrp v2
266 auth_type=None, auth_data=None):
267 super(vrrp, self).__init__()
268 self.version = version
271 self.priority = priority
272 self.count_ip = count_ip
273 self.max_adver_int = max_adver_int
275 self.checksum = checksum
276 self.ip_addresses = ip_addresses
277 assert len(list(ip_addresses)) == self.count_ip
279 self.auth_type = auth_type
280 self.auth_data = auth_data
282 self._is_ipv6 = is_ipv6(list(self.ip_addresses)[0])
283 self.identification = 0 # used for ipv4 identification
285 def checksum_ok(self, ipvx, vrrp_buf):
286 cls_ = self._VRRP_VERSIONS[self.version]
287 return cls_.checksum_ok(self, ipvx, vrrp_buf)
290 def max_adver_int_in_sec(self):
291 # return seconds of float as time.sleep() accepts such type.
292 return self.max_adver_int_to_sec(self.version, self.max_adver_int)
299 cls_ = self._VRRP_VERSIONS[self.version]
300 return cls_.__len__(self)
303 def create_version(version, type_, vrid, priority, max_adver_int,
304 ip_addresses, auth_type=None, auth_data=None):
305 cls_ = vrrp._VRRP_VERSIONS.get(version, None)
307 raise ValueError('unknown VRRP version %d' % version)
310 priority = VRRP_PRIORITY_BACKUP_DEFAULT
311 count_ip = len(ip_addresses)
312 if max_adver_int is None:
313 max_adver_int = cls_.sec_to_max_adver_int(
314 VRRP_MAX_ADVER_INT_DEFAULT_IN_SEC)
315 return cls_(version, type_, vrid, priority, count_ip, max_adver_int,
317 auth_type=auth_type, auth_data=auth_data)
319 def get_identification(self):
320 self.identification += 1
321 self.identification &= 0xffff
322 if self.identification == 0:
323 self.identification += 1
324 self.identification &= 0xffff
325 return self.identification
327 def create_packet(self, primary_ip_address, vlan_id=None):
328 """Prepare a VRRP packet.
330 Returns a newly created ryu.lib.packet.packet.Packet object
331 with appropriate protocol header objects added by add_protocol().
332 It's caller's responsibility to serialize().
333 The serialized packet would looks like the ones described in
334 the following sections.
336 * RFC 3768 5.1. VRRP Packet Format
337 * RFC 5798 5.1. VRRP Packet Format
339 ================== ====================
341 ================== ====================
342 primary_ip_address Source IP address
343 vlan_id VLAN ID. None for no VLAN.
344 ================== ====================
347 traffic_class = 0xc0 # set tos to internetwork control
349 payload_length = ipv6.ipv6._MIN_LEN + len(self) # XXX _MIN_LEN
350 e = ethernet.ethernet(VRRP_IPV6_DST_MAC_ADDRESS,
351 vrrp_ipv6_src_mac_address(self.vrid),
353 ip = ipv6.ipv6(6, traffic_class, flow_label, payload_length,
354 inet.IPPROTO_VRRP, VRRP_IPV6_HOP_LIMIT,
355 primary_ip_address, VRRP_IPV6_DST_ADDRESS)
357 header_length = ipv4.ipv4._MIN_LEN // 4 # XXX _MIN_LEN
359 tos = 0xc0 # set tos to internetwork control
360 identification = self.get_identification()
361 e = ethernet.ethernet(VRRP_IPV4_DST_MAC_ADDRESS,
362 vrrp_ipv4_src_mac_address(self.vrid),
364 ip = ipv4.ipv4(4, header_length, tos, total_length, identification,
365 0, 0, VRRP_IPV4_TTL, inet.IPPROTO_VRRP, 0,
366 primary_ip_address, VRRP_IPV4_DST_ADDRESS)
370 if vlan_id is not None:
371 vlan_ = vlan.vlan(0, 0, vlan_id, e.ethertype)
372 e.ethertype = ether.ETH_TYPE_8021Q
373 p.add_protocol(vlan_)
379 def parser(cls, buf):
380 (version_type,) = struct.unpack_from(cls._VERSION_PACK_STR, buf)
381 version, _type = vrrp_from_version_type(version_type)
382 cls_ = cls._VRRP_VERSIONS[version]
383 return cls_.parser(buf)
386 def serialize_static(vrrp_, prev):
387 # self can be a instance of vrrpv2 or vrrpv3.
388 assert isinstance(vrrp_, vrrp)
389 cls = vrrp._VRRP_VERSIONS[vrrp_.version]
390 return cls.serialize_static(vrrp_, prev)
392 def serialize(self, payload, prev):
393 return self.serialize_static(self, prev)
396 def is_valid_ttl(ipvx):
397 version = ipvx.version
399 return ipvx.ttl == VRRP_IPV4_TTL
401 return ipvx.hop_limit == VRRP_IPV6_HOP_LIMIT
403 raise ValueError('invalid ip version %d' % version)
406 cls = self._VRRP_VERSIONS.get(self.version, None)
409 return cls.is_valid(self)
412 # max_adver_int is in seconds
413 @vrrp.register_vrrp_version(VRRP_VERSION_V2, 1)
415 """VRRPv2 (RFC 3768) header encoder/decoder class.
417 Unlike other ryu.lib.packet.packet_base.PacketBase derived classes,
418 *create* method should be used to instantiate an object of this class.
421 _PACK_STR = '!BBBBBBH'
422 _MIN_LEN = struct.calcsize(_PACK_STR)
423 _CHECKSUM_PACK_STR = '!H'
425 _AUTH_DATA_PACK_STR = '!II'
426 _AUTH_DATA_LEN = struct.calcsize('!II')
429 return (self._MIN_LEN + self._IPV4_ADDRESS_LEN * self.count_ip +
432 def checksum_ok(self, ipvx, vrrp_buf):
433 return packet_utils.checksum(vrrp_buf) == 0
436 def create(type_, vrid, priority, max_adver_int, ip_addresses):
437 """Unlike other ryu.lib.packet.packet_base.PacketBase derived classes,
438 this method should be used to instantiate an object of this class.
440 This method's arguments are same as ryu.lib.packet.vrrp.vrrp object's
441 attributes of the same name. (except that *type_* corresponds to
445 return vrrp.create_version(VRRP_VERSION_V2, type_, vrid, priority,
448 auth_type=VRRP_AUTH_NO_AUTH,
449 auth_data=VRRP_AUTH_DATA)
452 def _ip_addresses_pack_str(count_ip):
453 return '!' + vrrpv2._IPV4_ADDRESS_PACK_STR_RAW * count_ip
456 def parser(cls, buf):
457 (version_type, vrid, priority, count_ip, auth_type, adver_int,
458 checksum) = struct.unpack_from(cls._PACK_STR, buf)
459 (version, type_) = vrrp_from_version_type(version_type)
461 offset = cls._MIN_LEN
462 ip_addresses_pack_str = cls._ip_addresses_pack_str(count_ip)
463 ip_addresses_bin = struct.unpack_from(ip_addresses_pack_str, buf,
465 ip_addresses = [addrconv.ipv4.bin_to_text(x) for x in ip_addresses_bin]
467 offset += struct.calcsize(ip_addresses_pack_str)
468 auth_data = struct.unpack_from(cls._AUTH_DATA_PACK_STR, buf, offset)
470 msg = cls(version, type_, vrid, priority, count_ip, adver_int,
471 checksum, ip_addresses, auth_type, auth_data)
472 return msg, None, buf[len(msg):]
475 def serialize_static(vrrp_, prev):
476 assert not vrrp_.is_ipv6 # vrrpv2 defines only IPv4
477 ip_addresses_pack_str = vrrpv2._ip_addresses_pack_str(vrrp_.count_ip)
478 ip_addresses_len = struct.calcsize(ip_addresses_pack_str)
479 vrrp_len = vrrpv2._MIN_LEN + ip_addresses_len + vrrpv2._AUTH_DATA_LEN
482 if vrrp_.checksum is None:
486 if vrrp_.auth_type is None:
487 vrrp_.auth_type = VRRP_AUTH_NO_AUTH
488 if vrrp_.auth_data is None:
489 vrrp_.auth_data = VRRP_AUTH_DATA
491 buf = bytearray(vrrp_len)
493 struct.pack_into(vrrpv2._PACK_STR, buf, offset,
494 vrrp_to_version_type(vrrp_.version, vrrp_.type),
495 vrrp_.vrid, vrrp_.priority,
496 vrrp_.count_ip, vrrp_.auth_type, vrrp_.max_adver_int,
498 offset += vrrpv2._MIN_LEN
499 struct.pack_into(ip_addresses_pack_str, buf, offset,
500 *[addrconv.ipv4.text_to_bin(x) for x in vrrp_.ip_addresses])
501 offset += ip_addresses_len
502 struct.pack_into(vrrpv2._AUTH_DATA_PACK_STR, buf, offset,
505 vrrp_.checksum = packet_utils.checksum(buf)
506 struct.pack_into(vrrpv2._CHECKSUM_PACK_STR, buf,
507 vrrpv2._CHECKSUM_OFFSET, vrrp_.checksum)
511 return (self.version == VRRP_VERSION_V2 and
512 self.type == VRRP_TYPE_ADVERTISEMENT and
513 VRRP_VRID_MIN <= self.vrid and self.vrid <= VRRP_VRID_MAX and
514 VRRP_PRIORITY_MIN <= self.priority and
515 self.priority <= VRRP_PRIORITY_MAX and
516 self.auth_type == VRRP_AUTH_NO_AUTH and
517 VRRP_V2_MAX_ADVER_INT_MIN <= self.max_adver_int and
518 self.max_adver_int <= VRRP_V2_MAX_ADVER_INT_MAX and
519 self.count_ip == len(self.ip_addresses))
522 # max_adver_int is in centi seconds: 1 second = 100 centiseconds
523 @vrrp.register_vrrp_version(VRRP_VERSION_V3, 100)
525 """VRRPv3 (RFC 5798) header encoder/decoder class.
527 Unlike other ryu.lib.packet.packet_base.PacketBase derived classes,
528 *create* method should be used to instantiate an object of this class.
531 _PACK_STR = '!BBBBHH'
532 _MIN_LEN = struct.calcsize(_PACK_STR)
533 _CHECKSUM_PACK_STR = '!H'
538 address_len = self._IPV6_ADDRESS_LEN
540 address_len = self._IPV4_ADDRESS_LEN
541 return self._MIN_LEN + address_len * self.count_ip
543 def checksum_ok(self, ipvx, vrrp_buf):
544 # There are two interpretation of IPv4 checksum
545 # include IPv4 pseudo header or not.
546 # http://www.ietf.org/mail-archive/web/vrrp/current/msg01473.html
547 # if not self.is_ipv6:
548 # return packet_utils.checksum(vrrp_buf) == 0
549 return packet_utils.checksum_ip(ipvx, len(self), vrrp_buf) == 0
552 def create(type_, vrid, priority, max_adver_int, ip_addresses):
553 """Unlike other ryu.lib.packet.packet_base.PacketBase derived classes,
554 this method should be used to instantiate an object of this class.
556 This method's arguments are same as ryu.lib.packet.vrrp.vrrp object's
557 attributes of the same name. (except that *type_* corresponds to
560 return vrrp.create_version(VRRP_VERSION_V3, type_, vrid, priority,
561 max_adver_int, ip_addresses)
564 def parser(cls, buf):
565 (version_type, vrid, priority, count_ip, max_adver_int,
566 checksum) = struct.unpack_from(cls._PACK_STR, buf)
567 (version, type_) = vrrp_from_version_type(version_type)
569 # _rsvd = (max_adver_int & ~VRRP_V3_MAX_ADVER_INT_MASK) >> 12
571 max_adver_int &= VRRP_V3_MAX_ADVER_INT_MASK
573 offset = cls._MIN_LEN
574 address_len = (len(buf) - offset) // count_ip
575 # Address version (IPv4 or IPv6) is determined by network layer
577 # Unfortunately it isn't available. Guess it by vrrp packet length.
578 if address_len == cls._IPV4_ADDRESS_LEN:
579 pack_str = '!' + cls._IPV4_ADDRESS_PACK_STR_RAW * count_ip
580 conv = addrconv.ipv4.bin_to_text
581 elif address_len == cls._IPV6_ADDRESS_LEN:
582 pack_str = '!' + cls._IPV6_ADDRESS_PACK_STR_RAW * count_ip
583 conv = addrconv.ipv6.bin_to_text
586 'unknown address version address_len %d count_ip %d' % (
587 address_len, count_ip))
589 ip_addresses_bin = struct.unpack_from(pack_str, buf, offset)
590 ip_addresses = [conv(x) for x in ip_addresses_bin]
591 msg = cls(version, type_, vrid, priority,
592 count_ip, max_adver_int, checksum, ip_addresses)
593 return msg, None, buf[len(msg):]
596 def serialize_static(vrrp_, prev):
597 if isinstance(prev, ipv4.ipv4):
598 assert type(vrrp_.ip_addresses[0]) == str
599 conv = addrconv.ipv4.text_to_bin
600 ip_address_pack_raw = vrrpv3._IPV4_ADDRESS_PACK_STR_RAW
601 elif isinstance(prev, ipv6.ipv6):
602 assert type(vrrp_.ip_addresses[0]) == str
603 conv = addrconv.ipv6.text_to_bin
604 ip_address_pack_raw = vrrpv3._IPV6_ADDRESS_PACK_STR_RAW
606 raise ValueError('Unkown network layer %s' % type(prev))
608 ip_addresses_pack_str = '!' + ip_address_pack_raw * vrrp_.count_ip
609 ip_addresses_len = struct.calcsize(ip_addresses_pack_str)
610 vrrp_len = vrrpv3._MIN_LEN + ip_addresses_len
613 if vrrp_.checksum is None:
617 buf = bytearray(vrrp_len)
618 assert vrrp_.max_adver_int <= VRRP_V3_MAX_ADVER_INT_MASK
619 struct.pack_into(vrrpv3._PACK_STR, buf, 0,
620 vrrp_to_version_type(vrrp_.version, vrrp_.type),
621 vrrp_.vrid, vrrp_.priority,
622 vrrp_.count_ip, vrrp_.max_adver_int, vrrp_.checksum)
623 struct.pack_into(ip_addresses_pack_str, buf, vrrpv3._MIN_LEN,
624 *[conv(x) for x in vrrp_.ip_addresses])
627 vrrp_.checksum = packet_utils.checksum_ip(prev, len(buf), buf)
628 struct.pack_into(vrrpv3._CHECKSUM_PACK_STR, buf,
629 vrrpv3._CHECKSUM_OFFSET, vrrp_.checksum)
633 return (self.version == VRRP_VERSION_V3 and
634 self.type == VRRP_TYPE_ADVERTISEMENT and
635 VRRP_VRID_MIN <= self.vrid and self.vrid <= VRRP_VRID_MAX and
636 VRRP_PRIORITY_MIN <= self.priority and
637 self.priority <= VRRP_PRIORITY_MAX and
638 VRRP_V3_MAX_ADVER_INT_MIN <= self.max_adver_int and
639 self.max_adver_int <= VRRP_V3_MAX_ADVER_INT_MAX and
640 self.count_ip == len(self.ip_addresses))
643 ipv4.ipv4.register_packet_type(vrrp, inet.IPPROTO_VRRP)
644 ipv6.ipv6.register_packet_type(vrrp, inet.IPPROTO_VRRP)