blob: ae32bfc345ca4fcdc83deff1b29a4d336789b349 [file] [log] [blame]
Pier Ventre10bd8d12016-11-26 21:05:22 -08001/*
2 * Copyright 2016-present 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 */
16
17package org.onosproject.segmentrouting;
18
Pier Ventre735b8c82016-12-02 08:16:05 -080019import org.onlab.packet.Ethernet;
20import org.onlab.packet.IpAddress;
21import org.onlab.packet.MacAddress;
Pier Ventre10bd8d12016-11-26 21:05:22 -080022import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
Pier Ventre735b8c82016-12-02 08:16:05 -080023import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.Host;
26import org.onosproject.net.HostId;
27import org.onosproject.net.flow.DefaultTrafficTreatment;
28import org.onosproject.net.flow.TrafficTreatment;
Pier Ventre10bd8d12016-11-26 21:05:22 -080029import org.onosproject.net.host.HostService;
Pier Ventre735b8c82016-12-02 08:16:05 -080030import org.onosproject.net.packet.DefaultOutboundPacket;
31import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
32import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventre10bd8d12016-11-26 21:05:22 -080033import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
Pier Ventre735b8c82016-12-02 08:16:05 -080036import java.nio.ByteBuffer;
37
38import static com.google.common.base.Preconditions.checkNotNull;
39
Pier Ventre10bd8d12016-11-26 21:05:22 -080040/**
Pier Ventre735b8c82016-12-02 08:16:05 -080041 * This handler provides provides useful functions to the
42 * neighbour handlers (ARP, NDP).
Pier Ventre10bd8d12016-11-26 21:05:22 -080043 */
Pier Ventre735b8c82016-12-02 08:16:05 -080044public class SegmentRoutingNeighbourHandler {
Pier Ventre10bd8d12016-11-26 21:05:22 -080045
46 private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourHandler.class);
Pier Ventre735b8c82016-12-02 08:16:05 -080047
48 protected SegmentRoutingManager srManager;
49 protected DeviceConfiguration config;
Pier Ventre10bd8d12016-11-26 21:05:22 -080050
51 /**
Pier Ventre735b8c82016-12-02 08:16:05 -080052 * Creates an SegmentRoutingNeighbourHandler object.
Pier Ventre10bd8d12016-11-26 21:05:22 -080053 *
Pier Ventre735b8c82016-12-02 08:16:05 -080054 * @param srManager SegmentRoutingManager object
Pier Ventre10bd8d12016-11-26 21:05:22 -080055 */
Pier Ventre735b8c82016-12-02 08:16:05 -080056 public SegmentRoutingNeighbourHandler(SegmentRoutingManager srManager) {
57 this.srManager = srManager;
58 this.config = checkNotNull(srManager.deviceConfiguration);
Pier Ventre10bd8d12016-11-26 21:05:22 -080059 }
60
Pier Ventre735b8c82016-12-02 08:16:05 -080061 /**
62 * Creates an SegmentRoutingNeighbourHandler object.
Pier Ventre10bd8d12016-11-26 21:05:22 -080063 */
Pier Ventre735b8c82016-12-02 08:16:05 -080064 public SegmentRoutingNeighbourHandler() {
65 this.srManager = null;
66 this.config = null;
67 }
68
69 /**
70 * Retrieve router (device) info.
71 *
72 * @param mac where to copy the mac
73 * @param ip where to copy the ip
74 * @param deviceId the device id
75 * @param targetAddress the target address
76 */
77 protected void getSenderInfo(byte[] mac,
78 byte[] ip,
79 DeviceId deviceId,
80 IpAddress targetAddress) {
81 byte[] senderMacAddress;
82 byte[] senderIpAddress;
83 try {
84 senderMacAddress = config.getDeviceMac(deviceId).toBytes();
85 senderIpAddress = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address())
86 .toOctets();
87 } catch (DeviceConfigNotFoundException e) {
88 log.warn(e.getMessage() + " Aborting sendArpRequest.");
89 return;
90 }
91 /*
92 * FIXME understand how to manage IPv4/IPv6 together.
93 */
94 System.arraycopy(senderMacAddress, 0, mac, 0, senderMacAddress.length);
95 System.arraycopy(senderIpAddress, 0, ip, 0, senderIpAddress.length);
96 }
97
98 /**
99 * Utility to send a ND reply using the supplied information.
100 *
101 * @param pkt the request
102 * @param targetMac the target mac
103 * @param hostService the host service
104 */
105 protected void sendResponse(NeighbourMessageContext pkt, MacAddress targetMac, HostService hostService) {
106 HostId dstId = HostId.hostId(pkt.srcMac(), pkt.vlan());
107 Host dst = hostService.getHost(dstId);
108 if (dst == null) {
109 log.warn("Cannot send {} response to host {} - does not exist in the store",
110 pkt.protocol(), dstId);
111 return;
112 }
113 pkt.reply(targetMac);
114 }
115
116 /**
117 * Flood to all ports in the same subnet.
118 *
119 * @param packet packet to be flooded
120 * @param inPort where the packet comes from
121 * @param targetAddress the target address
122 */
123 protected void flood(Ethernet packet, ConnectPoint inPort, IpAddress targetAddress) {
124 try {
125 srManager.deviceConfiguration
126 .getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
127 if (subnet.contains(targetAddress)) {
128 ports.stream()
129 .filter(port -> port != inPort.port())
130 .forEach(port -> {
131 forward(packet, new ConnectPoint(inPort.deviceId(), port));
132 });
Pier Ventre10bd8d12016-11-26 21:05:22 -0800133 }
Pier Ventre735b8c82016-12-02 08:16:05 -0800134 });
135 } catch (DeviceConfigNotFoundException e) {
136 log.warn(e.getMessage()
137 + " Cannot flood in subnet as device config not available"
138 + " for device: " + inPort.deviceId());
Pier Ventre10bd8d12016-11-26 21:05:22 -0800139 }
140 }
141
Pier Ventre735b8c82016-12-02 08:16:05 -0800142 /*
143 * Floods only on the port which have been configured with the subnet
144 * of the target address. The in port is excluded.
145 *
146 * @param pkt the ndp/arp packet and context information
147 */
148 protected void flood(NeighbourMessageContext pkt) {
149 try {
150 srManager.deviceConfiguration
151 .getSubnetPortsMap(pkt.inPort().deviceId()).forEach((subnet, ports) -> {
152 if (subnet.contains(pkt.target())) {
153 ports.stream()
154 .filter(port -> port != pkt.inPort().port())
155 .forEach(port -> {
156 ConnectPoint outPoint = new ConnectPoint(
157 pkt.inPort().deviceId(),
158 port
159 );
160 pkt.forward(outPoint);
161 });
162 }
163 });
164 } catch (DeviceConfigNotFoundException e) {
165 log.warn(e.getMessage()
166 + " Cannot flood in subnet as device config not available"
167 + " for device: " + pkt.inPort().deviceId());
168 }
169 }
170
171 /**
172 * Packet out to given port.
173 *
174 * Note: In current implementation, we expect all communication with
175 * end hosts within a subnet to be untagged.
176 * <p>
177 * For those pipelines that internally assigns a VLAN, the VLAN tag will be
178 * removed before egress.
179 * <p>
180 * For those pipelines that do not assign internal VLAN, the packet remains
181 * untagged.
182 *
183 * @param packet packet to be forwarded
184 * @param outPort where the packet should be forwarded
185 */
186 private void forward(Ethernet packet, ConnectPoint outPort) {
187 ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
188
189 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
190 tbuilder.setOutput(outPort.port());
191 srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
192 tbuilder.build(), buf));
193 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800194
195}