+ LOG.info("Ignoring RouteRefresh message. Afi/Safi is not supported: {}, {}.", rrAfi, rrSafi);
+ }
+ }
+
+ /**
+ * Check for presence of well known mandatory attribute LOCAL_PREF in Update message
+ *
+ * @param message Update message
+ * @throws BGPDocumentedException
+ */
+ private void checkMandatoryAttributesPresence(final Update message) throws BGPDocumentedException {
+ if (MessageUtil.isAnyNlriPresent(message)) {
+ final Attributes attrs = message.getAttributes();
+ if (this.peerRole == PeerRole.Ibgp && (attrs == null || attrs.getLocalPref() == null)) {
+ throw new BGPDocumentedException(BGPError.MANDATORY_ATTR_MISSING_MSG + "LOCAL_PREF",
+ BGPError.WELL_KNOWN_ATTR_MISSING,
+ new byte[] { LocalPreferenceAttributeParser.TYPE });
+ }
+ }
+ }
+
+ /**
+ * Process Update message received.
+ * Calls {@link #checkMandatoryAttributesPresence(Update)} to check for presence of mandatory attributes.
+ *
+ * @param message Update message
+ * @throws BGPDocumentedException
+ */
+ private void onUpdateMessage(final Update message) throws BGPDocumentedException {
+ checkMandatoryAttributesPresence(message);
+
+ // update AdjRibs
+ final Attributes attrs = message.getAttributes();
+ MpReachNlri mpReach = null;
+ final boolean isAnyNlriAnnounced = message.getNlri() != null;
+ if (isAnyNlriAnnounced) {
+ mpReach = prefixesToMpReach(message);
+ } else {
+ mpReach = MessageUtil.getMpReachNlri(attrs);
+ }
+ if (mpReach != null) {
+ this.ribWriter.updateRoutes(mpReach, nextHopToAttribute(attrs, mpReach));
+ }
+ MpUnreachNlri mpUnreach = null;
+ if (message.getWithdrawnRoutes() != null) {
+ mpUnreach = prefixesToMpUnreach(message, isAnyNlriAnnounced);
+ } else {
+ mpUnreach = MessageUtil.getMpUnreachNlri(attrs);
+ }
+ if (mpUnreach != null) {
+ this.ribWriter.removeRoutes(mpUnreach);
+ }
+ }
+
+ private static Attributes nextHopToAttribute(final Attributes attrs, final MpReachNlri mpReach) {
+ if (attrs.getCNextHop() == null && mpReach.getCNextHop() != null) {
+ final AttributesBuilder attributesBuilder = new AttributesBuilder(attrs);
+ attributesBuilder.setCNextHop(mpReach.getCNextHop());
+ return attributesBuilder.build();
+ }
+ return attrs;
+ }
+
+ /**
+ * Creates MPReach for the prefixes to be handled in the same way as linkstate routes
+ *
+ * @param message Update message containing prefixes in NLRI
+ * @return MpReachNlri with prefixes from the nlri field
+ */
+ private static MpReachNlri prefixesToMpReach(final Update message) {
+ final List<Ipv4Prefixes> prefixes = new ArrayList<>();
+ for (final Ipv4Prefix p : message.getNlri().getNlri()) {
+ prefixes.add(new Ipv4PrefixesBuilder().setPrefix(p).build());
+ }
+ final MpReachNlriBuilder b = new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(
+ UnicastSubsequentAddressFamily.class).setAdvertizedRoutes(
+ new AdvertizedRoutesBuilder().setDestinationType(
+ new DestinationIpv4CaseBuilder().setDestinationIpv4(
+ new DestinationIpv4Builder().setIpv4Prefixes(prefixes).build()).build()).build());
+ if (message.getAttributes() != null) {
+ b.setCNextHop(message.getAttributes().getCNextHop());