1 # Copyright (C) 2014 Xinguard, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 BFD Control packet parser/serializer
19 [RFC 5880] BFD Control packet format::
22 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
23 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 |Vers | Diag |Sta|P|F|C|A|D|M| Detect Mult | Length |
25 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 | Your Discriminator |
29 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 | Desired Min TX Interval |
31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 | Required Min RX Interval |
33 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 | Required Min Echo RX Interval |
35 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 An optional Authentication Section MAY be present in the following
40 1. Format of Simple Password Authentication Section::
43 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
44 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 | Auth Type | Auth Len | Auth Key ID | Password... |
46 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 2. Format of Keyed MD5 and Meticulous Keyed MD5 Authentication Section::
53 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
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | Auth Type | Auth Len | Auth Key ID | Reserved |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 | Auth Key/Digest... |
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 3. Format of Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section::
67 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
68 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 | Auth Type | Auth Len | Auth Key ID | Reserved |
70 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 from . import packet_base
85 from ryu.lib import addrconv
86 from ryu.lib import stringify
88 BFD_STATE_ADMIN_DOWN = 0
93 BFD_STATE_NAME = {0: "AdminDown",
98 BFD_FLAG_POLL = 1 << 5
99 BFD_FLAG_FINAL = 1 << 4
100 BFD_FLAG_CTRL_PLANE_INDEP = 1 << 3
101 BFD_FLAG_AUTH_PRESENT = 1 << 2
102 BFD_FLAG_DEMAND = 1 << 1
103 BFD_FLAG_MULTIPOINT = 1
106 BFD_DIAG_CTRL_DETECT_TIME_EXPIRED = 1
107 BFD_DIAG_ECHO_FUNC_FAILED = 2
108 BFD_DIAG_NEIG_SIG_SESS_DOWN = 3
109 BFD_DIAG_FWD_PLANE_RESET = 4
110 BFD_DIAG_PATH_DOWN = 5
111 BFD_DIAG_CONCAT_PATH_DOWN = 6
112 BFD_DIAG_ADMIN_DOWN = 7
113 BFD_DIAG_REV_CONCAT_PATH_DOWN = 8
115 BFD_DIAG_CODE_NAME = {0: "No Diagnostic",
116 1: "Control Detection Time Expired",
117 2: "Echo Function Failed",
118 3: "Neighbor Signaled Session Down",
119 4: "Forwarding Plane Reset",
121 6: "Concatenated Path Down",
122 7: "Administratively Down",
123 8: "Reverse Concatenated Path Down"}
125 BFD_AUTH_RESERVED = 0
126 BFD_AUTH_SIMPLE_PASS = 1
127 BFD_AUTH_KEYED_MD5 = 2
128 BFD_AUTH_METICULOUS_KEYED_MD5 = 3
129 BFD_AUTH_KEYED_SHA1 = 4
130 BFD_AUTH_METICULOUS_KEYED_SHA1 = 5
132 BFD_AUTH_TYPE_NAME = {0: "Reserved",
133 1: "Simple Password",
135 3: "Meticulous Keyed MD5",
137 5: "Meticulous Keyed SHA1"}
140 class bfd(packet_base.PacketBase):
141 """BFD (RFC 5880) Control packet encoder/decoder class.
143 The serialized packet would looks like the ones described
144 in the following sections.
146 * RFC 5880 Generic BFD Control Packet Format
148 An instance has the following attributes at least.
149 Most of them are same to the on-wire counterparts but in host byte order.
151 __init__ takes the corresponding args in this order.
153 .. tabularcolumns:: |l|L|
155 ============================== ============================================
156 Attribute Description
157 ============================== ============================================
158 ver The version number of the protocol.
159 This class implements protocol version 1.
160 diag A diagnostic code specifying the local
161 system's reason for the last change in
163 state The current BFD session state as seen by
164 the transmitting system.
165 flags Bitmap of the following flags.
169 | BFD_FLAG_CTRL_PLANE_INDEP
170 | BFD_FLAG_AUTH_PRESENT
172 | BFD_FLAG_MULTIPOINT
173 detect_mult Detection time multiplier.
174 my_discr My Discriminator.
175 your_discr Your Discriminator.
176 desired_min_tx_interval Desired Min TX Interval. (in microseconds)
177 required_min_rx_interval Required Min RX Interval. (in microseconds)
178 required_min_echo_rx_interval Required Min Echo RX Interval.
180 auth_cls (Optional) Authentication Section instance.
181 It's defined only when the Authentication
182 Present (A) bit is set in flags.
183 Assign an instance of the following classes:
184 ``SimplePassword``, ``KeyedMD5``,
185 ``MeticulousKeyedMD5``, ``KeyedSHA1``, and
186 ``MeticulousKeyedSHA1``.
187 length (Optional) Length of the BFD Control packet,
189 ============================== ============================================
192 _PACK_STR = '!BBBBIIIII'
193 _PACK_STR_LEN = struct.calcsize(_PACK_STR)
201 def __init__(self, ver=1, diag=0, state=0, flags=0, detect_mult=0,
202 my_discr=0, your_discr=0, desired_min_tx_interval=0,
203 required_min_rx_interval=0, required_min_echo_rx_interval=0,
204 auth_cls=None, length=None):
205 super(bfd, self).__init__()
211 self.detect_mult = detect_mult
212 self.my_discr = my_discr
213 self.your_discr = your_discr
214 self.desired_min_tx_interval = desired_min_tx_interval
215 self.required_min_rx_interval = required_min_rx_interval
216 self.required_min_echo_rx_interval = required_min_echo_rx_interval
217 self.auth_cls = auth_cls
218 if isinstance(length, int):
221 self.length = len(self)
224 if self.flags & BFD_FLAG_AUTH_PRESENT and self.auth_cls is not None:
225 return self._PACK_STR_LEN + len(self.auth_cls)
227 return self._PACK_STR_LEN
230 def parser(cls, buf):
231 (diag, flags, detect_mult, length, my_discr, your_discr,
232 desired_min_tx_interval, required_min_rx_interval,
233 required_min_echo_rx_interval) = \
234 struct.unpack_from(cls._PACK_STR, buf[:cls._PACK_STR_LEN])
241 if flags & BFD_FLAG_AUTH_PRESENT:
242 auth_type = six.indexbytes(buf, cls._PACK_STR_LEN)
243 auth_cls = cls._auth_parsers[auth_type].\
244 parser(buf[cls._PACK_STR_LEN:])[0]
248 msg = cls(ver, diag, state, flags, detect_mult,
249 my_discr, your_discr, desired_min_tx_interval,
250 required_min_rx_interval, required_min_echo_rx_interval,
253 return msg, None, None
255 def serialize(self, payload, prev):
256 if self.flags & BFD_FLAG_AUTH_PRESENT and self.auth_cls is not None:
257 return self.pack() + \
258 self.auth_cls.serialize(payload=None, prev=self)
264 Encode a BFD Control packet without authentication section.
266 diag = (self.ver << 5) + self.diag
267 flags = (self.state << 6) + self.flags
270 return struct.pack(self._PACK_STR, diag, flags, self.detect_mult,
271 length, self.my_discr, self.your_discr,
272 self.desired_min_tx_interval,
273 self.required_min_rx_interval,
274 self.required_min_echo_rx_interval)
276 def authenticate(self, *args, **kwargs):
277 """Authenticate this packet.
279 Returns a boolean indicates whether the packet can be authenticated
282 Returns ``False`` if the Authentication Present (A) is not set in the
285 Returns ``False`` if the Authentication Section for this packet is not
288 For the description of the arguemnts of this method, refer to the
289 authentication method of the Authentication Section classes.
291 if not self.flags & BFD_FLAG_AUTH_PRESENT or \
292 not issubclass(self.auth_cls.__class__, BFDAuth):
295 return self.auth_cls.authenticate(self, *args, **kwargs)
298 def set_auth_parser(cls, auth_cls):
299 cls._auth_parsers[auth_cls.auth_type] = auth_cls
302 def register_auth_type(cls, auth_type):
303 def _set_type(auth_cls):
304 auth_cls.set_type(auth_cls, auth_type)
305 cls.set_auth_parser(auth_cls)
310 class BFDAuth(stringify.StringifyMixin):
311 """Base class of BFD (RFC 5880) Authentication Section
313 An instance has the following attributes at least.
314 Most of them are same to the on-wire counterparts but in host byte order.
316 .. tabularcolumns:: |l|L|
318 =========== ============================================
319 Attribute Description
320 =========== ============================================
321 auth_type The authentication type in use.
322 auth_len The length, in bytes, of the authentication
323 section, including the ``auth_type`` and
325 =========== ============================================
327 _PACK_HDR_STR = '!BB'
328 _PACK_HDR_STR_LEN = struct.calcsize(_PACK_HDR_STR)
332 def __init__(self, auth_len=None):
333 super(BFDAuth, self).__init__()
334 if isinstance(auth_len, int):
335 self.auth_len = auth_len
337 self.auth_len = len(self)
340 def set_type(subcls, auth_type):
341 assert issubclass(subcls, BFDAuth)
342 subcls.auth_type = auth_type
345 def parser_hdr(cls, buf):
347 Parser for common part of authentication section.
349 return struct.unpack_from(cls._PACK_HDR_STR,
350 buf[:cls._PACK_HDR_STR_LEN])
352 def serialize_hdr(self):
354 Serialization function for common part of authentication section.
356 return struct.pack(self._PACK_HDR_STR, self.auth_type, self.auth_len)
359 @bfd.register_auth_type(BFD_AUTH_SIMPLE_PASS)
360 class SimplePassword(BFDAuth):
361 """ BFD (RFC 5880) Simple Password Authentication Section class
363 An instance has the following attributes.
364 Most of them are same to the on-wire counterparts but in host byte order.
366 .. tabularcolumns:: |l|L|
368 =========== ============================================
369 Attribute Description
370 =========== ============================================
371 auth_type (Fixed) The authentication type in use.
372 auth_key_id The authentication Key ID in use.
373 password The simple password in use on this session.
374 The password is a binary string, and MUST be
375 from 1 to 16 bytes in length.
376 auth_len The length, in bytes, of the authentication
377 section, including the ``auth_type`` and
379 =========== ============================================
382 _PACK_STR_LEN = struct.calcsize(_PACK_STR)
384 def __init__(self, auth_key_id, password, auth_len=None):
385 assert len(password) >= 1 and len(password) <= 16
386 self.auth_key_id = auth_key_id
387 self.password = password
388 super(SimplePassword, self).__init__(auth_len)
391 return self._PACK_HDR_STR_LEN + self._PACK_STR_LEN + len(self.password)
394 def parser(cls, buf):
395 (auth_type, auth_len) = cls.parser_hdr(buf)
396 assert auth_type == cls.auth_type
398 auth_key_id = six.indexbytes(buf, cls._PACK_HDR_STR_LEN)
400 password = buf[cls._PACK_HDR_STR_LEN + cls._PACK_STR_LEN:auth_len]
402 msg = cls(auth_key_id, password, auth_len)
404 return msg, None, None
406 def serialize(self, payload, prev):
407 """Encode a Simple Password Authentication Section.
409 ``payload`` is the rest of the packet which will immediately follow
412 ``prev`` is a ``bfd`` instance for the BFD Control header. It's not
413 necessary for encoding only the Simple Password section.
415 return self.serialize_hdr() + \
416 struct.pack(self._PACK_STR, self.auth_key_id) + self.password
418 def authenticate(self, prev=None, auth_keys=None):
419 """Authenticate the password for this packet.
421 This method can be invoked only when ``self.password`` is defined.
423 Returns a boolean indicates whether the password can be authenticated
426 ``prev`` is a ``bfd`` instance for the BFD Control header. It's not
427 necessary for authenticating the Simple Password.
429 ``auth_keys`` is a dictionary of authentication key chain which
430 key is an integer of *Auth Key ID* and value is a string of *Password*.
432 auth_keys = auth_keys if auth_keys else {}
433 assert isinstance(prev, bfd)
434 if self.auth_key_id in auth_keys and \
435 self.password == auth_keys[self.auth_key_id]:
441 @bfd.register_auth_type(BFD_AUTH_KEYED_MD5)
442 class KeyedMD5(BFDAuth):
443 """ BFD (RFC 5880) Keyed MD5 Authentication Section class
445 An instance has the following attributes.
446 Most of them are same to the on-wire counterparts but in host byte order.
448 .. tabularcolumns:: |l|L|
450 =========== =================================================
451 Attribute Description
452 =========== =================================================
453 auth_type (Fixed) The authentication type in use.
454 auth_key_id The authentication Key ID in use.
455 seq The sequence number for this packet.
456 This value is incremented occasionally.
457 auth_key The shared MD5 key for this packet.
458 digest (Optional) The 16-byte MD5 digest for the packet.
459 auth_len (Fixed) The length of the authentication section
461 =========== =================================================
463 _PACK_STR = '!BBL16s'
464 _PACK_STR_LEN = struct.calcsize(_PACK_STR)
466 def __init__(self, auth_key_id, seq, auth_key=None, digest=None,
468 self.auth_key_id = auth_key_id
470 self.auth_key = auth_key
472 super(KeyedMD5, self).__init__(auth_len)
475 # Defined in RFC5880 Section 4.3.
479 def parser(cls, buf):
480 (auth_type, auth_len) = cls.parser_hdr(buf)
481 assert auth_type == cls.auth_type
482 assert auth_len == 24
484 (auth_key_id, reserved, seq, digest) = \
485 struct.unpack_from(cls._PACK_STR, buf[cls._PACK_HDR_STR_LEN:])
488 msg = cls(auth_key_id=auth_key_id, seq=seq, auth_key=None,
491 return msg, None, None
493 def serialize(self, payload, prev):
494 """Encode a Keyed MD5 Authentication Section.
496 This method is used only when encoding an BFD Control packet.
498 ``payload`` is the rest of the packet which will immediately follow
501 ``prev`` is a ``bfd`` instance for the BFD Control header which this
502 authentication section belongs to. It's necessary to be assigned
503 because an MD5 digest must be calculated over the entire BFD Control
506 assert self.auth_key is not None and len(self.auth_key) <= 16
507 assert isinstance(prev, bfd)
509 bfd_bin = prev.pack()
510 auth_hdr_bin = self.serialize_hdr()
511 auth_data_bin = struct.pack(self._PACK_STR, self.auth_key_id, 0,
512 self.seq, self.auth_key +
513 (b'\x00' * (len(self.auth_key) - 16)))
516 h.update(bfd_bin + auth_hdr_bin + auth_data_bin)
517 self.digest = h.digest()
519 return auth_hdr_bin + struct.pack(self._PACK_STR, self.auth_key_id, 0,
520 self.seq, self.digest)
522 def authenticate(self, prev, auth_keys=None):
523 """Authenticate the MD5 digest for this packet.
525 This method can be invoked only when ``self.digest`` is defined.
527 Returns a boolean indicates whether the digest can be authenticated
528 by the correspondent Auth Key or not.
530 ``prev`` is a ``bfd`` instance for the BFD Control header which this
531 authentication section belongs to. It's necessary to be assigned
532 because an MD5 digest must be calculated over the entire BFD Control
535 ``auth_keys`` is a dictionary of authentication key chain which
536 key is an integer of *Auth Key ID* and value is a string of *Auth Key*.
538 auth_keys = auth_keys if auth_keys else {}
539 assert isinstance(prev, bfd)
541 if self.digest is None:
544 if self.auth_key_id not in auth_keys:
547 auth_key = auth_keys[self.auth_key_id]
549 bfd_bin = prev.pack()
550 auth_hdr_bin = self.serialize_hdr()
551 auth_data_bin = struct.pack(self._PACK_STR, self.auth_key_id, 0,
553 (b'\x00' * (len(auth_key) - 16)))
556 h.update(bfd_bin + auth_hdr_bin + auth_data_bin)
558 if self.digest == h.digest():
564 @bfd.register_auth_type(BFD_AUTH_METICULOUS_KEYED_MD5)
565 class MeticulousKeyedMD5(KeyedMD5):
566 """ BFD (RFC 5880) Meticulous Keyed MD5 Authentication Section class
568 All methods of this class are inherited from ``KeyedMD5``.
570 An instance has the following attributes.
571 Most of them are same to the on-wire counterparts but in host byte order.
573 .. tabularcolumns:: |l|L|
575 =========== =================================================
576 Attribute Description
577 =========== =================================================
578 auth_type (Fixed) The authentication type in use.
579 auth_key_id The authentication Key ID in use.
580 seq The sequence number for this packet.
581 This value is incremented for each
582 successive packet transmitted for a session.
583 auth_key The shared MD5 key for this packet.
584 digest (Optional) The 16-byte MD5 digest for the packet.
585 auth_len (Fixed) The length of the authentication section
587 =========== =================================================
592 @bfd.register_auth_type(BFD_AUTH_KEYED_SHA1)
593 class KeyedSHA1(BFDAuth):
594 """ BFD (RFC 5880) Keyed SHA1 Authentication Section class
596 An instance has the following attributes.
597 Most of them are same to the on-wire counterparts but in host byte order.
599 .. tabularcolumns:: |l|L|
601 =========== ================================================
602 Attribute Description
603 =========== ================================================
604 auth_type (Fixed) The authentication type in use.
605 auth_key_id The authentication Key ID in use.
606 seq The sequence number for this packet.
607 This value is incremented occasionally.
608 auth_key The shared SHA1 key for this packet.
609 auth_hash (Optional) The 20-byte SHA1 hash for the packet.
610 auth_len (Fixed) The length of the authentication section
612 =========== ================================================
614 _PACK_STR = '!BBL20s'
615 _PACK_STR_LEN = struct.calcsize(_PACK_STR)
617 def __init__(self, auth_key_id, seq, auth_key=None, auth_hash=None,
619 self.auth_key_id = auth_key_id
621 self.auth_key = auth_key
622 self.auth_hash = auth_hash
623 super(KeyedSHA1, self).__init__(auth_len)
626 # Defined in RFC5880 Section 4.4.
630 def parser(cls, buf):
631 (auth_type, auth_len) = cls.parser_hdr(buf)
632 assert auth_type == cls.auth_type
633 assert auth_len == 28
635 (auth_key_id, reserved, seq, auth_hash) = \
636 struct.unpack_from(cls._PACK_STR, buf[cls._PACK_HDR_STR_LEN:])
639 msg = cls(auth_key_id=auth_key_id, seq=seq, auth_key=None,
642 return msg, None, None
644 def serialize(self, payload, prev):
645 """Encode a Keyed SHA1 Authentication Section.
647 This method is used only when encoding an BFD Control packet.
649 ``payload`` is the rest of the packet which will immediately follow
652 ``prev`` is a ``bfd`` instance for the BFD Control header which this
653 authentication section belongs to. It's necessary to be assigned
654 because an SHA1 hash must be calculated over the entire BFD Control
657 assert self.auth_key is not None and len(self.auth_key) <= 20
658 assert isinstance(prev, bfd)
660 bfd_bin = prev.pack()
661 auth_hdr_bin = self.serialize_hdr()
662 auth_data_bin = struct.pack(self._PACK_STR, self.auth_key_id, 0,
663 self.seq, self.auth_key +
664 (b'\x00' * (len(self.auth_key) - 20)))
667 h.update(bfd_bin + auth_hdr_bin + auth_data_bin)
668 self.auth_hash = h.digest()
670 return auth_hdr_bin + struct.pack(self._PACK_STR, self.auth_key_id, 0,
671 self.seq, self.auth_hash)
673 def authenticate(self, prev, auth_keys=None):
674 """Authenticate the SHA1 hash for this packet.
676 This method can be invoked only when ``self.auth_hash`` is defined.
678 Returns a boolean indicates whether the hash can be authenticated
679 by the correspondent Auth Key or not.
681 ``prev`` is a ``bfd`` instance for the BFD Control header which this
682 authentication section belongs to. It's necessary to be assigned
683 because an SHA1 hash must be calculated over the entire BFD Control
686 ``auth_keys`` is a dictionary of authentication key chain which
687 key is an integer of *Auth Key ID* and value is a string of *Auth Key*.
689 auth_keys = auth_keys if auth_keys else {}
690 assert isinstance(prev, bfd)
692 if self.auth_hash is None:
695 if self.auth_key_id not in auth_keys:
698 auth_key = auth_keys[self.auth_key_id]
700 bfd_bin = prev.pack()
701 auth_hdr_bin = self.serialize_hdr()
702 auth_data_bin = struct.pack(self._PACK_STR, self.auth_key_id, 0,
704 (b'\x00' * (len(auth_key) - 20)))
707 h.update(bfd_bin + auth_hdr_bin + auth_data_bin)
709 if self.auth_hash == h.digest():
715 @bfd.register_auth_type(BFD_AUTH_METICULOUS_KEYED_SHA1)
716 class MeticulousKeyedSHA1(KeyedSHA1):
717 """ BFD (RFC 5880) Meticulous Keyed SHA1 Authentication Section class
719 All methods of this class are inherited from ``KeyedSHA1``.
721 An instance has the following attributes.
722 Most of them are same to the on-wire counterparts but in host byte order.
724 .. tabularcolumns:: |l|L|
726 =========== ================================================
727 Attribute Description
728 =========== ================================================
729 auth_type (Fixed) The authentication type in use.
730 auth_key_id The authentication Key ID in use.
731 seq The sequence number for this packet.
732 This value is incremented for each
733 successive packet transmitted for a session.
734 auth_key The shared SHA1 key for this packet.
735 auth_hash (Optional) The 20-byte SHA1 hash for the packet.
736 auth_len (Fixed) The length of the authentication section
738 =========== ================================================
743 bfd.set_classes(bfd._auth_parsers)