Open Kilda Java Documentation
FlowVerificationService.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.service;
17 
26 
27 import com.auth0.jwt.interfaces.DecodedJWT;
28 import com.google.common.collect.ImmutableSet;
29 import net.floodlightcontroller.core.FloodlightContext;
30 import net.floodlightcontroller.core.IFloodlightProviderService;
31 import net.floodlightcontroller.core.IOFSwitch;
32 import net.floodlightcontroller.core.internal.IOFSwitchService;
33 import net.floodlightcontroller.core.module.FloodlightModuleContext;
34 import net.floodlightcontroller.core.module.FloodlightModuleException;
35 import net.floodlightcontroller.core.module.IFloodlightService;
36 import net.floodlightcontroller.packet.Ethernet;
37 import org.projectfloodlight.openflow.protocol.OFMessage;
38 import org.projectfloodlight.openflow.protocol.OFType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 
42 import java.util.LinkedList;
43 import java.util.ListIterator;
44 import java.util.Map;
45 import java.util.Set;
46 
47 public class FlowVerificationService extends AbstractOfHandler implements IFloodlightService {
48  private static Logger log = LoggerFactory.getLogger(FlowVerificationService.class);
49 
50  private final LinkedList<VerificationListenCommand> pendingRecipients = new LinkedList<>();
51 
52  private DataSignature signature = null;
53  private SwitchUtils switchUtils = null;
54 
58  public void subscribe(VerificationListenCommand handler) {
59  synchronized (pendingRecipients) {
60  pendingRecipients.add(handler);
61  }
62  }
63 
67  public void unsubscribe(VerificationListenCommand handler) {
68  synchronized (pendingRecipients) {
69  pendingRecipients.remove(handler);
70  }
71  }
72 
77  public void init(FloodlightModuleContext moduleContext) throws FloodlightModuleException {
78  // FIXME(surabujin): avoid usage foreign module configuration
79  Map<String, String> config = moduleContext.getConfigParams(PathVerificationService.class);
80  try {
81  signature = new DataSignature(config.get("hmac256-secret"));
83  throw new FloodlightModuleException(String.format("Unable to initialize %s", getClass().getName()), e);
84  }
85 
86  switchUtils = new SwitchUtils(moduleContext.getServiceImpl(IOFSwitchService.class));
87  activateSubscription(moduleContext, OFType.PACKET_IN);
88  }
89 
90  @Override
91  public boolean handle(IOFSwitch sw, OFMessage packet, FloodlightContext context) {
92  Ethernet eth = IFloodlightProviderService.bcStore.get(context, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
93 
95  try {
96  byte[] payload = VerificationSendCommand.unwrapData(switchUtils.dpIdToMac(sw), eth);
97  if (payload == null) {
98  log.debug("packet xId: {} is not flow verification packet", packet.getXid());
99  return false;
100  }
101 
102  DecodedJWT token = signature.verify(payload);
103  data = VerificationData.of(token);
104 
105  if (! data.getDest().equals(sw.getId())) {
106  throw new CorruptedNetworkDataException(String.format(
107  "Catch flow verification package on %s while target is %s", sw.getId(), data.getDest()));
108  }
109  } catch (CorruptedNetworkDataException e) {
110  log.error(String.format("dpid:%s %s", sw.getId(), e));
111  return false;
112  }
113 
114  boolean isHandled = false;
115  synchronized (pendingRecipients) {
116  for (ListIterator<VerificationListenCommand> iter = pendingRecipients.listIterator(); iter.hasNext(); ) {
117  VerificationListenCommand command = iter.next();
118 
119  if (!command.packetIn(sw, data)) {
120  continue;
121  }
122  isHandled = true;
123  iter.remove();
124  break;
125  }
126  }
127 
128  return isHandled;
129  }
130 
131  @Override
132  protected Set<String> mustHandleBefore() {
133  return ImmutableSet.of("PathVerificationService");
134  }
135 
137  return signature;
138  }
139 }
MacAddress dpIdToMac(final IOFSwitch sw)
static byte [] unwrapData(MacAddress targetL2Address, Ethernet packet)
void activateSubscription(IFloodlightModuleContext moduleContext, OFType... desiredTypes)
static VerificationData of(DecodedJWT token)
boolean handle(IOFSwitch sw, OFMessage packet, FloodlightContext context)
def command(payload, fields)
Definition: share.py:102
net
Definition: plan-b.py:46