Skip to content

Commit

Permalink
Add successfully parsed attributes to the malformed return value (#171)
Browse files Browse the repository at this point in the history
* Add successfully parsed attributes to the malformed return value

* update update.py for pep8

---------

Co-authored-by: [email protected] <[email protected]>
  • Loading branch information
chenailin11 and [email protected] authored Oct 18, 2024
1 parent 475f34b commit 42b173f
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 83 deletions.
6 changes: 5 additions & 1 deletion yabgp/common/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class NotificationSent(Exception):

def __init__(self, sub_error, data=''):
try:
super(NotificationSent, self).__init__()
self.msg = self.message % {'sub_error': sub_error, 'data': data}
self.sub_error = sub_error
self.data = data
super(NotificationSent, self).__init__(self.msg)
except Exception:
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise
Expand All @@ -77,6 +77,10 @@ class UpdateMessageError(NotificationSent):
error = 3
message = "BGP Update Message Error, sub error:%(sub_error)s, data:%(data)s"

def __init__(self, sub_error, data='', sub_results=None):
super(UpdateMessageError, self).__init__(sub_error, data)
self.sub_results = sub_results


class HoldTimerExpiredError(NotificationSent):
error = 4
Expand Down
40 changes: 27 additions & 13 deletions yabgp/message/attribute/linkstate/linkstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import logging
import struct

import binascii

import traceback
from yabgp.common import constants as bgp_cons
from yabgp.common import exception as excep
from yabgp.message.attribute import Attribute, AttributeFlag, AttributeID

LOG = logging.getLogger()


class LinkState(Attribute):
"""BGP link-state attribute
Expand Down Expand Up @@ -61,17 +65,27 @@ def unpack(cls, data, bgpls_pro_id=None):
while data:
type_code, length = struct.unpack('!HH', data[:4])
value = data[4: 4 + length]
if type_code in [1099, 1100, 1158, 1162, 1038] and type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[type_code].unpack(value, bgpls_pro_id).dict())
elif type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[type_code].unpack(value).dict())
else:
tlvs.append(
{
'type': type_code,
'value': str(binascii.b2a_hex(value))
}
)
try:
if type_code in [1099, 1100, 1158, 1162, 1038] and type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[type_code].unpack(value, bgpls_pro_id).dict())
elif type_code in cls.registered_tlvs:
tlvs.append(cls.registered_tlvs[type_code].unpack(value).dict())
else:
tlvs.append(
{
'type': type_code,
'value': str(binascii.b2a_hex(value))
}
)
except Exception as e:
LOG.error(e)
error_str = traceback.format_exc()
LOG.debug(error_str)
raise excep.UpdateMessageError(
sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST,
data=value,
sub_results=cls(value=tlvs))

data = data[4 + length:]

return cls(value=tlvs)
144 changes: 75 additions & 69 deletions yabgp/message/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@

"""BGP Update Message"""

import struct
import traceback
import logging
import binascii

import logging
import netaddr

import struct
import traceback
from yabgp.common import exception as excep
from yabgp.common import constants as bgp_cons
from yabgp.message.attribute import AttributeFlag
Expand Down Expand Up @@ -191,6 +189,7 @@ def parse(cls, t, msg_hex, asn4=False, add_path_remote=False, add_path_local=Fal
LOG.error(e)
results['sub_error'] = e.sub_error
results['err_data'] = e.data
results['attr'] = e.sub_results
except Exception as e:
LOG.error(e)
error_str = traceback.format_exc()
Expand Down Expand Up @@ -291,9 +290,9 @@ def parse_attributes(data, asn4=False):
postfix = data
bgpls_pro_id = None
bgpls_attr = None
while len(postfix) > 0:

try:
try:
while len(postfix) > 0:
flags, type_code = struct.unpack('!BB', postfix[:2])

if flags & AttributeFlag.EXTENDED_LENGTH:
Expand All @@ -307,103 +306,110 @@ def parse_attributes(data, asn4=False):
attr_len = ord(postfix[2])
attr_value = postfix[3:3 + attr_len]
postfix = postfix[3 + attr_len:] # Next attribute
except Exception as e:
LOG.error(e)
error_str = traceback.format_exc()
LOG.debug(error_str)
raise excep.UpdateMessageError(
sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST,
data='')

if type_code == bgp_cons.BGPTYPE_ORIGIN:
if type_code == bgp_cons.BGPTYPE_ORIGIN:

decode_value = Origin.parse(value=attr_value)
decode_value = Origin.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_AS_PATH:
elif type_code == bgp_cons.BGPTYPE_AS_PATH:

decode_value = ASPath.parse(value=attr_value, asn4=asn4)
decode_value = ASPath.parse(value=attr_value, asn4=asn4)

elif type_code == bgp_cons.BGPTYPE_NEXT_HOP:
elif type_code == bgp_cons.BGPTYPE_NEXT_HOP:

decode_value = NextHop.parse(value=attr_value)
decode_value = NextHop.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC:
elif type_code == bgp_cons.BGPTYPE_MULTI_EXIT_DISC:

decode_value = MED.parse(value=attr_value)
decode_value = MED.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF:
elif type_code == bgp_cons.BGPTYPE_LOCAL_PREF:

decode_value = LocalPreference.parse(value=attr_value)
decode_value = LocalPreference.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE:
elif type_code == bgp_cons.BGPTYPE_ATOMIC_AGGREGATE:

decode_value = AtomicAggregate.parse(value=attr_value)
decode_value = AtomicAggregate.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_AGGREGATOR:
elif type_code == bgp_cons.BGPTYPE_AGGREGATOR:

decode_value = Aggregator.parse(value=attr_value, asn4=asn4)
decode_value = Aggregator.parse(value=attr_value, asn4=asn4)

elif type_code == bgp_cons.BGPTYPE_COMMUNITIES:
elif type_code == bgp_cons.BGPTYPE_COMMUNITIES:

decode_value = Community.parse(value=attr_value)
decode_value = Community.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID:
elif type_code == bgp_cons.BGPTYPE_ORIGINATOR_ID:

decode_value = OriginatorID.parse(value=attr_value)
decode_value = OriginatorID.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST:
elif type_code == bgp_cons.BGPTYPE_CLUSTER_LIST:

decode_value = ClusterList.parse(value=attr_value)
decode_value = ClusterList.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_NEW_AS_PATH:
elif type_code == bgp_cons.BGPTYPE_NEW_AS_PATH:

decode_value = ASPath.parse(value=attr_value, asn4=True)
decode_value = ASPath.parse(value=attr_value, asn4=True)

elif type_code == bgp_cons.BGPTYPE_NEW_AGGREGATOR:
elif type_code == bgp_cons.BGPTYPE_NEW_AGGREGATOR:

decode_value = Aggregator.parse(value=attr_value, asn4=True)
decode_value = Aggregator.parse(value=attr_value, asn4=True)

elif type_code == bgp_cons.BGPTYPE_LARGE_COMMUNITY:
elif type_code == bgp_cons.BGPTYPE_LARGE_COMMUNITY:

decode_value = LargeCommunity.parse(value=attr_value)
decode_value = LargeCommunity.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI:
decode_value = MpReachNLRI.parse(value=attr_value)
if decode_value['nlri'][0] and type(decode_value['nlri'][0]) is dict:
if decode_value['nlri'][0].get("protocol_id"):
bgpls_pro_id = decode_value['nlri'][0]["protocol_id"]
elif type_code == bgp_cons.BGPTYPE_MP_REACH_NLRI:
decode_value = MpReachNLRI.parse(value=attr_value)
if decode_value['nlri'][0] and type(decode_value['nlri'][0]) is dict:
if decode_value['nlri'][0].get("protocol_id"):
bgpls_pro_id = decode_value['nlri'][0]["protocol_id"]

elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI:
decode_value = MpUnReachNLRI.parse(value=attr_value)
elif type_code == bgp_cons.BGPTYPE_MP_UNREACH_NLRI:
decode_value = MpUnReachNLRI.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY:
decode_value = ExtCommunity.parse(value=attr_value)
elif type_code == bgp_cons.BGPTYPE_EXTENDED_COMMUNITY:
decode_value = ExtCommunity.parse(value=attr_value)

elif type_code == bgp_cons.BGPTYPE_PMSI_TUNNEL:
decode_value = PMSITunnel.parse(value=attr_value)
pmsi_hex = attr_value
elif type_code == bgp_cons.BGPTYPE_PMSI_TUNNEL:
decode_value = PMSITunnel.parse(value=attr_value)
pmsi_hex = attr_value

elif type_code == bgp_cons.BGPTYPE_LINK_STATE:
if bgpls_pro_id:
attributes.update(LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=attr_value).dict())
else:
bgpls_attr = attr_value
continue
elif type_code == bgp_cons.BGPTYPE_LINK_STATE:
if bgpls_pro_id:
attributes.update(LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=attr_value).dict())
else:
bgpls_attr = attr_value
continue

elif type_code == bgp_cons.BGPTYPE_BGP_PREFIX_SID:
decode_value = BGPPrefixSID.unpack(data=attr_value)
elif type_code == bgp_cons.BGPTYPE_BGP_PREFIX_SID:
decode_value = BGPPrefixSID.unpack(data=attr_value)

else:
decode_value = binascii.b2a_hex(attr_value).decode('utf-8')
attributes[type_code] = decode_value
else:
decode_value = binascii.b2a_hex(attr_value).decode('utf-8')
attributes[type_code] = decode_value

if bgpls_attr:
attributes.update(LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=bgpls_attr).dict())
if bgpls_attr:
attributes.update(LinkState.unpack(bgpls_pro_id=bgpls_pro_id, data=bgpls_attr).dict())

evpn_overlay = EVPN.signal_evpn_overlay(attributes)
if evpn_overlay['evpn'] and evpn_overlay['encap_ec']:
if bgp_cons.BGPTYPE_PMSI_TUNNEL in attributes:
attributes[bgp_cons.BGPTYPE_PMSI_TUNNEL] = PMSITunnel.parse(value=pmsi_hex, evpn_overlay=evpn_overlay)
evpn_overlay = EVPN.signal_evpn_overlay(attributes)
if evpn_overlay['evpn'] and evpn_overlay['encap_ec']:
if bgp_cons.BGPTYPE_PMSI_TUNNEL in attributes:
attributes[bgp_cons.BGPTYPE_PMSI_TUNNEL] = PMSITunnel.parse(value=pmsi_hex,
evpn_overlay=evpn_overlay)
except excep.UpdateMessageError as e:
raise excep.UpdateMessageError(
sub_error=e.sub_error,
data=e.data,
sub_results=attributes)
except Exception as e:
LOG.error(e)
error_str = traceback.format_exc()
LOG.debug(error_str)
raise excep.UpdateMessageError(
sub_error=bgp_cons.ERR_MSG_UPDATE_MALFORMED_ATTR_LIST,
data='',
sub_results=attributes)
return attributes

@staticmethod
Expand Down

0 comments on commit 42b173f

Please sign in to comment.