if (addpath_encoded) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
/* All EVPN NLRI types start with type and length. */
if (pnt + 2 > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE;
rtype = *pnt++;
psize = *pnt++;
/* When packet overflow occur return immediately. */
if (pnt + psize > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
switch (rtype) {
case BGP_EVPN_MAC_IP_ROUTE:
EC_BGP_EVPN_FAIL,
"%u:%s - Error in processing EVPN type-2 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-3 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-4 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE;
}
break;
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-5 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE;
}
break;
/* Packet length consistency check. */
if (pnt != lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
/*
if (afi == AFI_IP6) {
flog_err(EC_LIB_DEVELOPMENT, "BGP flowspec IPv6 not supported");
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED;
}
if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT) {
flog_err(EC_BGP_FLOWSPEC_PACKET,
"BGP flowspec nlri length maximum reached (%u)",
packet->length);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT;
}
for (; pnt < lim; pnt += psize) {
/* All FlowSpec NLRI begin with length. */
if (pnt + 1 > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
psize = *pnt++;
EC_BGP_FLOWSPEC_PACKET,
"Flowspec NLRI length inconsistent ( size %u seen)",
psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
if (bgp_fs_nlri_validate(pnt, psize) < 0) {
flog_err(
EC_BGP_FLOWSPEC_PACKET,
"Bad flowspec format or NLRI options not supported");
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT;
}
p.family = AF_FLOWSPEC;
p.prefixlen = 0;
flog_err(EC_BGP_FLOWSPEC_INSTALLATION,
"Flowspec NLRI failed to be %s.",
attr ? "added" : "withdrawn");
- return -1;
+ return BGP_NLRI_PARSE_ERROR;
}
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host, prefixlen, (uint)(lim - pnt));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Fill in the labels */
peer->host, prefixlen);
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
}
if ((afi == AFI_IP && p.prefixlen > 32)
|| (afi == AFI_IP6 && p.prefixlen > 128))
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
/* Fetch prefix from NLRI packet */
memcpy(&p.u.prefix, pnt + llen, psize - llen);
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
peer->host, lim - pnt);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
peer->host, prefixlen);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
}
/* sanity check against packet data */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
peer->host, prefixlen, (uint)(lim - pnt));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* sanity check against storage for the IP address portion */
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
sizeof(p.u));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Sanity check against max bitlen of the address family */
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
p.family, prefix_blen(&p));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Copy label to prefix. */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
peer->host, lim - pnt);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
return 0;
case SAFI_FLOWSPEC:
return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw);
}
- return -1;
+ return BGP_NLRI_PARSE_ERROR;
}
/*
nlri_ret = bgp_nlri_parse(peer, &attr, &nlris[i], 1);
break;
default:
- nlri_ret = -1;
+ nlri_ret = BGP_NLRI_PARSE_ERROR;
}
- if (nlri_ret < 0) {
+ if (nlri_ret < BGP_NLRI_PARSE_OK
+ && nlri_ret != BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW) {
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] Error parsing NLRI", peer->host);
if (peer->status == Established)
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (wrong prefix length %d for afi %u)",
peer->host, p.prefixlen, packet->afi);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
}
/* Packet size overflow check. */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d overflows packet)",
peer->host, p.prefixlen);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Defensive coding, double-check the psize fits in a struct
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
peer->host, p.prefixlen, sizeof(p.u));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Fetch prefix from NLRI packet. */
BGP_ROUTE_NORMAL, NULL, NULL, 0,
NULL);
- /* Address family configuration mismatch or maximum-prefix count
- overflow. */
+ /* Do not send BGP notification twice when maximum-prefix count
+ * overflow. */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+ return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
+
+ /* Address family configuration mismatch. */
if (ret < 0)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
}
/* Packet length consistency check. */
EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (prefix length mismatch with total length)",
peer->host);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
static struct bgp_static *bgp_static_new(void)
*/
#define BGP_MAX_LABELS 2
+/* Error codes for handling NLRI */
+#define BGP_NLRI_PARSE_OK 0
+#define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1
+#define BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW -2
+#define BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH -3
+#define BGP_NLRI_PARSE_ERROR_PACKET_LENGTH -4
+#define BGP_NLRI_PARSE_ERROR_LABEL_LENGTH -5
+#define BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE -6
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE -7
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE -8
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE -9
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE -10
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED -11
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT -12
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT -13
+#define BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY -14
+#define BGP_NLRI_PARSE_ERROR -32
+
/* Ancillary information to struct bgp_path_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
* and lazily allocated to save memory.
--- /dev/null
+router bgp 65000
+ neighbor 192.168.255.2 remote-as 65001
+ address-family ipv4 unicast
+ redistribute connected
--- /dev/null
+!
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
--- /dev/null
+router bgp 65001
+ neighbor 192.168.255.1 remote-as 65000
+ address-family ipv4
+ neighbor 192.168.255.1 maximum-prefix 1
--- /dev/null
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
--- /dev/null
+#!/usr/bin/env python
+
+#
+# bgp_local_as_private_remove.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+bgp_maximum_prefix_invalid_update.py:
+Test if unnecesarry UPDATE message like below:
+
+[Error] Error parsing NLRI
+%NOTIFICATION: sent to neighbor X.X.X.X 3/10 (UPDATE Message Error/Invalid Network Field) 0 bytes
+
+is not sent if maximum-prefix count is overflow.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 3):
+ tgen.add_router('r{}'.format(routern))
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.iteritems(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+ )
+
+ tgen.start_router()
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+def test_bgp_maximum_prefix_invalid():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_converge(router):
+ while True:
+ output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ if output['192.168.255.1']['connectionsEstablished'] > 3:
+ return True
+ time.sleep(1)
+
+ def _bgp_parsing_nlri(router):
+ cmd_max_exceeded = 'grep "%MAXPFXEXCEED: No. of IPv4 Unicast prefix received" bgpd.log'
+ cmdt_error_parsing_nlri = 'grep "Error parsing NLRI" bgpd.log'
+ output_max_exceeded = tgen.gears[router].run(cmd_max_exceeded)
+ output_error_parsing_nlri = tgen.gears[router].run(cmdt_error_parsing_nlri)
+
+ if len(output_max_exceeded) > 0:
+ if len(output_error_parsing_nlri) > 0:
+ return False
+ return True
+
+
+ if _bgp_converge('r2'):
+ assert _bgp_parsing_nlri('r2') == True
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))