BUG-45 : migrated Subsequent Address Family Identifier to generated source code.
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BGPSynchronization.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import java.util.Map;
11 import java.util.Map.Entry;
12 import java.util.Set;
13
14 import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
15 import org.opendaylight.protocol.bgp.concepts.BGPObject;
16 import org.opendaylight.protocol.bgp.concepts.BGPTableType;
17 import org.opendaylight.protocol.bgp.parser.BGPLink;
18 import org.opendaylight.protocol.bgp.parser.BGPNode;
19 import org.opendaylight.protocol.bgp.parser.BGPPrefix;
20 import org.opendaylight.protocol.bgp.parser.BGPRoute;
21 import org.opendaylight.protocol.bgp.parser.BGPSession;
22 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
23 import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
24 import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
25 import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
26 import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpSubsequentAddressFamily;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.base.Preconditions;
32 import com.google.common.collect.Maps;
33
34 /**
35  * BGP speaker (without Graceful restart capability) sends KeepAlive message after sending all initial Update messages
36  * with certain AFI/SAFI. For each AFI/SAFI, it sends one KA message. As it is undetermined which KA message belongs to
37  * which AFI/SAFI, an algorithm needed to be implemented.
38  */
39 public class BGPSynchronization {
40
41         private static final Logger logger = LoggerFactory.getLogger(BGPSynchronization.class);
42
43         private static class SyncVariables {
44
45                 private boolean upd = false;
46                 private boolean eor = false;
47
48                 public void setUpd(final boolean upd) {
49                         this.upd = upd;
50                 }
51
52                 public void setEorTrue() {
53                         this.eor = true;
54                 }
55
56                 public boolean getEor() {
57                         return this.eor;
58                 }
59
60                 public boolean getUpd() {
61                         return this.upd;
62                 }
63         }
64
65         private final Map<BGPTableType, SyncVariables> syncStorage = Maps.newHashMap();
66
67         private final BGPSessionListener listener;
68
69         private final BGPSession session;
70
71         public BGPSynchronization(final BGPSession session, final BGPSessionListener listener, final Set<BGPTableType> types) {
72                 this.listener = Preconditions.checkNotNull(listener);
73                 this.session = Preconditions.checkNotNull(session);
74
75                 for (final BGPTableType type : types) {
76                         this.syncStorage.put(type, new SyncVariables());
77                 }
78         }
79
80         /**
81          * For each received Update message, the upd sync variable needs to be updated to true, for particular AFI/SAFI
82          * combination. Currently we only assume Unicast SAFI. From the Update message we have to extract the AFI. Each
83          * Update message can contain BGP Object with one type of AFI. If the object is BGP Link, BGP Node or BGPPrefix<?>
84          * the AFI is Linkstate. In case of BGPRoute, the AFI depends on the IP Address of the prefix.
85          * 
86          * @param msg received Update message
87          */
88         public void updReceived(final BGPUpdateMessage msg) {
89                 BGPTableType type = null;
90                 if (!msg.getAddedObjects().isEmpty()) {
91                         final BGPObject obj = msg.getAddedObjects().iterator().next();
92                         if (obj instanceof BGPRoute<?>) {
93                                 if ((BGPRoute<?>) obj instanceof BGPIPv4RouteImpl) {
94                                         type = new BGPTableType(BGPAddressFamily.IPv4, BgpSubsequentAddressFamily.Unicast);
95                                 } else if ((BGPRoute<?>) obj instanceof BGPIPv6RouteImpl) {
96                                         type = new BGPTableType(BGPAddressFamily.IPv6, BgpSubsequentAddressFamily.Unicast);
97                                 }
98                         } else if (obj instanceof BGPLink || obj instanceof BGPNode || obj instanceof BGPPrefix<?>) {
99                                 type = new BGPTableType(BGPAddressFamily.LinkState, BgpSubsequentAddressFamily.Linkstate);
100                         }
101                 }
102                 final SyncVariables s = this.syncStorage.get(type);
103                 if (s == null) {
104                         logger.warn("BGPTableType was not present in open message : {}", type);
105                         return;
106                 }
107                 s.setUpd(true);
108         }
109
110         /**
111          * This method is called, when the second KA message is received. It checks each AFI/SAFI sync variables. If they
112          * are all false, which means, that there was at least one update message followed by one KA, the EOR is sent to
113          * session.
114          */
115         public void kaReceived() {
116                 for (final Entry<BGPTableType, SyncVariables> entry : this.syncStorage.entrySet()) {
117                         final SyncVariables s = entry.getValue();
118                         if (!s.getEor()) {
119                                 if (!s.getUpd()) {
120                                         s.setEorTrue();
121                                         final BGPUpdateSynchronized up = generateEOR(entry.getKey());
122                                         logger.debug("Sending synchronization message: {}", up);
123                                         this.listener.onMessage(this.session, up);
124                                 }
125                                 s.setUpd(false);
126                         }
127                 }
128         }
129
130         private BGPUpdateSynchronized generateEOR(final BGPTableType type) {
131                 return new BGPUpdateSynchronizedImpl(type);
132         }
133 }