Open Kilda Java Documentation
VerificationSendCommand.java
Go to the documentation of this file.
1 /* Copyright 2018 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.floodlight.command.flow;
17 
29 
30 import com.auth0.jwt.JWT;
31 import com.google.common.collect.ImmutableList;
32 import net.floodlightcontroller.core.IOFSwitch;
33 import net.floodlightcontroller.core.internal.IOFSwitchService;
34 import net.floodlightcontroller.core.module.FloodlightModuleContext;
35 import net.floodlightcontroller.packet.Data;
36 import net.floodlightcontroller.packet.Ethernet;
37 import net.floodlightcontroller.packet.IPv4;
38 import net.floodlightcontroller.packet.UDP;
39 import net.floodlightcontroller.util.OFMessageUtils;
40 import org.projectfloodlight.openflow.protocol.OFFactory;
41 import org.projectfloodlight.openflow.protocol.OFMessage;
42 import org.projectfloodlight.openflow.protocol.OFPacketOut;
43 import org.projectfloodlight.openflow.protocol.action.OFAction;
44 import org.projectfloodlight.openflow.types.DatapathId;
45 import org.projectfloodlight.openflow.types.EthType;
46 import org.projectfloodlight.openflow.types.MacAddress;
47 import org.projectfloodlight.openflow.types.OFPort;
48 import org.projectfloodlight.openflow.types.TransportPort;
49 
50 import java.util.ArrayList;
51 import java.util.List;
52 
53 public class VerificationSendCommand extends AbstractVerificationCommand {
54  private static final String NET_L3_ADDRESS = "127.0.0.2";
55 
56  private final OfBatchService ioService;
57  private final SwitchUtils switchUtils;
58  private final DataSignature signature;
59 
60  public VerificationSendCommand(CommandContext context, UniFlowVerificationRequest verificationRequest) {
61  super(context, verificationRequest);
62 
63  FloodlightModuleContext moduleContext = getContext().getModuleContext();
64  this.ioService = moduleContext.getServiceImpl(OfBatchService.class);
65  this.switchUtils = new SwitchUtils(moduleContext.getServiceImpl(IOFSwitchService.class));
66  this.signature = moduleContext.getServiceImpl(FlowVerificationService.class).getSignature();
67  }
68 
69  @Override
70  public void run() {
71  UniFlowVerificationRequest verificationRequest = getVerificationRequest();
72  DatapathId sourceDpId = DatapathId.of(verificationRequest.getSourceSwitchId().toLong());
73  IOFSwitch sw = switchUtils.lookupSwitch(sourceDpId);
74 
75  VerificationData data = VerificationData.of(verificationRequest);
76  data.setSenderLatency(sw.getLatency().getValue());
77 
78  Ethernet netPacket = wrapData(data);
79  OFMessage message = makePacketOut(sw, netPacket.serialize());
80 
81  try {
82  ioService.push(this, ImmutableList.of(new OfPendingMessage(sourceDpId, message)));
83  } catch (OFInstallException e) {
84  sendErrorResponse(FlowVerificationErrorCode.WRITE_FAILURE);
85  }
86  }
87 
88  @Override
89  public void ioComplete(List<OfPendingMessage> payload, boolean isError) {
90  if (!isError) {
91  return;
92  }
93 
94  sendErrorResponse(FlowVerificationErrorCode.WRITE_FAILURE);
95  }
96 
97  private Ethernet wrapData(VerificationData data) {
98  Data l7 = new Data(signature.sign(data.toJwt(JWT.create())));
99 
100  UDP l4 = new UDP();
101  l4.setPayload(l7);
102  l4.setSourcePort(TransportPort.of(PathVerificationService.VERIFICATION_PACKET_UDP_PORT));
103  l4.setDestinationPort(TransportPort.of(PathVerificationService.VERIFICATION_PACKET_UDP_PORT));
104 
105  IPv4 l3 = new IPv4();
106  l3.setPayload(l4);
107  l3.setSourceAddress(NET_L3_ADDRESS);
108  l3.setDestinationAddress(NET_L3_ADDRESS);
109 
110  Ethernet l2 = new Ethernet();
111  l2.setPayload(l3);
112  l2.setEtherType(EthType.IPv4);
113 
114  UniFlowVerificationRequest verificationRequest = getVerificationRequest();
115  l2.setSourceMACAddress(switchUtils.dpIdToMac(
116  DatapathId.of(verificationRequest.getSourceSwitchId().toLong())));
117  l2.setDestinationMACAddress(switchUtils.dpIdToMac(
118  DatapathId.of(verificationRequest.getDestSwitchId().toLong())));
119  if (0 != verificationRequest.getVlanId()) {
120  l2.setVlanID((short) verificationRequest.getVlanId());
121  }
122 
123  return l2;
124  }
125 
130  public static byte[] unwrapData(MacAddress targetL2Address, Ethernet packet) {
131  if (!packet.getDestinationMACAddress().equals(targetL2Address)) {
132  return null;
133  }
134 
135  if (!(packet.getPayload() instanceof IPv4)) {
136  return null;
137  }
138  IPv4 ip = (IPv4) packet.getPayload();
139 
140  if (!NET_L3_ADDRESS.equals(ip.getSourceAddress().toString())) {
141  return null;
142  }
143  if (!NET_L3_ADDRESS.equals(ip.getDestinationAddress().toString())) {
144  return null;
145  }
146 
147  if (!(ip.getPayload() instanceof UDP)) {
148  return null;
149  }
150  UDP udp = (UDP) ip.getPayload();
151 
152  if (udp.getSourcePort().getPort() != PathVerificationService.VERIFICATION_PACKET_UDP_PORT) {
153  return null;
154  }
155  if (udp.getDestinationPort().getPort() != PathVerificationService.VERIFICATION_PACKET_UDP_PORT) {
156  return null;
157  }
158 
159  return ((Data) udp.getPayload()).getData();
160  }
161 
162  private OFMessage makePacketOut(IOFSwitch sw, byte[] data) {
163  OFFactory ofFactory = sw.getOFFactory();
164  OFPacketOut.Builder pktOut = ofFactory.buildPacketOut();
165 
166  pktOut.setData(data);
167 
168  List<OFAction> actions = new ArrayList<>(2);
169  actions.add(ofFactory.actions().buildOutput().setPort(OFPort.TABLE).build());
170  pktOut.setActions(actions);
171 
172  OFMessageUtils.setInPort(pktOut, OFPort.of(getVerificationRequest().getSourcePort()));
173 
174  return pktOut.build();
175  }
176 }
MacAddress dpIdToMac(final IOFSwitch sw)
static byte [] unwrapData(MacAddress targetL2Address, Ethernet packet)
static VerificationData of(DecodedJWT token)
IOFSwitch lookupSwitch(DatapathId dpId)
byte [] sign(JWTCreator.Builder token)
VerificationSendCommand(CommandContext context, UniFlowVerificationRequest verificationRequest)
synchronized void push(org.openkilda.floodlight.command.Command initiator, List< OfPendingMessage > payload)
void ioComplete(List< OfPendingMessage > payload, boolean isError)
net
Definition: plan-b.py:46