Open Kilda Java Documentation
FlowsResource.java
Go to the documentation of this file.
1 /* Copyright 2017 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.switchmanager.web;
17 
18 import static org.openkilda.messaging.Utils.MAPPER;
19 
20 import com.google.common.collect.ImmutableList;
25 import org.projectfloodlight.openflow.protocol.OFActionType;
26 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
27 import org.projectfloodlight.openflow.protocol.OFInstructionType;
28 import org.projectfloodlight.openflow.protocol.action.OFAction;
29 import org.projectfloodlight.openflow.protocol.action.OFActionMeter;
30 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
31 import org.projectfloodlight.openflow.protocol.action.OFActionPushVlan;
32 import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
33 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
34 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
35 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionMeter;
36 import org.projectfloodlight.openflow.protocol.match.Match;
37 import org.projectfloodlight.openflow.protocol.match.MatchField;
38 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
39 import org.projectfloodlight.openflow.types.DatapathId;
40 import org.projectfloodlight.openflow.types.OFValueType;
41 import org.restlet.resource.Get;
42 import org.restlet.resource.ServerResource;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Objects;
50 import java.util.Optional;
51 
52 public class FlowsResource extends ServerResource {
53  private static final Logger LOGGER = LoggerFactory.getLogger(FlowsResource.class);
54  //should be extended once we find match field that should be shown in the response
55  private static final List<MatchField<? extends OFValueType>> KNOWN_MATCHES = ImmutableList.of(
56  MatchField.ETH_SRC, MatchField.ETH_DST, MatchField.IN_PORT, MatchField.VLAN_VID,
57  MatchField.IP_PROTO
58  );
59 
60  private Map<String, Object> buildFlowMatch(final Match match) {
61  final Map<String, Object> data = new HashMap<>();
62  //There is only one way to receive match by type
63  for (MatchField<? extends OFValueType> field : KNOWN_MATCHES) {
64  OFValueType value = match.get(field);
65  if (Objects.nonNull(value)) {
66  data.put(field.getName(), value.toString());
67  }
68  }
69  return data;
70  }
71 
72  private Map<String, Object> buildFlowInstructions(final List<OFInstruction> instructions) {
73  Map<String, Object> data = new HashMap<>();
74  for (OFInstruction instruction : instructions) {
75  Map<String, Object> iData = new HashMap<>();
76  OFInstructionType instructionType = instruction.getType();
77  switch (instructionType) {
78  case APPLY_ACTIONS:
79  for (OFAction action : ((OFInstructionApplyActions) instruction).getActions()) {
80  OFActionType actionType = action.getType();
81  switch (actionType) {
82  case METER: // ver1.5
83  iData.put(actionType.toString(), ((OFActionMeter) action).getMeterId());
84  break;
85  case OUTPUT:
86  Optional.ofNullable(((OFActionOutput) action).getPort())
87  .ifPresent(port -> iData.put(actionType.toString(), port.toString()));
88  break;
89  case POP_VLAN:
90  iData.put(actionType.toString(), null);
91  break;
92  case PUSH_VLAN:
93  Optional.ofNullable(((OFActionPushVlan) action).getEthertype())
94  .ifPresent(ethType -> iData.put(actionType.toString(), ethType.toString()));
95  break;
96  case SET_FIELD:
97  OFOxm<?> setFieldAction = ((OFActionSetField) action).getField();
98  iData.put(actionType.toString(), String.format("%s->%s",
99  setFieldAction.getValue(), setFieldAction.getMatchField().getName()));
100  break;
101  default:
102  iData.put(actionType.toString(), "could not parse");
103  break;
104  }
105  }
106  break;
107  case METER:
108  OFInstructionMeter action = ((OFInstructionMeter) instruction);
109  iData.put(instructionType.toString(), action.getMeterId());
110  break;
111  default:
112  iData.put(instructionType.toString(), "could not parse");
113  break;
114  }
115  data.put(instruction.getType().name(), iData);
116  }
117  return data;
118  }
119 
120  private Map<String, Object> buildFlowStat(final OFFlowStatsEntry entry) {
121  Map<String, Object> data = new HashMap<>();
122  data.put("version", entry.getVersion());
123  data.put("duration-nsec", entry.getDurationNsec());
124  data.put("duration-sec", entry.getDurationSec());
125  data.put("hard-timeout", entry.getHardTimeout());
126  data.put("idle-timeout", entry.getIdleTimeout());
127  data.put("priority", entry.getPriority());
128  data.put("byte-count", entry.getByteCount().getValue());
129  data.put("packet-count", entry.getPacketCount().getValue());
130  data.put("flags", entry.getFlags());
131  data.put("cookie", Long.toHexString(entry.getCookie().getValue()));
132  data.put("table-id", entry.getTableId().getValue());
133  data.put("match", buildFlowMatch(entry.getMatch()));
134  data.put("instructions", buildFlowInstructions(entry.getInstructions()));
135  return data;
136  }
137 
138  @Get("json")
139  @SuppressWarnings("unchecked")
140  public Map<String, Object> getFlows() {
141  Map<String, Object> response = new HashMap<>();
142  String switchId = (String) this.getRequestAttributes().get("switch_id");
143  LOGGER.debug("Get flows for switch: {}", switchId);
144  ISwitchManager switchManager = (ISwitchManager) getContext().getAttributes()
145  .get(ISwitchManager.class.getCanonicalName());
146 
147  try {
148  List<OFFlowStatsEntry> flowEntries = switchManager.dumpFlowTable(DatapathId.of(switchId));
149  LOGGER.debug("OF_STATS: {}", flowEntries);
150 
151  if (flowEntries != null) {
152  for (OFFlowStatsEntry entry : flowEntries) {
153  String key = String.format("flow-0x%s",
154  Long.toHexString(entry.getCookie().getValue()).toUpperCase());
155  response.put(key, buildFlowStat(entry));
156  }
157  }
158  } catch (IllegalArgumentException exception) {
159  String messageString = "No such switch";
160  LOGGER.error("{}: {}", messageString, switchId, exception);
161  MessageError responseMessage = new MessageError(CorrelationContext.getId(), System.currentTimeMillis(),
162  ErrorType.PARAMETERS_INVALID.toString(), messageString, exception.getMessage());
163  response.putAll(MAPPER.convertValue(responseMessage, Map.class));
164  }
165  return response;
166  }
167 }
static final ObjectMapper MAPPER
Definition: Utils.java:31
value
Definition: nodes.py:62
List< OFFlowStatsEntry > dumpFlowTable(final DatapathId dpid)