blob: a80c0f8191c4c668f90e95709b3f162c4d687032 [file] [log] [blame]
Amit Ghosh8951f042017-08-10 13:48:10 +01001/*
2 * Copyright 2017-present Open Networking Foundation
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.opencord.dhcpl2relay;
18
19import org.onlab.packet.BasePacket;
20import org.onlab.packet.DHCP;
21import org.onlab.packet.DHCPOption;
22import org.onlab.packet.DHCPPacketType;
23import org.onlab.packet.Ethernet;
24import org.onlab.packet.IPv4;
25import org.onlab.packet.Ip4Address;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.UDP;
28import org.onosproject.net.ConnectPoint;
29import org.onosproject.net.packet.DefaultInboundPacket;
30import org.onosproject.net.packet.DefaultPacketContext;
31import org.onosproject.net.packet.InboundPacket;
32import org.onosproject.net.packet.OutboundPacket;
33import org.onosproject.net.packet.PacketContext;
34import org.onosproject.net.packet.PacketProcessor;
35import org.onosproject.net.packet.PacketServiceAdapter;
36
37import org.opencord.dhcpl2relay.packet.DhcpEthernet;
38
39import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42import java.nio.ByteBuffer;
43import java.nio.charset.StandardCharsets;
44
45import java.util.ArrayList;
46import java.util.LinkedList;
47import java.util.List;
48
49import static org.junit.Assert.fail;
50
51
52/**
53 * Common methods for AAA app testing.
54 */
55public class DhcpL2RelayTestBase {
56 private final Logger log = LoggerFactory.getLogger(getClass());
57
58 private static final int TRANSACTION_ID = 1000;
59
60 private static final String EXPECTED_IP = "10.2.0.2";
61
62 List<BasePacket> savedPackets = new LinkedList<>();
63 PacketProcessor packetProcessor;
64
65
66 /**
67 * Saves the given packet onto the saved packets list.
68 *
69 * @param packet packet to save
70 */
71 void savePacket(BasePacket packet) {
72 savedPackets.add(packet);
73 }
74
75 BasePacket getPacket() {
76 return savedPackets.remove(0);
77 }
78
79 /**
80 * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
81 */
82 class MockPacketService extends PacketServiceAdapter {
83
84 @Override
85 public void addProcessor(PacketProcessor processor, int priority) {
86 packetProcessor = processor;
87 }
88
89 @Override
90 public void emit(OutboundPacket packet) {
91 try {
92 DhcpEthernet eth = DhcpEthernet.deserializer().deserialize(packet.data().array(),
93 0, packet.data().array().length);
94 savePacket(eth);
95 } catch (Exception e) {
96 fail(e.getMessage());
97 }
98 }
99 }
100
101 /**
102 * Mocks the DefaultPacketContext.
103 */
104 final class TestPacketContext extends DefaultPacketContext {
105
106 private TestPacketContext(long time, InboundPacket inPkt,
107 OutboundPacket outPkt, boolean block) {
108 super(time, inPkt, outPkt, block);
109 }
110
111 @Override
112 public void send() {
113 // We don't send anything out.
114 }
115 }
116
117 /**
118 * Sends an Ethernet packet to the process method of the Packet Processor.
119 *
120 * @param pkt Ethernet packet
121 */
122 void sendPacket(DhcpEthernet pkt, ConnectPoint cp) {
123 final ByteBuffer byteBuffer = ByteBuffer.wrap(pkt.serialize());
124 InboundPacket inPacket = new DefaultInboundPacket(cp, null, byteBuffer);
125
126 PacketContext context = new TestPacketContext(127L, inPacket, null, false);
127 packetProcessor.process(context);
128 }
129
130 /**
131 * Constructs an Ethernet packet with IP/UDP/DHCP payload.
132 *
133 * @return Ethernet packet
134 */
135 private DhcpEthernet construcEthernetPacket(MacAddress srcMac, MacAddress dstMac,
136 String dstIp, byte dhcpReqRsp,
137 MacAddress clientHwAddress,
138 Ip4Address dhcpClientIpAddress) {
139 // Ethernet Frame.
140 DhcpEthernet ethPkt = new DhcpEthernet();
141 ethPkt.setSourceMacAddress(srcMac);
142 ethPkt.setDestinationMacAddress(dstMac);
143 ethPkt.setEtherType(Ethernet.TYPE_IPV4);
144 ethPkt.setVlanID((short) 2);
145 ethPkt.setPriorityCode((byte) 6);
146
147 // IP Packet
148 IPv4 ipv4Reply = new IPv4();
149 ipv4Reply.setSourceAddress(0);
150 ipv4Reply.setDestinationAddress(dstIp);
151
152 ipv4Reply.setTtl((byte) 127);
153
154 // UDP Datagram.
155 UDP udpReply = new UDP();
156 udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
157 udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
158
159 // DHCP Payload.
160 DHCP dhcpReply = new DHCP();
161 dhcpReply.setOpCode(dhcpReqRsp);
162
163 dhcpReply.setYourIPAddress(dhcpClientIpAddress.toInt());
164 dhcpReply.setServerIPAddress(0);
165
166 final byte[] serverNameBytes = new byte[64];
167 String result = new String(serverNameBytes, StandardCharsets.US_ASCII).trim();
168 dhcpReply.setServerName(result);
169
170 final byte[] bootFileBytes = new byte[128];
171 String result1 = new String(bootFileBytes, StandardCharsets.US_ASCII).trim();
172 dhcpReply.setBootFileName(result1);
173
174 dhcpReply.setTransactionId(TRANSACTION_ID);
175 dhcpReply.setClientHardwareAddress(clientHwAddress.toBytes());
176 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
177 dhcpReply.setHardwareAddressLength((byte) 6);
178
179 udpReply.setPayload(dhcpReply);
180 ipv4Reply.setPayload(udpReply);
181 ethPkt.setPayload(ipv4Reply);
182
183 return ethPkt;
184 }
185
186 /**
187 * Constructs DHCP Discover Packet.
188 *
189 * @return Ethernet packet
190 */
191 DhcpEthernet constructDhcpDiscoverPacket(MacAddress clientMac) {
192
193 DhcpEthernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
194 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
195 Ip4Address.valueOf("0.0.0.0"));
196
197 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
198 UDP udpPacket = (UDP) ipv4Packet.getPayload();
199 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
200
201 dhcpPacket.setOptions(constructDhcpOptions(DHCPPacketType.DHCPDISCOVER));
202
203 return pkt;
204 }
205
206 /**
207 * Constructs DHCP Request Packet.
208 *
209 * @return Ethernet packet
210 */
211 DhcpEthernet constructDhcpRequestPacket(MacAddress clientMac) {
212
213 DhcpEthernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
214 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
215 Ip4Address.valueOf("0.0.0.0"));
216
217 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
218 UDP udpPacket = (UDP) ipv4Packet.getPayload();
219 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
220
221 dhcpPacket.setOptions(constructDhcpOptions(DHCPPacketType.DHCPREQUEST));
222
223 return pkt;
224 }
225
226 /**
227 * Constructs DHCP Offer Packet.
228 *
229 * @return Ethernet packet
230 */
231 DhcpEthernet constructDhcpOfferPacket(MacAddress servMac, MacAddress clientMac,
232 String ipAddress, String dhcpClientIpAddress) {
233
234 DhcpEthernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
235 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
236
237 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
238 UDP udpPacket = (UDP) ipv4Packet.getPayload();
239 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
240
241 dhcpPacket.setOptions(constructDhcpOptions(DHCPPacketType.DHCPOFFER));
242
243 return pkt;
244 }
245
246 /**
247 * Constructs DHCP Ack Packet.
248 *
249 * @return Ethernet packet
250 */
251 DhcpEthernet constructDhcpAckPacket(MacAddress servMac, MacAddress clientMac,
252 String ipAddress, String dhcpClientIpAddress) {
253
254 DhcpEthernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
255 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
256
257 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
258 UDP udpPacket = (UDP) ipv4Packet.getPayload();
259 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
260
261 dhcpPacket.setOptions(constructDhcpOptions(DHCPPacketType.DHCPACK));
262
263 return pkt;
264 }
265
266 /**
267 * Constructs DHCP Discover Options.
268 *
269 * @return Ethernet packet
270 */
271 private List<DHCPOption> constructDhcpOptions(DHCPPacketType packetType) {
272
273 // DHCP Options.
274 DHCPOption option = new DHCPOption();
275 List<DHCPOption> optionList = new ArrayList<>();
276
277
278 // DHCP Message Type.
279 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
280 option.setLength((byte) 1);
281 byte[] optionData = {(byte) packetType.getValue()};
282 option.setData(optionData);
283 optionList.add(option);
284
285 // DHCP Requested IP.
286 option = new DHCPOption();
287 option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
288 option.setLength((byte) 4);
289 optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
290 option.setData(optionData);
291 optionList.add(option);
292
293 // End Option.
294 option = new DHCPOption();
295 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
296 option.setLength((byte) 1);
297 optionList.add(option);
298
299 return optionList;
300 }
301}