Test Failed
Push — master ( c6929c...db4166 )
by Thomas
10:57
created

SrCapabilities.unpack()   A

Complexity

Conditions 5

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 18
nop 3
dl 0
loc 27
rs 9.0333
c 0
b 0
f 0
1
# encoding: utf-8
2
"""
3
srcap.py
4
5
Created by Evelio Vila
6
Copyright (c) 2014-2017 Exa Networks. All rights reserved.
7
"""
8
9
import json
10
from struct import unpack
11
12
from exabgp.bgp.message.update.attribute.bgpls.linkstate import LINKSTATE, LsGenericFlags
13
from exabgp.bgp.message.notification import Notify
14
15
#    draft-gredler-idr-bgp-ls-segment-routing-ext-03
16
#   0                   1                   2                   3
17
#    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
18
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
#   |               Type            |               Length          |
20
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
#   |      Flags    |   RESERVED    |
22
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
#
24
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
#   |                  Range Size                   |
26
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
#   //                SID/Label Sub-TLV (variable)                 //
28
#   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
#
30
#         SR Node Cap Flags
31
# 				+
32
#      One or more entries, each of which have the following format:
33
#
34
#         Range Size: 3 octet value indicating the number of labels in
35
#         the range.
36
#
37
#         SID/Label sub-TLV (as defined in Section 2.3.7.2).
38
39
40
@LINKSTATE.register()
41
class SrCapabilities(object):
42
    TLV = 1034
43
44
    def __init__(self, sr_flags, sids):
45
        self.sr_flags = sr_flags
46
        self.sids = sids
47
48
    def __repr__(self):
49
        return "sr_capability_flags: %s, sids: %s" % (self.sr_flags, self.sids)
50
51
    @classmethod
52
    def unpack(cls, data, length):
53
        # Extract node capability flags
54
        flags = LsGenericFlags.unpack(data[0:1], LsGenericFlags.ISIS_SR_CAP_FLAGS)
55
        # Move pointer past flags and reserved bytes
56
        data = data[2:]
57
        sids = []
58
        while data:
59
            # Range Size: 3 octet value indicating the number of labels in
60
            # the range.
61
            range_size = unpack('!L', bytes([0]) + data[:3])[0]
62
63
            # SID/Label: If length is set to 3, then the 20 rightmost bits
64
            # represent a label.  If length is set to 4, then the value
65
            # represents a 32 bit SID.
66
            t, l = unpack('!HH', data[3:7])
67
            if t != 1161:
68
                raise Notify(3, 5, "Invalid sub-TLV type: {}".format(t))
69
            v = data[7 : l + 7]
70
            if l == 3:
71
                sid = unpack('!L', bytes([0]) + data[:3])[0]
72
            elif l == 4:
73
                sid = unpack('!I', v)[0]
74
            sids.append((range_size, sid))
0 ignored issues
show
introduced by
The variable sid does not seem to be defined for all execution paths.
Loading history...
75
            data = data[l + 7 :]
76
77
        return cls(sr_flags=flags, sids=sids)
78
79
    def json(self, compact=None):
80
        return ', '.join(
81
            ['"sr-capability-flags": {}'.format(self.sr_flags.json()), '"sids": {}'.format(json.dumps(self.sids))]
82
        )
83