ROFL-pipeline  v0.6.0dev
of1x_switch.c
1 #include "of1x_switch.h"
2 
3 #include "../../switch_port.h"
4 #include "../../platform/lock.h"
5 #include "../../platform/memory.h"
6 #include "../../platform/likely.h"
7 #include "../../util/logging.h"
8 #include "../of_switch.h"
10 
11 /* Initializer and destructor */
12 of1x_switch_t* of1x_init_switch(const char* name, of_version_t version, uint64_t dpid, unsigned int num_of_tables, enum of1x_matching_algorithm_available* list){
13 
14  of1x_switch_t* sw;
16  if( unlikely(sw == NULL) )
17  return NULL;
18 
19  //Filling in values
20  sw->of_ver = version;
21  sw->dpid = dpid;
22  strncpy(sw->name,name,LOGICAL_SWITCH_MAX_LEN_NAME);
23 
24  //Initialize logical_ports
25  platform_memset(sw->logical_ports,0,sizeof(logical_switch_port_t)*LOGICAL_SWITCH_MAX_LOG_PORTS);
26  sw->num_of_ports=0;
27  sw->max_ports=LOGICAL_SWITCH_MAX_LOG_PORTS;
28 
29  //Initialize platform state to NULL
30  sw->platform_state=NULL;
31 
32  //Mutex
33  if(NULL == (sw->mutex = platform_mutex_init(NULL))){
35  return NULL;
36  }
37 
38  //Setup pipeline
39  if(__of1x_init_pipeline(sw, num_of_tables, list) != ROFL_SUCCESS){
41  return NULL;
42  }
43 
44  //Allow the platform to add specific configurations to the switch
45  if(platform_post_init_of1x_switch(sw) != ROFL_SUCCESS){
46  __of1x_destroy_pipeline(&sw->pipeline);
48  return NULL;
49  }
50 
51  return sw;
52 }
53 
54 rofl_result_t __of1x_destroy_switch(of1x_switch_t* sw){
55 
56  rofl_result_t result;
57 
58  //Allow the platform to do specific things before deletion
59  if(platform_pre_destroy_of1x_switch(sw) != ROFL_SUCCESS)
60  return ROFL_FAILURE;
61 
62  result = __of1x_destroy_pipeline(&sw->pipeline);
63 
64  //TODO: trace if result != SUCCESS
65  (void)result;
66 
67  //TODO: rwlock
68 
69  platform_mutex_destroy(sw->mutex);
71 
72  return ROFL_SUCCESS;
73 }
74 
75 //Reconfiguration of the pipeline
76 rofl_result_t __of1x_reconfigure_switch(of1x_switch_t* sw, of_version_t version){
77 
78  if(sw->of_ver == version)
79  return ROFL_SUCCESS;
80 
81  if(version == OF_VERSION_11)
82  return ROFL_FAILURE; //Early return OF11 NOT supported
83 
84  //Purge all entries(flow&groups) in the pipeline
85  if(__of1x_purge_pipeline_entries(&sw->pipeline) != ROFL_SUCCESS)
86  return ROFL_FAILURE;
87 
88  //Set the default tables(flow and group tables) configuration according to the new version
89  if(__of1x_set_pipeline_tables_defaults(&sw->pipeline, version) != ROFL_SUCCESS)
90  return ROFL_FAILURE;
91 
92  //Set switch to the new version and return
93  sw->of_ver = version;
94  return ROFL_SUCCESS;
95 }
96 
97 /* Port management */
98 rofl_result_t __of1x_attach_port_to_switch_at_port_num(of1x_switch_t* sw, unsigned int port_num, switch_port_t* port){
99 
100  if( unlikely(port==NULL) || unlikely(port_num==0) || unlikely(port_num >= LOGICAL_SWITCH_MAX_LOG_PORTS) )
101  return ROFL_FAILURE;
102 
103  //Allow single add/remove operation over the switch
104  platform_mutex_lock(sw->mutex);
105 
106  if(sw->logical_ports[port_num].attachment_state != LOGICAL_PORT_STATE_FREE){
107  platform_mutex_unlock(sw->mutex);
108  return ROFL_FAILURE;
109  }
110 
111  //Initialize logical port
112  sw->logical_ports[port_num].attachment_state = LOGICAL_PORT_STATE_ATTACHED;
113  sw->logical_ports[port_num].port = port;
114  sw->num_of_ports++;
115 
116  //Initialize also port structure
117  port->attached_sw = (of_switch_t*)sw;
118  port->of_port_num = port_num;
119 
120  //Return success
121  platform_mutex_unlock(sw->mutex);
122  return ROFL_SUCCESS;
123 }
124 
125 rofl_result_t __of1x_attach_port_to_switch(of1x_switch_t* sw, switch_port_t* port, unsigned int* port_num){
126  unsigned int i;
127 
128  if( unlikely(port==NULL) || unlikely(port->attached_sw!=NULL) )
129  return ROFL_FAILURE;
130 
131  //Allow single add/remove operation over the switch
132  platform_mutex_lock(sw->mutex);
133 
134  for(i=1;i<LOGICAL_SWITCH_MAX_LOG_PORTS;i++){
135  if(!sw->logical_ports[i].attachment_state){
136  //Initialize logical port
137  sw->logical_ports[i].attachment_state = LOGICAL_PORT_STATE_ATTACHED;
138  sw->logical_ports[i].port = port;
139  sw->num_of_ports++;
140  *port_num = i;
141 
142  //Initialize port
143  port->attached_sw = (of_switch_t*)sw;
144  port->of_port_num = i;
145 
146  //Return success
147  platform_mutex_unlock(sw->mutex);
148  return ROFL_SUCCESS;
149  }
150  }
151 
152  //No slots free
153  platform_mutex_unlock(sw->mutex);
154  return ROFL_FAILURE;
155 }
156 
157 rofl_result_t __of1x_detach_port_from_switch_by_port_num(of1x_switch_t* sw, unsigned int port_num){
158 
159  if( unlikely(port_num==0) )
160  return ROFL_FAILURE;
161 
162  //Allow single add/remove operation over the switch
163  platform_mutex_lock(sw->mutex);
164 
165  if(sw->logical_ports[port_num].attachment_state != LOGICAL_PORT_STATE_ATTACHED){
166  platform_mutex_unlock(sw->mutex);
167  return ROFL_FAILURE;
168  }
169 
170  //Free port
171  sw->logical_ports[port_num].port->attached_sw = NULL;
172  sw->logical_ports[port_num].port->of_port_num = 0;
173 
174  //sw->logical_ports[port_num].attachment_state = LOGICAL_PORT_STATE_DETACHED;
175  //Marking it as free so it can be reused
176  sw->logical_ports[port_num].attachment_state = LOGICAL_PORT_STATE_FREE;
177  sw->logical_ports[port_num].port = NULL;
178  sw->num_of_ports--;
179 
180  //return success
181  platform_mutex_unlock(sw->mutex);
182  return ROFL_SUCCESS;
183 }
184 
185 rofl_result_t __of1x_detach_port_from_switch(of1x_switch_t* sw, switch_port_t* port){
186 
187  unsigned int i;
188 
189  if( unlikely(port==NULL) )
190  return ROFL_FAILURE;
191 
192  //Allow single add/remove operation over the switch
193  platform_mutex_lock(sw->mutex);
194 
195  for(i=0;i<LOGICAL_SWITCH_MAX_LOG_PORTS;i++){
196  if(sw->logical_ports[i].port == port){
197 
198  //Free port
199  sw->logical_ports[i].port->attached_sw = NULL;
200  sw->logical_ports[i].port->of_port_num = 0;
201 
202  //Detach
203  //sw->logical_ports[i].attachment_state = LOGICAL_PORT_STATE_DETACHED;
204  //Marking it as free so it can be reused
205  sw->logical_ports[i].attachment_state = LOGICAL_PORT_STATE_FREE;
206  sw->logical_ports[i].port = NULL;
207  sw->num_of_ports--;
208 
209  platform_mutex_unlock(sw->mutex);
210  return ROFL_SUCCESS;
211  }
212  }
213 
214  //Not found
215  platform_mutex_unlock(sw->mutex);
216  return ROFL_FAILURE;
217 }
218 
219 rofl_result_t __of1x_detach_all_ports_from_switch(of1x_switch_t* sw){
220 
221  unsigned int i;
222 
223  //Allow single add/remove operation over the switch
224  platform_mutex_lock(sw->mutex);
225 
226  for(i=0;i<LOGICAL_SWITCH_MAX_LOG_PORTS;i++){
227 
228  //Mark port as non-attached to current sw
229  if(sw->logical_ports[i].port)
230  sw->logical_ports[i].port->attached_sw = NULL;
231 
232  //Detach
233  //sw->logical_ports[i].attachment_state = LOGICAL_PORT_STATE_DETACHED;
234  //Marking it as free so it can be reused
235  sw->logical_ports[i].attachment_state = LOGICAL_PORT_STATE_FREE;
236  sw->logical_ports[i].port = NULL;
237  }
238 
239  //Not found
240  platform_mutex_unlock(sw->mutex);
241  return ROFL_SUCCESS;
242 }
243 
244 /* Dumping */
245 void of1x_dump_switch(of1x_switch_t* sw, bool nbo){
246 
247  ROFL_PIPELINE_INFO("\n");
248  ROFL_PIPELINE_INFO("OpenFlow switch instance (%p)\n",sw);
249  ROFL_PIPELINE_INFO("========================\n");
250  ROFL_PIPELINE_INFO("Name: %s\n",sw->name);
251  ROFL_PIPELINE_INFO("OpenFlow version: %s\n", of_version_str[sw->of_ver]);
252  ROFL_PIPELINE_INFO("OpenFlow datapathid: 0x%" PRIx64 "\n",sw->dpid);
253 }
254 
256  int i;
257  of1x_dump_switch(sw, nbo);
258 
259  /* Dumping tables */
260  for(i=0;i<sw->pipeline.num_of_tables;i++)
261  of1x_dump_table(&sw->pipeline.tables[i], nbo);
262  ROFL_PIPELINE_INFO("--End of pipeline tables--\n");
263 
264  of1x_dump_group_table(sw->pipeline.groups, nbo);
265  ROFL_PIPELINE_INFO("--End of group table--\n\n");
266 }
267 
268 //
269 // Snapshots
270 //
271 
272 //Creates a snapshot of the running of LSI
273 of1x_switch_snapshot_t* __of1x_switch_get_snapshot(of1x_switch_t* sw){
274 
275  int i;
276 
277  //Allocate a snapshot
279 
280  if(!sn)
281  return NULL;
282 
283  //Serialize actions over the switch
284  platform_mutex_lock(sw->mutex);
285 
286  //Copy contents
287  memcpy(sn, sw, sizeof(of1x_switch_snapshot_t));
288 
289  //Cleanup the stuff that should not be exported
290  sn->mutex = sn->platform_state = NULL;
291 
292  //Snapshot ports
293  for(i=0;i<LOGICAL_SWITCH_MAX_LOG_PORTS;i++){
294  if(sw->logical_ports[i].port){
295  //Exists, snapshot it
296  sn->logical_ports[i].port = __switch_port_get_snapshot(sw->logical_ports[i].port);
297  if(!sn->logical_ports[i].port)
298  goto ports_only_snapshoting_error;
299  }
300  }
301 
302  //Snapshot pipeline
303  if(__of1x_pipeline_get_snapshot(&sw->pipeline, &sn->pipeline) != ROFL_SUCCESS)
304  goto pipeline_snapshoting_error;
305 
306  platform_mutex_unlock(sw->mutex);
307 
308  return sn;
309 
310 pipeline_snapshoting_error:
311  //There is no need to do nothing, since
312  //call should have already cleanup his own memory
313 ports_only_snapshoting_error:
314  //Delete snapshotted ports
315  for(;i>0;i--){
316  if(sn->logical_ports[i].port)
317  switch_port_destroy_snapshot(sn->logical_ports[i].port);
318  }
319 
320  platform_mutex_unlock(sw->mutex);
321 
322  //Free main snapshot
324 
325  return NULL;
326 }
327 
328 //Destroy a previously generated snapshot
329 void __of1x_switch_destroy_snapshot(of1x_switch_snapshot_t* sn){
330 
331  int i;
332 
333  //Let the pipeline destroy its state
334  __of1x_pipeline_destroy_snapshot(&sn->pipeline);
335 
336  //Destroy port snapshots
337  for(i=0;i<LOGICAL_SWITCH_MAX_LOG_PORTS;i++){
338  if(sn->logical_ports[i].port)
339  switch_port_destroy_snapshot(sn->logical_ports[i].port);
340  }
341 
342  //Free main snapshot
344 }
OpenFlow-enabled switch abstraction (version-indepedent part).
Definition: of_switch.h:55
void platform_mutex_lock(platform_mutex_t *mutex)
Locks the platform_mutex_t mutex.
OpenFlow-enabled v1.0, 1.2 and 1.3.2 switch abstraction.
Definition: of1x_switch.h:28
rofl_result_t platform_pre_destroy_of1x_switch(of1x_switch_t *sw)
Allows the user of the library to perform other platform related actions when a switch is about the b...
void switch_port_destroy_snapshot(switch_port_snapshot_t *port)
Destroy a switch port snapshot.
Definition: switch_port.c:195
void platform_mutex_unlock(platform_mutex_t *mutex)
Unlocks the platform_mutex_t mutex.
ROFL_BEGIN_DECLS rofl_result_t platform_post_init_of1x_switch(of1x_switch_t *sw)
Allows the user of the library to pre-configure the switch, as well as perform other platform related...
ROFL_BEGIN_DECLS platform_mutex_t * platform_mutex_init(void *params)
Allocates and initializes a mutex.
of1x_switch_t * of1x_init_switch(const char *name, of_version_t version, uint64_t dpid, unsigned int num_of_tables, enum of1x_matching_algorithm_available *list)
Creates an OpenFlow v1.0, 1.2 and 1.3.2 forwarding instance.
Definition: of1x_switch.c:12
void * platform_memset(void *src, int c, size_t length)
Sets 'c' to the whole chunk of memory.
Port abstraction.
Definition: switch_port.h:145
OpenFlow v1.0, 1.2 and 1.3.2 switch(fwd module) -> asynchronous event notification and hooks) ...
void platform_mutex_destroy(platform_mutex_t *mutex)
Destroys and deallocates a mutex previously inited by platform_mutex_init().
void of1x_dump_switch(of1x_switch_t *sw, bool nbo)
Dumps the OpenFlow v1.0, 1.2 and 1.3.2 forwarding instance, for debugging purposes.
Definition: of1x_switch.c:245
OpenFlow v1.0, 1.2 and 1.3.2 logical switch abstraction.
void * platform_malloc_shared(size_t length)
Allocates a chunk of dynamic memory of size length, which must be accessible (R/W) for all the thread...
void platform_free_shared(void *data)
Frees a chunk of dynamic memory previously allocated with platform_malloc_shared().
void of1x_full_dump_switch(of1x_switch_t *sw, bool nbo)
Dumps the OpenFlow v1.0, 1.2 and 1.3.2 forwarding instance, for debugging purposes.
Definition: of1x_switch.c:255