blob: 39b248cb3087537a8d651a1b9675f562c3a8cb55 [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;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.net.ConnectPoint;
Jonathan Hart936a7292015-03-06 18:02:57 -080026import org.onosproject.net.flow.DefaultTrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080027import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart936a7292015-03-06 18:02:57 -080028import org.onosproject.net.flow.TrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080029import org.onosproject.net.flow.TrafficTreatment;
Saurav Das3d038262015-04-23 12:36:58 -070030import org.onosproject.net.flowobjective.DefaultForwardingObjective;
31import org.onosproject.net.flowobjective.FlowObjectiveService;
32import org.onosproject.net.flowobjective.ForwardingObjective;
Jonathan Hartf5829202015-02-12 09:37:02 -080033import org.onosproject.net.packet.DefaultOutboundPacket;
34import org.onosproject.net.packet.OutboundPacket;
35import org.onosproject.net.packet.PacketContext;
Jonathan Hartf5829202015-02-12 09:37:02 -080036import org.onosproject.net.packet.PacketProcessor;
37import org.onosproject.net.packet.PacketService;
Jonathan Hart2da1e602015-02-18 19:09:24 -080038import org.onosproject.routing.config.BgpPeer;
39import org.onosproject.routing.config.BgpSpeaker;
40import org.onosproject.routing.config.InterfaceAddress;
41import org.onosproject.routing.config.RoutingConfigurationService;
Saurav Das3d038262015-04-23 12:36:58 -070042import org.slf4j.Logger;
Jonathan Hartf5829202015-02-12 09:37:02 -080043
44
45/**
46 * Manages connectivity between peers by tunnelling BGP traffic through
47 * OpenFlow packet-ins and packet-outs.
48 */
49public class TunnellingConnectivityManager {
50
51 private static final short BGP_PORT = 179;
Saurav Das3d038262015-04-23 12:36:58 -070052 private final Logger log = getLogger(getClass());
Jonathan Hartf5829202015-02-12 09:37:02 -080053 private final ApplicationId appId;
54
Jonathan Hart936a7292015-03-06 18:02:57 -080055 private final BgpSpeaker bgpSpeaker;
56
Jonathan Hartf5829202015-02-12 09:37:02 -080057 private final PacketService packetService;
58 private final RoutingConfigurationService configService;
Saurav Das3d038262015-04-23 12:36:58 -070059 private final FlowObjectiveService flowObjectiveService;
Jonathan Hartf5829202015-02-12 09:37:02 -080060
61 private final BgpProcessor processor = new BgpProcessor();
62
63 public TunnellingConnectivityManager(ApplicationId appId,
64 RoutingConfigurationService configService,
Jonathan Hart936a7292015-03-06 18:02:57 -080065 PacketService packetService,
Saurav Das3d038262015-04-23 12:36:58 -070066 FlowObjectiveService flowObjectiveService) {
Jonathan Hartf5829202015-02-12 09:37:02 -080067 this.appId = appId;
68 this.configService = configService;
69 this.packetService = packetService;
Saurav Das3d038262015-04-23 12:36:58 -070070 this.flowObjectiveService = flowObjectiveService;
Jonathan Hart936a7292015-03-06 18:02:57 -080071
72 BgpSpeaker bgpSpeaker = null;
73 for (BgpSpeaker speaker : configService.getBgpSpeakers().values()) {
74 bgpSpeaker = speaker;
75 break;
76 }
77
78 if (bgpSpeaker == null) {
79 throw new IllegalArgumentException("Must have at least one BGP speaker configured");
80 }
81
82 this.bgpSpeaker = bgpSpeaker;
83
sanghof22fb402015-04-27 23:55:10 -070084 }
85
86 public void start() {
87 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 3);
88 }
89
90 public void stop() {
91 packetService.removeProcessor(processor);
92 // Should revoke packet requests in the future
93 }
94
95 /**
96 * Pushes the flow rules for forwarding BGP TCP packets to controller.
97 * It is called when switches are connected and available.
98 */
99 public void notifySwitchAvailable() {
100 // control plane OVS is available, push default flows
Jonathan Hart936a7292015-03-06 18:02:57 -0800101 TrafficSelector selectorDst = DefaultTrafficSelector.builder()
102 .matchEthType(Ethernet.TYPE_IPV4)
103 .matchIPProtocol(IPv4.PROTOCOL_TCP)
104 .matchTcpDst(BGP_PORT)
105 .build();
106
107 TrafficSelector selectorSrc = DefaultTrafficSelector.builder()
108 .matchEthType(Ethernet.TYPE_IPV4)
109 .matchIPProtocol(IPv4.PROTOCOL_TCP)
110 .matchTcpSrc(BGP_PORT)
111 .build();
112
113 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
114 .punt()
115 .build();
116
Saurav Das3d038262015-04-23 12:36:58 -0700117 ForwardingObjective puntSrc = DefaultForwardingObjective.builder()
118 .fromApp(appId)
119 .makePermanent()
120 .withSelector(selectorSrc)
121 .withTreatment(treatment)
122 .withFlag(ForwardingObjective.Flag.VERSATILE)
123 .add();
124 flowObjectiveService.forward(bgpSpeaker.connectPoint().deviceId(),
sanghof22fb402015-04-27 23:55:10 -0700125 puntSrc);
Saurav Das3d038262015-04-23 12:36:58 -0700126
127 ForwardingObjective puntDst = DefaultForwardingObjective.builder()
128 .fromApp(appId)
129 .makePermanent()
130 .withSelector(selectorDst)
131 .withTreatment(treatment)
132 .withFlag(ForwardingObjective.Flag.VERSATILE)
133 .add();
134 flowObjectiveService.forward(bgpSpeaker.connectPoint().deviceId(),
sanghof22fb402015-04-27 23:55:10 -0700135 puntDst);
Saurav Das3d038262015-04-23 12:36:58 -0700136 log.info("Sent punt forwarding objective to {}", bgpSpeaker.connectPoint().deviceId());
Jonathan Hartf5829202015-02-12 09:37:02 -0800137 }
138
139 /**
140 * Forwards a BGP packet to another connect point.
141 *
142 * @param context the packet context of the incoming packet
143 */
144 private void forward(PacketContext context) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800145 ConnectPoint outputPort = null;
Jonathan Hartf5829202015-02-12 09:37:02 -0800146
147 IPv4 ipv4 = (IPv4) context.inPacket().parsed().getPayload();
148 IpAddress dstAddress = IpAddress.valueOf(ipv4.getDestinationAddress());
149
Jonathan Hart936a7292015-03-06 18:02:57 -0800150 if (context.inPacket().receivedFrom().equals(bgpSpeaker.connectPoint())) {
151 BgpPeer peer = configService.getBgpPeers().get(dstAddress);
152 if (peer != null) {
153 outputPort = peer.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800154 }
Jonathan Hart936a7292015-03-06 18:02:57 -0800155 }
156 for (InterfaceAddress addr : bgpSpeaker.interfaceAddresses()) {
157 if (addr.ipAddress().equals(dstAddress) && !context.inPacket()
158 .receivedFrom().equals(bgpSpeaker.connectPoint())) {
159 outputPort = bgpSpeaker.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800160 }
161 }
162
163 if (outputPort != null) {
164 TrafficTreatment t = DefaultTrafficTreatment.builder()
165 .setOutput(outputPort.port()).build();
166 OutboundPacket o = new DefaultOutboundPacket(
167 outputPort.deviceId(), t, context.inPacket().unparsed());
168 packetService.emit(o);
169 }
170 }
171
172 /**
173 * Packet processor responsible receiving and filtering BGP packets.
174 */
175 private class BgpProcessor implements PacketProcessor {
176
177 @Override
178 public void process(PacketContext context) {
179 // Stop processing if the packet has been handled, since we
180 // can't do any more to it.
181 if (context.isHandled()) {
182 return;
183 }
184
185 Ethernet packet = context.inPacket().parsed();
186
187 if (packet == null) {
188 return;
189 }
190
191 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
192 IPv4 ipv4Packet = (IPv4) packet.getPayload();
193 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_TCP) {
194 TCP tcpPacket = (TCP) ipv4Packet.getPayload();
195
196 if (tcpPacket.getDestinationPort() == BGP_PORT ||
197 tcpPacket.getSourcePort() == BGP_PORT) {
198 forward(context);
199 }
200 }
201 }
202 }
203 }
204}