blob: 06420c1bb1f81714f9fed8dd3ed84d1851f33fc3 [file] [log] [blame]
Jonathan Hartf5829202015-02-12 09:37:02 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.bgprouter;
17
Saurav Das3d038262015-04-23 12:36:58 -070018import static org.slf4j.LoggerFactory.getLogger;
19
Jonathan Hartf5829202015-02-12 09:37:02 -080020import org.onlab.packet.Ethernet;
21import org.onlab.packet.IPv4;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.TCP;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070024import org.onlab.packet.TpPort;
Jonathan Hartf5829202015-02-12 09:37:02 -080025import org.onosproject.core.ApplicationId;
26import org.onosproject.net.ConnectPoint;
Jonathan Hart936a7292015-03-06 18:02:57 -080027import org.onosproject.net.flow.DefaultTrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080028import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart936a7292015-03-06 18:02:57 -080029import org.onosproject.net.flow.TrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080030import org.onosproject.net.flow.TrafficTreatment;
Saurav Das3d038262015-04-23 12:36:58 -070031import org.onosproject.net.flowobjective.DefaultForwardingObjective;
32import org.onosproject.net.flowobjective.FlowObjectiveService;
33import org.onosproject.net.flowobjective.ForwardingObjective;
Jonathan Hartf5829202015-02-12 09:37:02 -080034import org.onosproject.net.packet.DefaultOutboundPacket;
35import org.onosproject.net.packet.OutboundPacket;
36import org.onosproject.net.packet.PacketContext;
Jonathan Hartf5829202015-02-12 09:37:02 -080037import org.onosproject.net.packet.PacketProcessor;
38import org.onosproject.net.packet.PacketService;
Jonathan Hart2da1e602015-02-18 19:09:24 -080039import org.onosproject.routing.config.BgpPeer;
40import org.onosproject.routing.config.BgpSpeaker;
41import org.onosproject.routing.config.InterfaceAddress;
42import org.onosproject.routing.config.RoutingConfigurationService;
Saurav Das3d038262015-04-23 12:36:58 -070043import org.slf4j.Logger;
Jonathan Hartf5829202015-02-12 09:37:02 -080044
45
46/**
47 * Manages connectivity between peers by tunnelling BGP traffic through
48 * OpenFlow packet-ins and packet-outs.
49 */
50public class TunnellingConnectivityManager {
51
52 private static final short BGP_PORT = 179;
Saurav Das3d038262015-04-23 12:36:58 -070053 private final Logger log = getLogger(getClass());
Jonathan Hartf5829202015-02-12 09:37:02 -080054 private final ApplicationId appId;
55
Jonathan Hart936a7292015-03-06 18:02:57 -080056 private final BgpSpeaker bgpSpeaker;
57
Jonathan Hartf5829202015-02-12 09:37:02 -080058 private final PacketService packetService;
59 private final RoutingConfigurationService configService;
Saurav Das3d038262015-04-23 12:36:58 -070060 private final FlowObjectiveService flowObjectiveService;
Jonathan Hartf5829202015-02-12 09:37:02 -080061
62 private final BgpProcessor processor = new BgpProcessor();
63
64 public TunnellingConnectivityManager(ApplicationId appId,
65 RoutingConfigurationService configService,
Jonathan Hart936a7292015-03-06 18:02:57 -080066 PacketService packetService,
Saurav Das3d038262015-04-23 12:36:58 -070067 FlowObjectiveService flowObjectiveService) {
Jonathan Hartf5829202015-02-12 09:37:02 -080068 this.appId = appId;
69 this.configService = configService;
70 this.packetService = packetService;
Saurav Das3d038262015-04-23 12:36:58 -070071 this.flowObjectiveService = flowObjectiveService;
Jonathan Hart936a7292015-03-06 18:02:57 -080072
73 BgpSpeaker bgpSpeaker = null;
74 for (BgpSpeaker speaker : configService.getBgpSpeakers().values()) {
75 bgpSpeaker = speaker;
76 break;
77 }
78
79 if (bgpSpeaker == null) {
80 throw new IllegalArgumentException("Must have at least one BGP speaker configured");
81 }
82
83 this.bgpSpeaker = bgpSpeaker;
84
sanghof22fb402015-04-27 23:55:10 -070085 }
86
87 public void start() {
Brian O'Connor3b783262015-07-29 17:49:24 -070088 packetService.addProcessor(processor, PacketProcessor.director(3));
sanghof22fb402015-04-27 23:55:10 -070089 }
90
91 public void stop() {
92 packetService.removeProcessor(processor);
93 // Should revoke packet requests in the future
94 }
95
96 /**
97 * Pushes the flow rules for forwarding BGP TCP packets to controller.
98 * It is called when switches are connected and available.
99 */
100 public void notifySwitchAvailable() {
101 // control plane OVS is available, push default flows
Jonathan Hart936a7292015-03-06 18:02:57 -0800102 TrafficSelector selectorDst = DefaultTrafficSelector.builder()
103 .matchEthType(Ethernet.TYPE_IPV4)
104 .matchIPProtocol(IPv4.PROTOCOL_TCP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700105 .matchTcpDst(TpPort.tpPort(BGP_PORT))
Jonathan Hart936a7292015-03-06 18:02:57 -0800106 .build();
107
108 TrafficSelector selectorSrc = DefaultTrafficSelector.builder()
109 .matchEthType(Ethernet.TYPE_IPV4)
110 .matchIPProtocol(IPv4.PROTOCOL_TCP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700111 .matchTcpSrc(TpPort.tpPort(BGP_PORT))
Jonathan Hart936a7292015-03-06 18:02:57 -0800112 .build();
113
114 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
115 .punt()
116 .build();
117
Saurav Das3d038262015-04-23 12:36:58 -0700118 ForwardingObjective puntSrc = DefaultForwardingObjective.builder()
119 .fromApp(appId)
120 .makePermanent()
121 .withSelector(selectorSrc)
122 .withTreatment(treatment)
123 .withFlag(ForwardingObjective.Flag.VERSATILE)
124 .add();
125 flowObjectiveService.forward(bgpSpeaker.connectPoint().deviceId(),
sanghof22fb402015-04-27 23:55:10 -0700126 puntSrc);
Saurav Das3d038262015-04-23 12:36:58 -0700127
128 ForwardingObjective puntDst = DefaultForwardingObjective.builder()
129 .fromApp(appId)
130 .makePermanent()
131 .withSelector(selectorDst)
132 .withTreatment(treatment)
133 .withFlag(ForwardingObjective.Flag.VERSATILE)
134 .add();
135 flowObjectiveService.forward(bgpSpeaker.connectPoint().deviceId(),
sanghof22fb402015-04-27 23:55:10 -0700136 puntDst);
Saurav Das3d038262015-04-23 12:36:58 -0700137 log.info("Sent punt forwarding objective to {}", bgpSpeaker.connectPoint().deviceId());
Jonathan Hartf5829202015-02-12 09:37:02 -0800138 }
139
140 /**
141 * Forwards a BGP packet to another connect point.
142 *
143 * @param context the packet context of the incoming packet
144 */
145 private void forward(PacketContext context) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800146 ConnectPoint outputPort = null;
Jonathan Hartf5829202015-02-12 09:37:02 -0800147
148 IPv4 ipv4 = (IPv4) context.inPacket().parsed().getPayload();
149 IpAddress dstAddress = IpAddress.valueOf(ipv4.getDestinationAddress());
150
Jonathan Hart936a7292015-03-06 18:02:57 -0800151 if (context.inPacket().receivedFrom().equals(bgpSpeaker.connectPoint())) {
152 BgpPeer peer = configService.getBgpPeers().get(dstAddress);
153 if (peer != null) {
154 outputPort = peer.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800155 }
Jonathan Hart936a7292015-03-06 18:02:57 -0800156 }
157 for (InterfaceAddress addr : bgpSpeaker.interfaceAddresses()) {
158 if (addr.ipAddress().equals(dstAddress) && !context.inPacket()
159 .receivedFrom().equals(bgpSpeaker.connectPoint())) {
160 outputPort = bgpSpeaker.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800161 }
162 }
163
164 if (outputPort != null) {
165 TrafficTreatment t = DefaultTrafficTreatment.builder()
166 .setOutput(outputPort.port()).build();
167 OutboundPacket o = new DefaultOutboundPacket(
168 outputPort.deviceId(), t, context.inPacket().unparsed());
169 packetService.emit(o);
170 }
171 }
172
173 /**
174 * Packet processor responsible receiving and filtering BGP packets.
175 */
176 private class BgpProcessor implements PacketProcessor {
177
178 @Override
179 public void process(PacketContext context) {
180 // Stop processing if the packet has been handled, since we
181 // can't do any more to it.
182 if (context.isHandled()) {
183 return;
184 }
185
186 Ethernet packet = context.inPacket().parsed();
187
188 if (packet == null) {
189 return;
190 }
191
192 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
193 IPv4 ipv4Packet = (IPv4) packet.getPayload();
194 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_TCP) {
195 TCP tcpPacket = (TCP) ipv4Packet.getPayload();
196
197 if (tcpPacket.getDestinationPort() == BGP_PORT ||
198 tcpPacket.getSourcePort() == BGP_PORT) {
199 forward(context);
200 }
201 }
202 }
203 }
204 }
205}