blob: 3b750ae35df0b42ba7ddfef67ee11a20891fdcd2 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
2* Copyright 2011, Big Switch Networks, Inc.
3* Originally created by David Erickson, Stanford University
4*
5* Licensed under the Apache License, Version 2.0 (the "License"); you may
6* not use this file except in compliance with the License. You may obtain
7* a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14* License for the specific language governing permissions and limitations
15* under the License.
16**/
17
18package net.floodlightcontroller.staticflowentry.web;
19
20import java.io.IOException;
21import java.util.Map;
22
23import org.restlet.resource.Delete;
24import org.restlet.resource.Post;
25import org.restlet.resource.ServerResource;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29
30import net.floodlightcontroller.core.annotations.LogMessageCategory;
31import net.floodlightcontroller.core.annotations.LogMessageDoc;
32import net.floodlightcontroller.staticflowentry.StaticFlowEntries;
33import net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher;
34import net.floodlightcontroller.storage.IStorageSourceService;
35
36/**
37 * Pushes a static flow entry to the storage source
38 * @author alexreimers
39 *
40 */
41@LogMessageCategory("Static Flow Pusher")
42public class StaticFlowEntryPusherResource extends ServerResource {
43 protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusherResource.class);
44
45 /**
46 * Checks to see if the user matches IP information without
47 * checking for the correct ether-type (2048).
48 * @param rows The Map that is a string representation of
49 * the static flow.
50 * @reutrn True if they checked the ether-type, false otherwise
51 */
52 private boolean checkMatchIp(Map<String, Object> rows) {
53 boolean matchEther = false;
54 String val = (String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE);
55 if (val != null) {
56 int type = 0;
57 // check both hex and decimal
58 if (val.startsWith("0x")) {
59 type = Integer.parseInt(val.substring(2), 16);
60 } else {
61 try {
62 type = Integer.parseInt(val);
63 } catch (NumberFormatException e) { /* fail silently */}
64 }
65 if (type == 2048) matchEther = true;
66 }
67
68 if ((rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) ||
69 rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_SRC) ||
70 rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_PROTO) ||
71 rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_TOS)) &&
72 (matchEther == false))
73 return false;
74
75 return true;
76 }
77
78 /**
79 * Takes a Static Flow Pusher string in JSON format and parses it into
80 * our database schema then pushes it to the database.
81 * @param fmJson The Static Flow Pusher entry in JSON format.
82 * @return A string status message
83 */
84 @Post
85 @LogMessageDoc(level="ERROR",
86 message="Error parsing push flow mod request: {request}",
87 explanation="An invalid request was sent to static flow pusher",
88 recommendation="Fix the format of the static flow mod request")
89 public String store(String fmJson) {
90 IStorageSourceService storageSource =
91 (IStorageSourceService)getContext().getAttributes().
92 get(IStorageSourceService.class.getCanonicalName());
93
94 Map<String, Object> rowValues;
95 try {
96 rowValues = StaticFlowEntries.jsonToStorageEntry(fmJson);
97 String status = null;
98 if (!checkMatchIp(rowValues)) {
99 status = "Warning! Pushing a static flow entry that matches IP " +
100 "fields without matching for IP payload (ether-type 2048) will cause " +
101 "the switch to wildcard higher level fields.";
102 log.error(status);
103 } else {
104 status = "Entry pushed";
105 }
106 storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, rowValues);
107 return ("{\"status\" : \"" + status + "\"}");
108 } catch (IOException e) {
109 log.error("Error parsing push flow mod request: " + fmJson, e);
110 e.printStackTrace();
111 return "{\"status\" : \"Error! Could not parse flod mod, see log for details.\"}";
112 }
113 }
114
115 @Delete
116 @LogMessageDoc(level="ERROR",
117 message="Error deleting flow mod request: {request}",
118 explanation="An invalid delete request was sent to static flow pusher",
119 recommendation="Fix the format of the static flow mod request")
120 public String del(String fmJson) {
121 IStorageSourceService storageSource =
122 (IStorageSourceService)getContext().getAttributes().
123 get(IStorageSourceService.class.getCanonicalName());
124 String fmName = null;
125 if (fmJson == null) {
126 return "{\"status\" : \"Error! No data posted.\"}";
127 }
128 try {
129 fmName = StaticFlowEntries.getEntryNameFromJson(fmJson);
130 if (fmName == null) {
131 return "{\"status\" : \"Error deleting entry, no name provided\"}";
132 }
133 } catch (IOException e) {
134 log.error("Error deleting flow mod request: " + fmJson, e);
135 e.printStackTrace();
136 return "{\"status\" : \"Error deleting entry, see log for details\"}";
137 }
138
139 storageSource.deleteRowAsync(StaticFlowEntryPusher.TABLE_NAME, fmName);
140 return "{\"status\" : \"Entry " + fmName + " deleted\"}";
141 }
142}