Completed
Push — master ( 10850a...cc7769 )
by Thomas
12:56 queued 11s
created

exabgp.bgp.message.update.nlri.bgpls.prefixv6   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 132
Duplicated Lines 73.48 %

Importance

Changes 0
Metric Value
eloc 89
dl 97
loc 132
rs 10
c 0
b 0
f 0
wmc 17

8 Methods

Rating   Name   Duplication   Size   Complexity  
A PREFIXv6.__ne__() 2 2 1
B PREFIXv6.unpack_nlri() 38 38 8
A PREFIXv6.pack() 2 2 1
A PREFIXv6.json() 17 17 3
A PREFIXv6.__str__() 2 2 1
A PREFIXv6.__eq__() 7 7 1
A PREFIXv6.__init__() 13 13 1
A PREFIXv6.__hash__() 2 2 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
"""
2
prefixv6.py
3
Created by Tinus Flagstad & Håvard Eidnes on 2018-07-02.
4
Copyright (c) 2009-2018 Exa Networks. All rights reserved.
5
License: 3-clause BSD. (See the COPYRIGHT file)
6
"""
7
8
from struct import pack
9
from struct import unpack
10
import json
11
12
from exabgp.bgp.message.update.nlri.bgpls.nlri import BGPLS
13
from exabgp.bgp.message.update.nlri.bgpls.nlri import PROTO_CODES
14
from exabgp.bgp.message.update.nlri.bgpls.tlvs.node import NodeDescriptor
15
from exabgp.bgp.message.update.nlri.bgpls.tlvs.ospfroute import OspfRoute
16
from exabgp.bgp.message.update.nlri.bgpls.tlvs.ipreach import IpReach
17
18
#   The IPv4 and IPv6 Prefix NLRIs (NLRI Type = 3 and Type = 4) use the
19
#   same format, as shown in the following figure.
20
#
21
#      0                   1                   2                   3
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
#     |  Protocol-ID  |
25
#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
#     |                           Identifier                          |
27
#     |                            (64 bits)                          |
28
#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
#     //              Local Node Descriptors (variable)              //
30
#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
#     //                Prefix Descriptors (variable)                //
32
#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
34
35 View Code Duplication
@BGPLS.register
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
36
class PREFIXv6(BGPLS):
37
	CODE = 4
38
	NAME = "bgpls-prefix-v6"
39
	SHORT_NAME = "PREFIX_V6"
40
41
	def __init__ (
42
			self,domain,proto_id,local_node,
43
			packed=None,ospf_type=None,prefix=None,
44
			nexthop=None,route_d=None,action=None, addpath=None):
45
		BGPLS.__init__(self,action,addpath)
46
		self.domain = domain
47
		self.ospf_type = ospf_type
48
		self.proto_id = proto_id
49
		self.local_node = local_node
50
		self.prefix = prefix
51
		self.nexthop = nexthop
52
		self._pack = packed
53
		self.route_d = route_d
54
55
	@classmethod
56
	def unpack_nlri (cls, data, rd):
57
		ospf_type = None
58
		proto_id = unpack('!B',data[0:1])[0]
59
		if proto_id not in PROTO_CODES.keys():
60
			raise Exception('Protocol-ID {} is not valid'.format(proto_id))
61
		domain = unpack('!Q',data[1:9])[0]
62
		tlvs = data[9:]
63
64
		while tlvs:
65
			tlv_type, tlv_length = unpack('!HH', tlvs[:4])
66
			if tlv_type == 256:
67
				values = tlvs[4: 4 + tlv_length]
68
				local_node = []
69
				while values:
70
					# Unpack Local Node Descriptor Sub-TLVs
71
					# We pass proto_id as TLV interpretation
72
					# follows IGP type
73
					node, left = NodeDescriptor.unpack(values, proto_id)
74
					local_node.append(node)
75
					if left == values:
76
						raise RuntimeError("sub-calls should consume data")
77
					values = left
78
				tlvs = tlvs[4 + tlv_length:]
79
				continue
80
			if tlv_type == 264:
81
				values = tlvs[4: 4 + tlv_length]
82
				ospf_type = OspfRoute.unpack(values)
83
				tlvs = tlvs[4 + tlv_length:]
84
			if tlv_type == 265:
85
				values = tlvs[4: 4 + tlv_length]
86
				prefix = IpReach.unpack(values, 4)
87
				tlvs = tlvs[4 + tlv_length:]
88
89
		return cls(
90
			domain=domain,proto_id=proto_id,packed=data,
91
			local_node=local_node,ospf_type=ospf_type,
0 ignored issues
show
introduced by
The variable local_node does not seem to be defined in case the while loop on line 64 is not entered. Are you sure this can never be the case?
Loading history...
92
			prefix=prefix,route_d=rd
0 ignored issues
show
introduced by
The variable prefix does not seem to be defined for all execution paths.
Loading history...
93
		)
94
95
	def __eq__ (self, other):
96
		return \
97
			isinstance(other, PREFIXv6) and \
98
			self.CODE == other.CODE and \
99
			self.domain == other.domain and \
100
			self.proto_id == other.proto_id and \
101
			self.route_d == other.route_d
102
103
	def __ne__ (self, other):
104
		return not self.__eq__(other)
105
106
	def __str__ (self):
107
		return self.json()
108
109
	def __hash__ (self):
110
		return hash((self))
111
112
	def json (self, compact=None):
113
		nodes = ', '.join(d.json() for d in self.local_node)
114
		content = ', '.join([
115
			'"ls-nlri-type": "%s"' % self.NAME,
116
			'"l3-routing-topology": %d' % int(self.domain),
117
			'"protocol-id": %d' % int(self.proto_id),
118
			'"node-descriptors": { %s }' % nodes,
119
			self.prefix.json(),
120
			'"nexthop": "%s"' % self.nexthop,
121
		])
122
		if self.ospf_type:
123
			content += ', %s' % self.ospf_type.json()
124
125
		if self.route_d:
126
			content += ', %s' % self.route_d.json()
127
128
		return '{ %s }' % (content)
129
130
	def pack (self,negotiated=None):
131
		return self._pack