Daniel Park
Committed by Gerrit Code Review

[ONOS-3946] Implement IcmpHandler for OpenstackRoutingService

- Process Icmp packet sent from Host to external network for OpenstackGateway Node
- Process Arp packet sent from physical  router to gateway

Change-Id: Ifcde71a9ca10180682811c9e1bcf58f991b36443
...@@ -68,7 +68,6 @@ public class OpenstackRouterCodec extends JsonCodec<OpenstackRouter> { ...@@ -68,7 +68,6 @@ public class OpenstackRouterCodec extends JsonCodec<OpenstackRouter> {
68 String tenantId = checkNotNull(routerInfo.path(TENANT_ID).asText()); 68 String tenantId = checkNotNull(routerInfo.path(TENANT_ID).asText());
69 String id = checkNotNull(routerInfo.path(ID).asText()); 69 String id = checkNotNull(routerInfo.path(ID).asText());
70 String name = checkNotNull(routerInfo.path(NAME).asText()); 70 String name = checkNotNull(routerInfo.path(NAME).asText());
71 - String status = checkNotNull(routerInfo.path(STATUS).asText());
72 String adminStateUp = checkNotNull(routerInfo.path(ADMIN_STATE_UP).asText()); 71 String adminStateUp = checkNotNull(routerInfo.path(ADMIN_STATE_UP).asText());
73 72
74 OpenstackExternalGateway.Builder osExtBuiler = new OpenstackExternalGateway.Builder(); 73 OpenstackExternalGateway.Builder osExtBuiler = new OpenstackExternalGateway.Builder();
...@@ -98,7 +97,7 @@ public class OpenstackRouterCodec extends JsonCodec<OpenstackRouter> { ...@@ -98,7 +97,7 @@ public class OpenstackRouterCodec extends JsonCodec<OpenstackRouter> {
98 .tenantId(tenantId) 97 .tenantId(tenantId)
99 .id(id) 98 .id(id)
100 .name(name) 99 .name(name)
101 - .status(OpenstackRouter.RouterStatus.valueOf(status)) 100 + .status(OpenstackRouter.RouterStatus.ACTIVE)
102 .adminStateUp(Boolean.valueOf(adminStateUp)) 101 .adminStateUp(Boolean.valueOf(adminStateUp))
103 .gatewayExternalInfo(osExtBuiler.build()); 102 .gatewayExternalInfo(osExtBuiler.build());
104 103
......
...@@ -27,12 +27,13 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -27,12 +27,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
27 /** 27 /**
28 * Contains OpenstackPort Information. 28 * Contains OpenstackPort Information.
29 */ 29 */
30 -public class OpenstackPortInfo { 30 +public final class OpenstackPortInfo {
31 private final Ip4Address hostIp; 31 private final Ip4Address hostIp;
32 private final MacAddress hostMac; 32 private final MacAddress hostMac;
33 private final DeviceId deviceId; 33 private final DeviceId deviceId;
34 private final long vni; 34 private final long vni;
35 private final Ip4Address gatewayIP; 35 private final Ip4Address gatewayIP;
36 + private final String networkId;
36 private final Collection<String> securityGroups; 37 private final Collection<String> securityGroups;
37 38
38 /** 39 /**
...@@ -46,12 +47,13 @@ public class OpenstackPortInfo { ...@@ -46,12 +47,13 @@ public class OpenstackPortInfo {
46 * @param securityGroups security group list 47 * @param securityGroups security group list
47 */ 48 */
48 public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni, 49 public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni,
49 - Ip4Address gatewayIP, Collection<String> securityGroups) { 50 + Ip4Address gatewayIP, String networkId, Collection<String> securityGroups) {
50 this.hostIp = hostIp; 51 this.hostIp = hostIp;
51 this.hostMac = hostMac; 52 this.hostMac = hostMac;
52 this.deviceId = deviceId; 53 this.deviceId = deviceId;
53 this.vni = vni; 54 this.vni = vni;
54 this.gatewayIP = gatewayIP; 55 this.gatewayIP = gatewayIP;
56 + this.networkId = networkId;
55 this.securityGroups = securityGroups; 57 this.securityGroups = securityGroups;
56 } 58 }
57 59
...@@ -101,6 +103,15 @@ public class OpenstackPortInfo { ...@@ -101,6 +103,15 @@ public class OpenstackPortInfo {
101 } 103 }
102 104
103 /** 105 /**
106 + * Returns network ID.
107 + *
108 + * @return network ID
109 + */
110 + public String networkId() {
111 + return networkId;
112 + }
113 +
114 + /**
104 * Returns Security Group ID list. 115 * Returns Security Group ID list.
105 * 116 *
106 * @return list of Security Group ID 117 * @return list of Security Group ID
...@@ -129,11 +140,12 @@ public class OpenstackPortInfo { ...@@ -129,11 +140,12 @@ public class OpenstackPortInfo {
129 private long vni; 140 private long vni;
130 private Ip4Address gatewayIP; 141 private Ip4Address gatewayIP;
131 private Collection<String> securityGroups; 142 private Collection<String> securityGroups;
143 + private String networkId;
132 144
133 /** 145 /**
134 * Sets the IP address of the port. 146 * Sets the IP address of the port.
135 * 147 *
136 - * @param gatewayIP 148 + * @param gatewayIP gateway IP
137 * @return Builder reference 149 * @return Builder reference
138 */ 150 */
139 public Builder setGatewayIP(Ip4Address gatewayIP) { 151 public Builder setGatewayIP(Ip4Address gatewayIP) {
...@@ -142,6 +154,17 @@ public class OpenstackPortInfo { ...@@ -142,6 +154,17 @@ public class OpenstackPortInfo {
142 } 154 }
143 155
144 /** 156 /**
157 + * Sets the network ID.
158 + *
159 + * @param networkId network id
160 + * @return Builder reference
161 + */
162 + public Builder setNetworkId(String networkId) {
163 + this.networkId = checkNotNull(networkId, "networkId cannot be null");
164 + return this;
165 + }
166 +
167 + /**
145 * Sets the host IP address of the port. 168 * Sets the host IP address of the port.
146 * 169 *
147 * @param hostIp host IP address 170 * @param hostIp host IP address
...@@ -202,16 +225,7 @@ public class OpenstackPortInfo { ...@@ -202,16 +225,7 @@ public class OpenstackPortInfo {
202 * @return OpenstackPortInfo reference 225 * @return OpenstackPortInfo reference
203 */ 226 */
204 public OpenstackPortInfo build() { 227 public OpenstackPortInfo build() {
205 - return new OpenstackPortInfo(this); 228 + return new OpenstackPortInfo(hostIp, hostMac, deviceId, vni, gatewayIP, networkId, securityGroups);
206 } 229 }
207 } 230 }
208 -
209 - private OpenstackPortInfo(Builder builder) {
210 - hostIp = builder.hostIp;
211 - hostMac = builder.hostMac;
212 - deviceId = builder.deviceId;
213 - vni = builder.vni;
214 - gatewayIP = builder.gatewayIP;
215 - securityGroups = builder.securityGroups;
216 - }
217 } 231 }
......
1 { 1 {
2 "apps" : { 2 "apps" : {
3 - "org.onosproject.openstackswitching" : { 3 + "org.onosproject.openstackrouting" : {
4 - "openstackswitching" : { 4 + "openstackrouting" : {
5 - "do_not_push_flows" : "false", 5 + "physicalRouterMac" : "2a:a1:8a:89:dd:a4",
6 - "neutron_server" : "http://192.168.56.103:9696/v2.0/", 6 + "gatewayBridgeId" : "of:0000000000000003",
7 - "keystone_server" : "http://192.168.56.103:5000/v2.0/", 7 + "gatewayExternalInterfaceName" : "veth0",
8 - "user_name" : "admin", 8 + "gatewayExternalInterfaceMac" : "be:15:c6:b0:df:9f"
9 - "password" : "nova", 9 + }
10 - "physicalRouterMac" : "00:00:00:00:00:20", 10 + },
11 + "org.onosproject.openstacknode" : {
12 + "openstacknode" : {
11 "nodes" : [ 13 "nodes" : [
12 - { 14 + {
13 - "hostname" : "compute-01", 15 + "hostname" : "compute-01",
14 - "ovsdbIp" : "192.168.56.102", 16 + "ovsdbIp" : "192.168.56.112",
15 - "ovsdbPort" : "6640", 17 + "ovsdbPort" : "6640",
16 - "bridgeId" : "of:0000000000000001", 18 + "bridgeId" : "of:0000000000000001",
17 - "openstackNodeType" : "COMPUTENODE" 19 + "openstackNodeType" : "COMPUTENODE"
18 - }, 20 + },
19 - { 21 + {
20 - "hostname" : "compute-02", 22 + "hostname" : "compute-02",
21 - "ovsdbIp" : "192.168.56.101", 23 + "ovsdbIp" : "192.168.56.113",
22 - "ovsdbPort" : "6640", 24 + "ovsdbPort" : "6640",
23 - "bridgeId" : "of:0000000000000002", 25 + "bridgeId" : "of:0000000000000002",
24 - "openstackNodeType" : "COMPUTENODE" 26 + "openstackNodeType" : "COMPUTENODE"
25 - }, 27 + },
26 - { 28 + {
27 - "hostname" : "network", 29 + "hostname" : "network",
28 - "ovsdbIp" : "192.168.56.106", 30 + "ovsdbIp" : "192.168.56.114",
29 - "ovsdbPort" : "6640", 31 + "ovsdbPort" : "6640",
30 - "bridgeId" : "of:0000000000000003", 32 + "bridgeId" : "of:0000000000000003",
31 - "openstackNodeType" : "GATEWAYNODE", 33 + "openstackNodeType" : "GATEWAYNODE",
32 - "externalIfName" : "eth3", 34 + "gatewayExternalInterfaceName" : "veth0",
33 - "externalIfMacAddress" : "00:00:00:00:00:11" 35 + "gatewayExternalInterfaceMac" : "be:15:c6:b0:df:9f"
34 - } 36 + }
35 ] 37 ]
36 - } 38 + }
37 - } 39 + },
40 + "org.onosproject.openstackinterface" : {
41 + "openstackinterface" : {
42 + "neutron_server" : "http://192.168.56.111:9696/v2.0/",
43 + "keystone_server" : "http://192.168.56.111:5000/v2.0/",
44 + "user_name" : "admin",
45 + "password" : "nova"
46 + }
47 + }
38 }, 48 },
39 "devices" : { 49 "devices" : {
40 "of:0000000000000001" : { 50 "of:0000000000000001" : {
...@@ -49,3 +59,4 @@ ...@@ -49,3 +59,4 @@
49 } 59 }
50 } 60 }
51 } 61 }
62 +
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * you may not use this file except in compliance with 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 6 * You may obtain a copy of the License at
7 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
...@@ -15,21 +15,260 @@ ...@@ -15,21 +15,260 @@
15 */ 15 */
16 package org.onosproject.openstacknetworking.routing; 16 package org.onosproject.openstacknetworking.routing;
17 17
18 +import com.google.common.collect.Maps;
19 +import org.onlab.packet.Ethernet;
20 +import org.onlab.packet.ICMP;
21 +import org.onlab.packet.IPv4;
22 +import org.onlab.packet.Ip4Address;
23 +import org.onlab.packet.MacAddress;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.Port;
27 +import org.onosproject.net.PortNumber;
28 +import org.onosproject.net.device.DeviceService;
29 +import org.onosproject.net.flow.DefaultTrafficSelector;
30 +import org.onosproject.net.flow.DefaultTrafficTreatment;
31 +import org.onosproject.net.flow.TrafficSelector;
32 +import org.onosproject.net.flow.TrafficTreatment;
33 +import org.onosproject.net.packet.DefaultOutboundPacket;
34 +import org.onosproject.net.packet.OutboundPacket;
18 import org.onosproject.net.packet.PacketContext; 35 import org.onosproject.net.packet.PacketContext;
36 +import org.onosproject.net.packet.PacketPriority;
37 +import org.onosproject.net.packet.PacketService;
38 +import org.onosproject.openstackinterface.OpenstackInterfaceService;
39 +import org.onosproject.openstackinterface.OpenstackPort;
40 +import org.onosproject.openstacknetworking.OpenstackPortInfo;
41 +import org.onosproject.openstacknetworking.OpenstackSwitchingService;
42 +import org.slf4j.Logger;
43 +
44 +import java.nio.ByteBuffer;
45 +import java.util.Map;
46 +import java.util.Optional;
47 +
48 +import static com.google.common.base.Preconditions.checkNotNull;
49 +
50 +import static org.slf4j.LoggerFactory.getLogger;
51 +
19 52
20 /** 53 /**
21 - * Handle ICMP packet processing for Managing Flow Rules In Openstack Nodes. 54 + * Handle ICMP packet sent from Openstack Gateway nodes.
22 */ 55 */
23 -public class OpenstackIcmpHandler implements Runnable { 56 +public class OpenstackIcmpHandler {
57 + protected final Logger log = getLogger(getClass());
58 +
59 + private final PacketService packetService;
60 + private final DeviceService deviceService;
61 + private final Map<String, OpenstackPortInfo> icmpInfoMap = Maps.newHashMap();
62 + private final OpenstackSwitchingService openstackSwitchingService;
63 + private final OpenstackInterfaceService openstackService;
64 + private final OpenstackRoutingConfig config;
65 + private static final MacAddress GATEWAY_MAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
66 + private static final String NETWORK_ROUTER_INTERFACE = "network:router_interface";
67 + private static final String PORTNAME = "portName";
68 +
69 + /**
70 + * Default constructor.
71 + *
72 + * @param packetService packet service
73 + * @param deviceService device service
74 + * @param openstackService openstackInterface service
75 + * @param config openstackRoutingConfig
76 + * @param openstackSwitchingService openstackSwitching service
77 + */
78 + OpenstackIcmpHandler(PacketService packetService, DeviceService deviceService,
79 + OpenstackInterfaceService openstackService, OpenstackRoutingConfig config,
80 + OpenstackSwitchingService openstackSwitchingService) {
81 + this.packetService = packetService;
82 + this.deviceService = deviceService;
83 + this.openstackService = checkNotNull(openstackService);
84 + this.config = checkNotNull(config);
85 + this.openstackSwitchingService = checkNotNull(openstackSwitchingService);
86 + }
87 +
88 + /**
89 + * Requests ICMP packet.
90 + *
91 + * @param appId Application Id
92 + */
93 + public void requestPacket(ApplicationId appId) {
94 + TrafficSelector icmpSelector = DefaultTrafficSelector.builder()
95 + .matchEthType(Ethernet.TYPE_IPV4)
96 + .matchIPProtocol(IPv4.PROTOCOL_ICMP)
97 + .build();
98 +
99 + packetService.requestPackets(icmpSelector,
100 + PacketPriority.CONTROL,
101 + appId,
102 + Optional.of(DeviceId.deviceId(config.gatewayBridgeId())));
103 + }
104 +
105 + /**
106 + * Handles ICMP packet.
107 + *
108 + * @param context packet context
109 + * @param ethernet ethernet
110 + */
111 + public void processIcmpPacket(PacketContext context, Ethernet ethernet) {
112 + checkNotNull(context, "context can not be null");
113 + checkNotNull(ethernet, "ethernet can not be null");
114 +
115 + IPv4 ipPacket = (IPv4) ethernet.getPayload();
116 +
117 + log.debug("icmpEvent called from ip {}, mac {}", Ip4Address.valueOf(ipPacket.getSourceAddress()).toString(),
118 + ethernet.getSourceMAC().toString());
119 +
120 + ICMP icmp = (ICMP) ipPacket.getPayload();
121 + short icmpId = getIcmpId(icmp);
122 +
123 + DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
124 + if (icmp.getIcmpType() == ICMP.TYPE_ECHO_REQUEST) {
125 + //TODO: Considers icmp between internal subnets which are belonged to the same router.
24 126
25 - volatile PacketContext context; 127 + OpenstackPortInfo openstackPortInfo =
26 - private OpenstackRoutingRulePopulator rulePopulator; 128 + getOpenstackPortInfo(Ip4Address.valueOf(ipPacket.getSourceAddress()), ethernet.getSourceMAC());
27 - OpenstackIcmpHandler(OpenstackRoutingRulePopulator rulePopulator, PacketContext context) { 129 +
28 - this.context = context; 130 + checkNotNull(openstackPortInfo, "openstackPortInfo can not be null");
29 - this.rulePopulator = rulePopulator; 131 +
132 + if (ipPacket.getDestinationAddress() == openstackPortInfo.gatewayIP().toInt()) {
133 + processIcmpPacketSentToGateway(ipPacket, icmp, openstackPortInfo);
134 + } else {
135 + Ip4Address pNatIpAddress = pNatIpForPort(openstackPortInfo);
136 + checkNotNull(pNatIpAddress, "pNatIpAddress can not be null");
137 +
138 + sendRequestPacketToExt(ipPacket, icmp, deviceId, pNatIpAddress);
139 +
140 + String icmpInfoKey = String.valueOf(icmpId)
141 + .concat(String.valueOf(pNatIpAddress.toInt()))
142 + .concat(String.valueOf(ipPacket.getDestinationAddress()));
143 + icmpInfoMap.putIfAbsent(icmpInfoKey, openstackPortInfo);
144 + }
145 + } else if (icmp.getIcmpType() == ICMP.TYPE_ECHO_REPLY) {
146 + String icmpInfoKey = String.valueOf(icmpId)
147 + .concat(String.valueOf(ipPacket.getDestinationAddress()))
148 + .concat(String.valueOf(ipPacket.getSourceAddress()));
149 +
150 + processResponsePacketFromExternalToHost(ipPacket, icmp, icmpInfoMap.get(icmpInfoKey));
151 +
152 + icmpInfoMap.remove(icmpInfoKey);
153 + }
30 } 154 }
31 155
32 - @Override 156 + private void processIcmpPacketSentToGateway(IPv4 icmpRequestIpv4, ICMP icmpRequest,
33 - public void run() { 157 + OpenstackPortInfo openstackPortInfo) {
158 + icmpRequest.setIcmpType(ICMP.TYPE_ECHO_REPLY)
159 + .resetChecksum();
160 +
161 + icmpRequestIpv4.setSourceAddress(icmpRequestIpv4.getDestinationAddress())
162 + .setDestinationAddress(openstackPortInfo.ip().toInt())
163 + .resetChecksum();
164 +
165 + icmpRequestIpv4.setPayload(icmpRequest);
166 +
167 + Ethernet icmpResponseEth = new Ethernet();
168 +
169 + icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
170 + .setSourceMACAddress(GATEWAY_MAC)
171 + .setDestinationMACAddress(openstackPortInfo.mac())
172 + .setPayload(icmpRequestIpv4);
173 +
174 + sendResponsePacketToHost(icmpResponseEth, openstackPortInfo);
175 + }
176 +
177 + private void sendRequestPacketToExt(IPv4 icmpRequestIpv4, ICMP icmpRequest, DeviceId deviceId,
178 + Ip4Address pNatIpAddress) {
179 + icmpRequest.resetChecksum();
180 + icmpRequestIpv4.setSourceAddress(pNatIpAddress.toInt())
181 + .resetChecksum();
182 + icmpRequestIpv4.setPayload(icmpRequest);
183 +
184 + Ethernet icmpRequestEth = new Ethernet();
185 +
186 + icmpRequestEth.setEtherType(Ethernet.TYPE_IPV4)
187 + .setSourceMACAddress(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
188 + .setDestinationMACAddress(MacAddress.valueOf(config.physicalRouterMac()))
189 + .setPayload(icmpRequestIpv4);
190 +
191 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
192 + .setOutput(getPortForAnnotationPortName(DeviceId.deviceId(config.gatewayBridgeId()),
193 + config.gatewayExternalInterfaceName()))
194 + .build();
195 +
196 + OutboundPacket packet = new DefaultOutboundPacket(deviceId,
197 + treatment, ByteBuffer.wrap(icmpRequestEth.serialize()));
198 +
199 + packetService.emit(packet);
200 + }
201 +
202 + private void processResponsePacketFromExternalToHost(IPv4 icmpResponseIpv4, ICMP icmpResponse,
203 + OpenstackPortInfo openstackPortInfo) {
204 + icmpResponse.resetChecksum();
205 +
206 + icmpResponseIpv4.setDestinationAddress(openstackPortInfo.ip().toInt())
207 + .resetChecksum();
208 + icmpResponseIpv4.setPayload(icmpResponse);
209 +
210 + Ethernet icmpResponseEth = new Ethernet();
211 +
212 + icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
213 + .setSourceMACAddress(GATEWAY_MAC)
214 + .setDestinationMACAddress(openstackPortInfo.mac())
215 + .setPayload(icmpResponseIpv4);
216 +
217 + sendResponsePacketToHost(icmpResponseEth, openstackPortInfo);
218 + }
219 +
220 + private void sendResponsePacketToHost(Ethernet icmpResponseEth, OpenstackPortInfo openstackPortInfo) {
221 + Map.Entry<String, OpenstackPortInfo> entry = openstackSwitchingService.openstackPortInfo().entrySet().stream()
222 + .filter(e -> e.getValue().mac().equals(openstackPortInfo.mac()))
223 + .findAny().orElse(null);
224 +
225 + if (entry == null) {
226 + return;
227 + }
228 +
229 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
230 + .setOutput(getPortForAnnotationPortName(openstackPortInfo.deviceId(), entry.getKey()))
231 + .build();
232 +
233 + OutboundPacket packet = new DefaultOutboundPacket(openstackPortInfo.deviceId(),
234 + treatment, ByteBuffer.wrap(icmpResponseEth.serialize()));
235 +
236 + packetService.emit(packet);
237 + }
238 +
239 + private OpenstackPortInfo getOpenstackPortInfo(Ip4Address sourceIp, MacAddress sourceMac) {
240 + checkNotNull(openstackSwitchingService.openstackPortInfo(), "openstackportinfo collection can not be null");
241 +
242 + return openstackSwitchingService.openstackPortInfo().values()
243 + .stream().filter(p -> p.ip().equals(sourceIp) && p.mac().equals(sourceMac))
244 + .findAny().orElse(null);
245 + }
246 +
247 + private short getIcmpId(ICMP icmp) {
248 + return ByteBuffer.wrap(icmp.serialize(), 4, 2).getShort();
249 + }
250 +
251 + private Ip4Address pNatIpForPort(OpenstackPortInfo openstackPortInfo) {
252 +
253 + OpenstackPort openstackPort = openstackService.ports().stream()
254 + .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_INTERFACE) &&
255 + p.networkId().equals(openstackPortInfo.networkId()))
256 + .findAny().orElse(null);
257 +
258 + checkNotNull(openstackPort, "openstackPort can not be null");
259 +
260 + return openstackService.router(openstackPort.deviceId())
261 + .gatewayExternalInfo().externalFixedIps().values()
262 + .stream().findAny().orElse(null);
263 + }
264 +
265 + private PortNumber getPortForAnnotationPortName(DeviceId deviceId, String match) {
266 + Port port = deviceService.getPorts(deviceId).stream()
267 + .filter(p -> p.annotations().value(PORTNAME).equals(match))
268 + .findAny().orElse(null);
269 +
270 + checkNotNull(port, "port cannot be null");
271 +
272 + return port.number();
34 } 273 }
35 -}
...\ No newline at end of file ...\ No newline at end of file
274 +}
......
1 +/*
2 + * Copyright 2016 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 +package org.onosproject.openstacknetworking.routing;
17 +
18 +import org.onlab.packet.ARP;
19 +import org.onlab.packet.EthType;
20 +import org.onlab.packet.Ethernet;
21 +import org.onlab.packet.IPv4;
22 +import org.onlab.packet.Ip4Address;
23 +import org.onlab.packet.IpAddress;
24 +import org.onlab.packet.MacAddress;
25 +import org.onosproject.core.ApplicationId;
26 +import org.onosproject.net.DeviceId;
27 +import org.onosproject.net.flow.DefaultTrafficSelector;
28 +import org.onosproject.net.flow.DefaultTrafficTreatment;
29 +import org.onosproject.net.flow.TrafficSelector;
30 +import org.onosproject.net.flow.TrafficTreatment;
31 +import org.onosproject.net.packet.DefaultOutboundPacket;
32 +import org.onosproject.net.packet.PacketContext;
33 +import org.onosproject.net.packet.PacketPriority;
34 +import org.onosproject.net.packet.PacketService;
35 +import org.onosproject.openstackinterface.OpenstackInterfaceService;
36 +import org.onosproject.openstackinterface.OpenstackPort;
37 +import org.slf4j.Logger;
38 +
39 +import java.nio.ByteBuffer;
40 +import java.util.Optional;
41 +
42 +import static com.google.common.base.Preconditions.checkNotNull;
43 +import static org.slf4j.LoggerFactory.getLogger;
44 +
45 +/**
46 + * Handle ARP packet sent from Openstack Gateway nodes.
47 + */
48 +public class OpenstackRoutingArpHandler {
49 + protected final Logger log = getLogger(getClass());
50 +
51 + private final PacketService packetService;
52 + private final OpenstackInterfaceService openstackService;
53 + private final OpenstackRoutingConfig config;
54 + private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
55 +
56 + /**
57 + * Default constructor.
58 + *
59 + * @param packetService packet service
60 + * @param openstackService openstackInterface service
61 + * @param config openstackRoutingConfig
62 + */
63 + OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
64 + OpenstackRoutingConfig config) {
65 + this.packetService = packetService;
66 + this.openstackService = checkNotNull(openstackService);
67 + this.config = checkNotNull(config);
68 + }
69 +
70 + /**
71 + * Requests ARP packet to GatewayNode.
72 + *
73 + * @param appId application id
74 + */
75 + public void requestPacket(ApplicationId appId) {
76 +
77 + TrafficSelector arpSelector = DefaultTrafficSelector.builder()
78 + .matchEthType(EthType.EtherType.ARP.ethType().toShort())
79 + .build();
80 +
81 + packetService.requestPackets(arpSelector,
82 + PacketPriority.CONTROL,
83 + appId,
84 + Optional.of(DeviceId.deviceId(config.gatewayBridgeId())));
85 + }
86 +
87 + /**
88 + * Handles ARP packet.
89 + *
90 + * @param context packet context
91 + * @param ethernet ethernet
92 + */
93 + public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
94 + checkNotNull(context, "context can not be null");
95 + checkNotNull(ethernet, "ethernet can not be null");
96 +
97 + log.info("arpEvent called from {} to {}",
98 + Ip4Address.valueOf(((IPv4) ethernet.getPayload()).getSourceAddress()).toString(),
99 + Ip4Address.valueOf(((IPv4) ethernet.getPayload()).getDestinationAddress()).toString());
100 + ARP arp = (ARP) ethernet.getPayload();
101 +
102 + if (arp.getOpCode() != ARP.OP_REQUEST) {
103 + return;
104 + }
105 +
106 + IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
107 + MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
108 +
109 + if (targetMac == MacAddress.NONE) {
110 + return;
111 + }
112 +
113 + Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
114 + targetMac, ethernet);
115 +
116 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
117 + .setOutput(context.inPacket().receivedFrom().port())
118 + .build();
119 +
120 + packetService.emit(new DefaultOutboundPacket(
121 + context.inPacket().receivedFrom().deviceId(),
122 + treatment,
123 + ByteBuffer.wrap(ethReply.serialize())));
124 + }
125 +
126 + private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
127 + OpenstackPort port = openstackService.ports().stream()
128 + .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
129 + .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
130 + .findAny().orElse(null);
131 +
132 + if (port == null) {
133 + return MacAddress.NONE;
134 + }
135 + return port.macAddress();
136 + }
137 +}
1 +/*
2 + * Copyright 2016 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 +package org.onosproject.openstacknetworking.routing;
17 +
18 +import org.onosproject.core.ApplicationId;
19 +import org.onosproject.net.config.Config;
20 +import org.slf4j.Logger;
21 +
22 +import static org.slf4j.LoggerFactory.getLogger;
23 +
24 +/**
25 + * Configuration object for OpenstackRouting service.
26 + */
27 +public class OpenstackRoutingConfig extends Config<ApplicationId> {
28 + protected final Logger log = getLogger(getClass());
29 +
30 + public static final String PHYSICAL_ROUTER_MAC = "physicalRouterMac";
31 + public static final String GATEWAY_BRIDGE_ID = "gatewayBridgeId";
32 + public static final String GATEWAY_EXTERNAL_INTERFACE_NAME = "gatewayExternalInterfaceName";
33 + public static final String GATEWAY_EXTERNAL_INTERFACE_MAC = "gatewayExternalInterfaceMac";
34 +
35 + /**
36 + * Returns physical router mac.
37 + *
38 + * @return physical router mac
39 + */
40 + public String physicalRouterMac() {
41 + return this.get("physicalRouterMac", "");
42 + }
43 +
44 + /**
45 + * Returns gateway's bridge id.
46 + *
47 + * @return bridge id
48 + */
49 + public String gatewayBridgeId() {
50 + return this.get("gatewayBridgeId", "");
51 + }
52 +
53 + /**
54 + * Returns gateway's external interface name.
55 + *
56 + * @return external interface name
57 + */
58 + public String gatewayExternalInterfaceName() {
59 + return this.get("gatewayExternalInterfaceName", "");
60 + }
61 +
62 + /**
63 + * Returns gateway's external interface mac.
64 + *
65 + * @return external interface mac
66 + */
67 + public String gatewayExternalInterfaceMac() {
68 + return this.get("gatewayExternalInterfaceMac", "");
69 + }
70 +}
...@@ -32,6 +32,12 @@ import org.onosproject.core.ApplicationId; ...@@ -32,6 +32,12 @@ import org.onosproject.core.ApplicationId;
32 import org.onosproject.core.CoreService; 32 import org.onosproject.core.CoreService;
33 import org.onosproject.net.DeviceId; 33 import org.onosproject.net.DeviceId;
34 import org.onosproject.net.Port; 34 import org.onosproject.net.Port;
35 +import org.onosproject.net.config.ConfigFactory;
36 +import org.onosproject.net.config.NetworkConfigEvent;
37 +import org.onosproject.net.config.NetworkConfigListener;
38 +import org.onosproject.net.config.NetworkConfigRegistry;
39 +import org.onosproject.net.config.NetworkConfigService;
40 +import org.onosproject.net.config.basics.SubjectFactories;
35 import org.onosproject.net.device.DeviceService; 41 import org.onosproject.net.device.DeviceService;
36 import org.onosproject.net.driver.DriverService; 42 import org.onosproject.net.driver.DriverService;
37 import org.onosproject.net.flowobjective.FlowObjectiveService; 43 import org.onosproject.net.flowobjective.FlowObjectiveService;
...@@ -45,6 +51,7 @@ import org.onosproject.openstackinterface.OpenstackPort; ...@@ -45,6 +51,7 @@ import org.onosproject.openstackinterface.OpenstackPort;
45 import org.onosproject.openstackinterface.OpenstackRouter; 51 import org.onosproject.openstackinterface.OpenstackRouter;
46 import org.onosproject.openstackinterface.OpenstackRouterInterface; 52 import org.onosproject.openstackinterface.OpenstackRouterInterface;
47 import org.onosproject.openstacknetworking.OpenstackRoutingService; 53 import org.onosproject.openstacknetworking.OpenstackRoutingService;
54 +import org.onosproject.openstacknetworking.OpenstackSwitchingService;
48 import org.slf4j.Logger; 55 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory; 56 import org.slf4j.LoggerFactory;
50 57
...@@ -80,24 +87,44 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -80,24 +87,44 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
80 protected OpenstackInterfaceService openstackService; 87 protected OpenstackInterfaceService openstackService;
81 88
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 + protected OpenstackSwitchingService openstackSwitchingService;
91 +
92 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected FlowObjectiveService flowObjectiveService; 93 protected FlowObjectiveService flowObjectiveService;
84 94
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected DriverService driverService; 96 protected DriverService driverService;
87 97
98 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 + protected NetworkConfigService configService;
100 +
101 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 + protected NetworkConfigRegistry configRegistry;
103 +
104 +
105 +
88 private ApplicationId appId; 106 private ApplicationId appId;
89 private Map<String, OpenstackRouterInterface> routerInterfaceMap = Maps.newHashMap(); 107 private Map<String, OpenstackRouterInterface> routerInterfaceMap = Maps.newHashMap();
90 private Map<Integer, String> portNumMap = initPortNumMap(); 108 private Map<Integer, String> portNumMap = initPortNumMap();
91 private static final String APP_ID = "org.onosproject.openstackrouting"; 109 private static final String APP_ID = "org.onosproject.openstackrouting";
92 private static final String PORT_NAME = "portName"; 110 private static final String PORT_NAME = "portName";
93 private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; 111 private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface";
112 + private final ConfigFactory configFactory =
113 + new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, OpenstackRoutingConfig.class, "openstackrouting") {
114 + @Override
115 + public OpenstackRoutingConfig createConfig() {
116 + return new OpenstackRoutingConfig();
117 + }
118 + };
119 + private final NetworkConfigListener configListener = new InternalConfigListener();
94 120
95 - // TODO: This will be replaced to get the information from openstackswitchingservice. 121 + private OpenstackRoutingConfig config;
96 - private static final String EXTERNAL_INTERFACE_NAME = "veth0"; 122 + private static final int PNAT_PORT_NUM_START = 1024;
123 + private static final int PNAT_PORT_NUM_END = 65535;
97 124
98 private Map<Integer, String> initPortNumMap() { 125 private Map<Integer, String> initPortNumMap() {
99 Map<Integer, String> map = Maps.newHashMap(); 126 Map<Integer, String> map = Maps.newHashMap();
100 - for (int i = 1024; i < 65535; i++) { 127 + for (int i = PNAT_PORT_NUM_START; i < PNAT_PORT_NUM_END; i++) {
101 map.put(i, ""); 128 map.put(i, "");
102 } 129 }
103 return map; 130 return map;
...@@ -108,17 +135,30 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -108,17 +135,30 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
108 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "L3-event")); 135 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "L3-event"));
109 private ExecutorService icmpEventExecutorService = 136 private ExecutorService icmpEventExecutorService =
110 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "icmp-event")); 137 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "icmp-event"));
138 + private ExecutorService arpEventExecutorService =
139 + Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "arp-event"));
140 + private OpenstackIcmpHandler openstackIcmpHandler;
141 + private OpenstackRoutingArpHandler openstackArpHandler;
111 142
112 @Activate 143 @Activate
113 protected void activate() { 144 protected void activate() {
114 appId = coreService.registerApplication(APP_ID); 145 appId = coreService.registerApplication(APP_ID);
115 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); 146 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
147 + configRegistry.registerConfigFactory(configFactory);
148 + configService.addListener(configListener);
149 +
150 + readConfiguration();
151 +
116 log.info("onos-openstackrouting started"); 152 log.info("onos-openstackrouting started");
117 } 153 }
118 154
119 @Deactivate 155 @Deactivate
120 protected void deactivate() { 156 protected void deactivate() {
121 packetService.removeProcessor(internalPacketProcessor); 157 packetService.removeProcessor(internalPacketProcessor);
158 + l3EventExecutorService.shutdown();
159 + icmpEventExecutorService.shutdown();
160 + arpEventExecutorService.shutdown();
161 +
122 log.info("onos-openstackrouting stopped"); 162 log.info("onos-openstackrouting stopped");
123 } 163 }
124 164
...@@ -155,16 +195,16 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -155,16 +195,16 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
155 195
156 @Override 196 @Override
157 public void updateRouterInterface(OpenstackRouterInterface routerInterface) { 197 public void updateRouterInterface(OpenstackRouterInterface routerInterface) {
158 - routerInterfaceMap.putIfAbsent(routerInterface.portId(), routerInterface); 198 + routerInterfaceMap.putIfAbsent(routerInterface.id(), routerInterface);
159 List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList(); 199 List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList();
160 routerInterfaces.add(routerInterface); 200 routerInterfaces.add(routerInterface);
161 - checkExternalConnection(getOpenstackRouter(routerInterface.portId()), routerInterfaces); 201 + checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces);
162 } 202 }
163 203
164 @Override 204 @Override
165 public void removeRouterInterface(OpenstackRouterInterface routerInterface) { 205 public void removeRouterInterface(OpenstackRouterInterface routerInterface) {
166 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, 206 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId,
167 - openstackService, flowObjectiveService, deviceService, driverService); 207 + openstackService, flowObjectiveService, deviceService, driverService, config);
168 rulePopulator.removeExternalRules(routerInterface); 208 rulePopulator.removeExternalRules(routerInterface);
169 routerInterfaceMap.remove(routerInterface.portId()); 209 routerInterfaceMap.remove(routerInterface.portId());
170 } 210 }
...@@ -181,10 +221,10 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -181,10 +221,10 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
181 221
182 private OpenstackRouterInterface portToRouterInterface(OpenstackPort p) { 222 private OpenstackRouterInterface portToRouterInterface(OpenstackPort p) {
183 OpenstackRouterInterface.Builder osBuilder = new OpenstackRouterInterface.Builder() 223 OpenstackRouterInterface.Builder osBuilder = new OpenstackRouterInterface.Builder()
184 - .id(checkNotNull(p.id())) 224 + .id(checkNotNull(p.deviceId()))
185 .tenantId(checkNotNull(openstackService.network(p.networkId()).tenantId())) 225 .tenantId(checkNotNull(openstackService.network(p.networkId()).tenantId()))
186 .subnetId(checkNotNull(p.fixedIps().keySet().stream().findFirst().orElse(null)).toString()) 226 .subnetId(checkNotNull(p.fixedIps().keySet().stream().findFirst().orElse(null)).toString())
187 - .portId(checkNotNull(p.deviceId())); 227 + .portId(checkNotNull(p.id()));
188 228
189 return osBuilder.build(); 229 return osBuilder.build();
190 } 230 }
...@@ -196,19 +236,26 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -196,19 +236,26 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
196 236
197 if (context.isHandled()) { 237 if (context.isHandled()) {
198 return; 238 return;
239 + } else if (!context.inPacket().receivedFrom().deviceId().toString()
240 + .equals(config.gatewayBridgeId())) {
241 + return;
199 } 242 }
200 243
201 InboundPacket pkt = context.inPacket(); 244 InboundPacket pkt = context.inPacket();
202 Ethernet ethernet = pkt.parsed(); 245 Ethernet ethernet = pkt.parsed();
203 246
204 - if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_IPV4) { 247 + //TODO: Considers IPv6 later.
248 + if (ethernet == null) {
249 + return;
250 + } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
205 IPv4 iPacket = (IPv4) ethernet.getPayload(); 251 IPv4 iPacket = (IPv4) ethernet.getPayload();
206 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, 252 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId,
207 - openstackService, flowObjectiveService, deviceService, 253 + openstackService, flowObjectiveService, deviceService, driverService, config);
208 - driverService);
209 switch (iPacket.getProtocol()) { 254 switch (iPacket.getProtocol()) {
210 case IPv4.PROTOCOL_ICMP: 255 case IPv4.PROTOCOL_ICMP:
211 - icmpEventExecutorService.execute(new OpenstackIcmpHandler(rulePopulator, context)); 256 +
257 + icmpEventExecutorService.submit(() ->
258 + openstackIcmpHandler.processIcmpPacket(context, ethernet));
212 break; 259 break;
213 case IPv4.PROTOCOL_UDP: 260 case IPv4.PROTOCOL_UDP:
214 // don't process DHCP 261 // don't process DHCP
...@@ -219,7 +266,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -219,7 +266,8 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
219 } 266 }
220 default: 267 default:
221 int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress()); 268 int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress());
222 - Port port = getExternalPort(pkt.receivedFrom().deviceId(), EXTERNAL_INTERFACE_NAME); 269 + Port port =
270 + getExternalPort(pkt.receivedFrom().deviceId(), config.gatewayExternalInterfaceName());
223 if (port == null) { 271 if (port == null) {
224 log.warn("There`s no external interface"); 272 log.warn("There`s no external interface");
225 break; 273 break;
...@@ -230,7 +278,9 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -230,7 +278,9 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
230 portNum, openstackPort, port)); 278 portNum, openstackPort, port));
231 break; 279 break;
232 } 280 }
233 - 281 + } else if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
282 + arpEventExecutorService.submit(() ->
283 + openstackArpHandler.processArpPacketFromRouter(context, ethernet));
234 } 284 }
235 } 285 }
236 286
...@@ -265,9 +315,9 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -265,9 +315,9 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
265 315
266 private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) { 316 private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) {
267 long vni = Long.parseLong(openstackService.network(openstackService 317 long vni = Long.parseLong(openstackService.network(openstackService
268 - .port(routerInterface.id()).networkId()).segmentId()); 318 + .port(routerInterface.portId()).networkId()).segmentId());
269 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId, 319 OpenstackRoutingRulePopulator rulePopulator = new OpenstackRoutingRulePopulator(appId,
270 - openstackService, flowObjectiveService, deviceService, driverService); 320 + openstackService, flowObjectiveService, deviceService, driverService, config);
271 rulePopulator.populateExternalRules(vni, router, routerInterface); 321 rulePopulator.populateExternalRules(vni, router, routerInterface);
272 } 322 }
273 323
...@@ -288,4 +338,50 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -288,4 +338,50 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
288 .equals(ip4Address) ? openstackPort : null; 338 .equals(ip4Address) ? openstackPort : null;
289 } 339 }
290 340
341 + private void readConfiguration() {
342 + config = configService.getConfig(appId, OpenstackRoutingConfig.class);
343 + if (config == null) {
344 + log.error("No configuration found");
345 + return;
346 + }
347 +
348 + checkNotNull(config.physicalRouterMac());
349 + checkNotNull(config.gatewayBridgeId());
350 + checkNotNull(config.gatewayExternalInterfaceMac());
351 + checkNotNull(config.gatewayExternalInterfaceName());
352 +
353 + log.debug("Configured info: {}, {}, {}, {}", config.physicalRouterMac(), config.gatewayBridgeId(),
354 + config.gatewayExternalInterfaceMac(), config.gatewayExternalInterfaceName());
355 +
356 + reloadInitL3Rules();
357 +
358 + openstackIcmpHandler = new OpenstackIcmpHandler(packetService, deviceService,
359 + openstackService, config, openstackSwitchingService);
360 + openstackArpHandler = new OpenstackRoutingArpHandler(packetService, openstackService, config);
361 +
362 + openstackIcmpHandler.requestPacket(appId);
363 + openstackArpHandler.requestPacket(appId);
364 +
365 + log.info("OpenstackRouting configured");
366 + }
367 +
368 + private class InternalConfigListener implements NetworkConfigListener {
369 +
370 + @Override
371 + public void event(NetworkConfigEvent event) {
372 + if (!event.configClass().equals(OpenstackRoutingConfig.class)) {
373 + return;
374 + }
375 +
376 + switch (event.type()) {
377 + case CONFIG_ADDED:
378 + case CONFIG_UPDATED:
379 + l3EventExecutorService.execute(OpenstackRoutingManager.this::readConfiguration);
380 + break;
381 + default:
382 + log.debug("Unsupported event type {}", event.type().toString());
383 + break;
384 + }
385 + }
386 + }
291 } 387 }
......
...@@ -71,6 +71,7 @@ public class OpenstackRoutingRulePopulator { ...@@ -71,6 +71,7 @@ public class OpenstackRoutingRulePopulator {
71 private final OpenstackInterfaceService openstackService; 71 private final OpenstackInterfaceService openstackService;
72 private final DeviceService deviceService; 72 private final DeviceService deviceService;
73 private final DriverService driverService; 73 private final DriverService driverService;
74 + private final OpenstackRoutingConfig config;
74 75
75 private static final String PORTNAME_PREFIX_VM = "tap"; 76 private static final String PORTNAME_PREFIX_VM = "tap";
76 private static final String PORTNAME_PREFIX_ROUTER = "qr"; 77 private static final String PORTNAME_PREFIX_ROUTER = "qr";
...@@ -93,9 +94,6 @@ public class OpenstackRoutingRulePopulator { ...@@ -93,9 +94,6 @@ public class OpenstackRoutingRulePopulator {
93 private OpenstackRouter router; 94 private OpenstackRouter router;
94 private OpenstackRouterInterface routerInterface; 95 private OpenstackRouterInterface routerInterface;
95 96
96 - // TODO: This will be replaced to get the information from openstackswitchingservice.
97 - private static final String EXTERNAL_INTERFACE_NAME = "veth0";
98 -
99 /** 97 /**
100 * The constructor of openstackRoutingRulePopulator. 98 * The constructor of openstackRoutingRulePopulator.
101 * 99 *
...@@ -104,20 +102,23 @@ public class OpenstackRoutingRulePopulator { ...@@ -104,20 +102,23 @@ public class OpenstackRoutingRulePopulator {
104 * @param flowObjectiveService FlowObjectiveService 102 * @param flowObjectiveService FlowObjectiveService
105 * @param deviceService DeviceService 103 * @param deviceService DeviceService
106 * @param driverService DriverService 104 * @param driverService DriverService
105 + * @param config OpenstackRoutingConfig
107 */ 106 */
108 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService, 107 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
109 - FlowObjectiveService flowObjectiveService, 108 + FlowObjectiveService flowObjectiveService, DeviceService deviceService,
110 - DeviceService deviceService, DriverService driverService) { 109 + DriverService driverService, OpenstackRoutingConfig config) {
111 this.appId = appId; 110 this.appId = appId;
112 this.flowObjectiveService = flowObjectiveService; 111 this.flowObjectiveService = flowObjectiveService;
113 - this.openstackService = openstackService; 112 + this.openstackService = checkNotNull(openstackService);
114 this.deviceService = deviceService; 113 this.deviceService = deviceService;
115 this.driverService = driverService; 114 this.driverService = driverService;
115 + this.config = config;
116 } 116 }
117 117
118 /** 118 /**
119 * Populates flow rules for Pnat configurations. 119 * Populates flow rules for Pnat configurations.
120 - * @param inboundPacket Packet-in event packet 120 + *
121 + * @param inboundPacket Packet-in event packet
121 * @param openstackPort Target VM information 122 * @param openstackPort Target VM information
122 * @param portNum Pnat port number 123 * @param portNum Pnat port number
123 * @param externalIp external ip address 124 * @param externalIp external ip address
...@@ -168,6 +169,7 @@ public class OpenstackRoutingRulePopulator { ...@@ -168,6 +169,7 @@ public class OpenstackRoutingRulePopulator {
168 tBuilder.setUdpSrc(TpPort.tpPort(portNum)); 169 tBuilder.setUdpSrc(TpPort.tpPort(portNum));
169 break; 170 break;
170 default: 171 default:
172 + log.debug("Unsupported IPv4 protocol {}");
171 break; 173 break;
172 } 174 }
173 175
...@@ -188,7 +190,7 @@ public class OpenstackRoutingRulePopulator { ...@@ -188,7 +190,7 @@ public class OpenstackRoutingRulePopulator {
188 190
189 private Port getPortNumOfExternalInterface() { 191 private Port getPortNumOfExternalInterface() {
190 return deviceService.getPorts(inboundPacket.receivedFrom().deviceId()).stream() 192 return deviceService.getPorts(inboundPacket.receivedFrom().deviceId()).stream()
191 - .filter(p -> p.annotations().value(PORTNAME).equals(EXTERNAL_INTERFACE_NAME)) 193 + .filter(p -> p.annotations().value(PORTNAME).equals(config.gatewayExternalInterfaceName()))
192 .findAny().orElse(null); 194 .findAny().orElse(null);
193 } 195 }
194 196
...@@ -239,7 +241,15 @@ public class OpenstackRoutingRulePopulator { ...@@ -239,7 +241,15 @@ public class OpenstackRoutingRulePopulator {
239 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); 241 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
240 } 242 }
241 243
242 - private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) { 244 + /**
245 + * Returns NiciraExtension treatment.
246 + *
247 + * @param id device id
248 + * @param hostIp host ip
249 + * @return NiciraExtension treatment
250 + */
251 +
252 + public ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
243 Driver driver = driverService.getDriver(id); 253 Driver driver = driverService.getDriver(id);
244 DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id)); 254 DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
245 ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class); 255 ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
...@@ -257,7 +267,13 @@ public class OpenstackRoutingRulePopulator { ...@@ -257,7 +267,13 @@ public class OpenstackRoutingRulePopulator {
257 return extensionInstruction; 267 return extensionInstruction;
258 } 268 }
259 269
260 - private PortNumber getTunnelPort(DeviceId deviceId) { 270 + /**
271 + * Returns port number of vxlan tunnel.
272 + *
273 + * @param deviceId device id
274 + * @return port number of vxlan tunnel
275 + */
276 + public PortNumber getTunnelPort(DeviceId deviceId) {
261 Port port = deviceService.getPorts(deviceId).stream() 277 Port port = deviceService.getPorts(deviceId).stream()
262 .filter(p -> p.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL)) 278 .filter(p -> p.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL))
263 .findAny().orElse(null); 279 .findAny().orElse(null);
...@@ -343,16 +359,11 @@ public class OpenstackRoutingRulePopulator { ...@@ -343,16 +359,11 @@ public class OpenstackRoutingRulePopulator {
343 } 359 }
344 360
345 private Device getGatewayNode() { 361 private Device getGatewayNode() {
346 - return checkNotNull(StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false) 362 + return checkNotNull(deviceService.getDevice(DeviceId.deviceId(config.gatewayBridgeId())));
347 - .filter(d -> checkGatewayNode(d.id()))
348 - .findAny()
349 - .orElse(null));
350 } 363 }
351 364
352 private boolean checkGatewayNode(DeviceId deviceId) { 365 private boolean checkGatewayNode(DeviceId deviceId) {
353 - return !deviceService.getPorts(deviceId).stream().anyMatch(port -> 366 + return deviceId.toString().equals(config.gatewayBridgeId());
354 - port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER) ||
355 - port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM));
356 } 367 }
357 368
358 private long getVni(OpenstackPort openstackPort) { 369 private long getVni(OpenstackPort openstackPort) {
......
...@@ -94,6 +94,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -94,6 +94,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected DriverService driverService; 95 protected DriverService driverService;
96 96
97 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected OpenstackInterfaceService openstackService; 98 protected OpenstackInterfaceService openstackService;
98 99
99 public static final String PORTNAME_PREFIX_VM = "tap"; 100 public static final String PORTNAME_PREFIX_VM = "tap";
...@@ -126,6 +127,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -126,6 +127,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
126 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); 127 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
127 deviceService.addListener(internalDeviceListener); 128 deviceService.addListener(internalDeviceListener);
128 hostService.addListener(internalHostListener); 129 hostService.addListener(internalHostListener);
130 + arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
129 131
130 arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService); 132 arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
131 sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService); 133 sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);
...@@ -204,10 +206,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -204,10 +206,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
204 206
205 @Override 207 @Override
206 public void createNetwork(OpenstackNetwork openstackNetwork) { 208 public void createNetwork(OpenstackNetwork openstackNetwork) {
209 + //TODO
207 } 210 }
208 211
209 @Override 212 @Override
210 public void createSubnet(OpenstackSubnet openstackSubnet) { 213 public void createSubnet(OpenstackSubnet openstackSubnet) {
214 + //TODO
211 } 215 }
212 216
213 @Override 217 @Override
...@@ -296,9 +300,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -296,9 +300,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
296 300
297 private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks, 301 private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks,
298 Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) { 302 Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
299 - long vni = Long.parseLong(networks.stream() 303 + long vni;
304 + OpenstackNetwork openstackNetwork = networks.stream()
300 .filter(n -> n.id().equals(openstackPort.networkId())) 305 .filter(n -> n.id().equals(openstackPort.networkId()))
301 - .findAny().orElse(null).segmentId()); 306 + .findAny().orElse(null);
307 + if (openstackNetwork != null) {
308 + vni = Long.parseLong(openstackNetwork.segmentId());
309 + } else {
310 + log.debug("updatePortMap failed because there's no OpenstackNetwork matches {}", openstackPort.networkId());
311 + return;
312 + }
313 +
302 314
303 OpenstackSubnet openstackSubnet = subnets.stream() 315 OpenstackSubnet openstackSubnet = subnets.stream()
304 .filter(n -> n.networkId().equals(openstackPort.networkId())) 316 .filter(n -> n.networkId().equals(openstackPort.networkId()))
...@@ -312,6 +324,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -312,6 +324,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
312 .setHostMac(openstackPort.macAddress()) 324 .setHostMac(openstackPort.macAddress())
313 .setVni(vni) 325 .setVni(vni)
314 .setGatewayIP(gatewayIPAddress) 326 .setGatewayIP(gatewayIPAddress)
327 + .setNetworkId(openstackPort.networkId())
315 .setSecurityGroups(openstackPort.securityGroups()); 328 .setSecurityGroups(openstackPort.securityGroups());
316 329
317 openstackPortInfoMap.put(portName, portBuilder.build()); 330 openstackPortInfoMap.put(portName, portBuilder.build());
...@@ -321,7 +334,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -321,7 +334,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
321 securityGroupMap.put(sgId, openstackService.getSecurityGroup(sgId)); 334 securityGroupMap.put(sgId, openstackService.getSecurityGroup(sgId));
322 } 335 }
323 }); 336 });
324 -
325 } 337 }
326 338
327 private void processHostRemoved(Host host) { 339 private void processHostRemoved(Host host) {
...@@ -440,6 +452,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -440,6 +452,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
440 processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port()); 452 processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
441 break; 453 break;
442 default: 454 default:
455 + log.debug("Unsupported deviceEvent type {}", deviceEvent.type().toString());
443 break; 456 break;
444 } 457 }
445 } else if (event instanceof HostEvent) { 458 } else if (event instanceof HostEvent) {
...@@ -450,6 +463,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -450,6 +463,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
450 processHostRemoved((Host) hostEvent.subject()); 463 processHostRemoved((Host) hostEvent.subject());
451 break; 464 break;
452 default: 465 default:
466 + log.debug("Unsupported hostEvent type {}", hostEvent.type().toString());
453 break; 467 break;
454 } 468 }
455 } 469 }
......