blob: d76b3535790b0c36b4b9e1cb1bf586cd67b49049 [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
18import org.onlab.packet.Ethernet;
19import org.onlab.packet.IPv4;
20import org.onlab.packet.IpAddress;
21import org.onlab.packet.TCP;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.net.ConnectPoint;
Jonathan Hart936a7292015-03-06 18:02:57 -080024import org.onosproject.net.flow.DefaultFlowRule;
25import org.onosproject.net.flow.DefaultTrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080026import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart936a7292015-03-06 18:02:57 -080027import org.onosproject.net.flow.FlowRuleOperations;
28import org.onosproject.net.flow.FlowRuleService;
29import org.onosproject.net.flow.TrafficSelector;
Jonathan Hartf5829202015-02-12 09:37:02 -080030import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.net.packet.DefaultOutboundPacket;
32import org.onosproject.net.packet.OutboundPacket;
33import org.onosproject.net.packet.PacketContext;
Jonathan Hartf5829202015-02-12 09:37:02 -080034import org.onosproject.net.packet.PacketProcessor;
35import org.onosproject.net.packet.PacketService;
Jonathan Hart2da1e602015-02-18 19:09:24 -080036import org.onosproject.routing.config.BgpPeer;
37import org.onosproject.routing.config.BgpSpeaker;
38import org.onosproject.routing.config.InterfaceAddress;
39import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hartf5829202015-02-12 09:37:02 -080040
41
42/**
43 * Manages connectivity between peers by tunnelling BGP traffic through
44 * OpenFlow packet-ins and packet-outs.
45 */
46public class TunnellingConnectivityManager {
47
48 private static final short BGP_PORT = 179;
49
50 private final ApplicationId appId;
51
Jonathan Hart936a7292015-03-06 18:02:57 -080052 private final BgpSpeaker bgpSpeaker;
53
Jonathan Hartf5829202015-02-12 09:37:02 -080054 private final PacketService packetService;
55 private final RoutingConfigurationService configService;
56
57 private final BgpProcessor processor = new BgpProcessor();
58
59 public TunnellingConnectivityManager(ApplicationId appId,
60 RoutingConfigurationService configService,
Jonathan Hart936a7292015-03-06 18:02:57 -080061 PacketService packetService,
62 FlowRuleService flowService) {
Jonathan Hartf5829202015-02-12 09:37:02 -080063 this.appId = appId;
64 this.configService = configService;
65 this.packetService = packetService;
Jonathan Hart936a7292015-03-06 18:02:57 -080066
67 BgpSpeaker bgpSpeaker = null;
68 for (BgpSpeaker speaker : configService.getBgpSpeakers().values()) {
69 bgpSpeaker = speaker;
70 break;
71 }
72
73 if (bgpSpeaker == null) {
74 throw new IllegalArgumentException("Must have at least one BGP speaker configured");
75 }
76
77 this.bgpSpeaker = bgpSpeaker;
78
79 TrafficSelector selectorDst = DefaultTrafficSelector.builder()
80 .matchEthType(Ethernet.TYPE_IPV4)
81 .matchIPProtocol(IPv4.PROTOCOL_TCP)
82 .matchTcpDst(BGP_PORT)
83 .build();
84
85 TrafficSelector selectorSrc = DefaultTrafficSelector.builder()
86 .matchEthType(Ethernet.TYPE_IPV4)
87 .matchIPProtocol(IPv4.PROTOCOL_TCP)
88 .matchTcpSrc(BGP_PORT)
89 .build();
90
91 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
92 .punt()
93 .build();
94
95 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
96 builder.add(new DefaultFlowRule(bgpSpeaker.connectPoint().deviceId(),
97 selectorSrc, treatment, 0, appId, 0, true));
98 builder.add(new DefaultFlowRule(bgpSpeaker.connectPoint().deviceId(),
99 selectorDst, treatment, 0, appId, 0, true));
100 flowService.apply(builder.build());
Jonathan Hartf5829202015-02-12 09:37:02 -0800101 }
102
103 public void start() {
104 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 3);
Jonathan Hartf5829202015-02-12 09:37:02 -0800105 }
106
107 public void stop() {
108 packetService.removeProcessor(processor);
109 // Should revoke packet requests in the future
110 }
111
112 /**
113 * Forwards a BGP packet to another connect point.
114 *
115 * @param context the packet context of the incoming packet
116 */
117 private void forward(PacketContext context) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800118 ConnectPoint outputPort = null;
Jonathan Hartf5829202015-02-12 09:37:02 -0800119
120 IPv4 ipv4 = (IPv4) context.inPacket().parsed().getPayload();
121 IpAddress dstAddress = IpAddress.valueOf(ipv4.getDestinationAddress());
122
Jonathan Hart936a7292015-03-06 18:02:57 -0800123 if (context.inPacket().receivedFrom().equals(bgpSpeaker.connectPoint())) {
124 BgpPeer peer = configService.getBgpPeers().get(dstAddress);
125 if (peer != null) {
126 outputPort = peer.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800127 }
Jonathan Hart936a7292015-03-06 18:02:57 -0800128 }
129 for (InterfaceAddress addr : bgpSpeaker.interfaceAddresses()) {
130 if (addr.ipAddress().equals(dstAddress) && !context.inPacket()
131 .receivedFrom().equals(bgpSpeaker.connectPoint())) {
132 outputPort = bgpSpeaker.connectPoint();
Jonathan Hartf5829202015-02-12 09:37:02 -0800133 }
134 }
135
136 if (outputPort != null) {
137 TrafficTreatment t = DefaultTrafficTreatment.builder()
138 .setOutput(outputPort.port()).build();
139 OutboundPacket o = new DefaultOutboundPacket(
140 outputPort.deviceId(), t, context.inPacket().unparsed());
141 packetService.emit(o);
142 }
143 }
144
145 /**
146 * Packet processor responsible receiving and filtering BGP packets.
147 */
148 private class BgpProcessor implements PacketProcessor {
149
150 @Override
151 public void process(PacketContext context) {
152 // Stop processing if the packet has been handled, since we
153 // can't do any more to it.
154 if (context.isHandled()) {
155 return;
156 }
157
158 Ethernet packet = context.inPacket().parsed();
159
160 if (packet == null) {
161 return;
162 }
163
164 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
165 IPv4 ipv4Packet = (IPv4) packet.getPayload();
166 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_TCP) {
167 TCP tcpPacket = (TCP) ipv4Packet.getPayload();
168
169 if (tcpPacket.getDestinationPort() == BGP_PORT ||
170 tcpPacket.getSourcePort() == BGP_PORT) {
171 forward(context);
172 }
173 }
174 }
175 }
176 }
177}