ROFL-pipeline  v0.6.0dev
of1x_pipeline.c
1 #include "of1x_pipeline.h"
2 #include "of1x_instruction.h"
3 #include "of1x_flow_table.h"
4 #include "of1x_group_table.h"
5 #include "of1x_timers.h"
6 #include "../../../platform/lock.h"
7 #include "../../../platform/likely.h"
8 #include "../../../platform/memory.h"
9 #include "../../../platform/atomic_operations.h"
10 #include "../of1x_async_events_hooks.h"
11 #include "matching_algorithms/matching_algorithms.h"
12 #include "../of1x_switch.h"
13 
14 #include "../../../util/logging.h"
15 
16 /*
17 * This file implements the abstraction of a pipeline
18 */
19 
20 /* Management operations */
21 rofl_result_t __of1x_init_pipeline(struct of1x_switch* sw, const unsigned int num_of_tables, enum of1x_matching_algorithm_available* list){
22 
23  int i;
24  of1x_pipeline_t* pipeline = &sw->pipeline;
25 
26  if(!sw)
27  return ROFL_FAILURE;
28 
29  //Verify params
30  if( ! (num_of_tables <= OF1X_MAX_FLOWTABLES && num_of_tables > 0) )
31  return ROFL_FAILURE;
32 
33 
34  //Fill in
35  pipeline->sw = sw;
36  pipeline->num_of_tables = num_of_tables;
37  pipeline->num_of_buffers = 0; //Should be filled in the post_init hook
38 
39 
40  //Allocate tables and initialize
41  pipeline->tables = (of1x_flow_table_t*)platform_malloc_shared(sizeof(of1x_flow_table_t)*num_of_tables);
42 
43  if(!pipeline->tables){
44  return ROFL_FAILURE;
45  }
46 
47  for(i=0;i<num_of_tables;i++){
48 
49  if( (list[i] >= of1x_matching_algorithm_count) ||
50  (__of1x_init_table(pipeline, &pipeline->tables[i],i, list[i]) != ROFL_SUCCESS)
51  ){
52  ROFL_PIPELINE_ERR("Creation of table #%d has failed in logical switch %s. This might be due to an invalid Matching Algorithm or that the system has run out of memory. Aborting Logical Switch creation\n",i,sw->name);
53  //Destroy already allocated tables
54  for(--i; i>=0; i--){
55  __of1x_destroy_table(&pipeline->tables[i]);
56  }
57 
58  platform_free_shared(pipeline->tables);
59  return ROFL_FAILURE;
60  }
61  }
62 
63  /*
64  * Setting default capabilities and miss_send_lent. driver can afterwards
65  * modify them at its will, via the hook.
66  */
67 
68  //Set datapath capabilities
69  pipeline->capabilities = OF1X_CAP_FLOW_STATS |
70  OF1X_CAP_TABLE_STATS |
71  OF1X_CAP_PORT_STATS |
72  OF1X_CAP_GROUP_STATS |
73  //OF1X_CAP_IP_REASM |
74  OF1X_CAP_QUEUE_STATS;
75  //OF1X_CAP_ARP_MATCH_IP;
76 
77  //TODO: Evaluate if OF1X_CAP_PORT_BLOCKED should be added by default
78 
79  //Set MISS-SEND length to default
80  pipeline->miss_send_len = OF1X_DEFAULT_MISS_SEND_LEN;
81 
82  //init groups
83  pipeline->groups = of1x_init_group_table(pipeline);
84 
85  return ROFL_SUCCESS;
86 }
87 
88 rofl_result_t __of1x_destroy_pipeline(of1x_pipeline_t* pipeline){
89 
90  int i;
91 
92  //destrouy groups
93  of1x_destroy_group_table(pipeline->groups);
94 
95  for(i=0; i<pipeline->num_of_tables; i++){
96  //We don't care about errors here, maybe add trace TODO
97  __of1x_destroy_table(&pipeline->tables[i]);
98  }
99 
100  //Now release table resources (allocated as single block)
101  platform_free_shared(pipeline->tables);
102 
103  return ROFL_SUCCESS;
104 }
105 
106 //Purge of all entries in the pipeline (reset)
107 rofl_result_t __of1x_purge_pipeline_entries(of1x_pipeline_t* pipeline){
108 
109  unsigned int i;
110  rofl_result_t result = ROFL_SUCCESS;
111  of1x_flow_entry_t* flow_entry;
112  of1x_group_table_t* group_entry;
113 
114  //Create empty entries
115  flow_entry = of1x_init_flow_entry(false);
116  group_entry = of1x_init_group_table(pipeline);
117 
118  if( unlikely(flow_entry==NULL) )
119  return ROFL_FAILURE;
120  if( unlikely(group_entry==NULL) ){
121  of1x_destroy_flow_entry(flow_entry);
122  return ROFL_FAILURE;
123  }
124 
125  //Purge flow_mods
126  for(i=OF1X_FIRST_FLOW_TABLE_INDEX; i < pipeline->num_of_tables ; i++){
127  //Purge flow_mods
128  if(of1x_remove_flow_entry_table(pipeline, i, flow_entry, NOT_STRICT, OF1X_PORT_ANY, OF1X_GROUP_ANY) != ROFL_SUCCESS){
129 
130  result = ROFL_FAILURE;
131  break;
132  }
133  }
134 
135  //Purge group mods
136  if(result == ROFL_SUCCESS){
137  if(of1x_group_delete(pipeline, group_entry, OF1X_GROUP_ANY) != ROFL_OF1X_GM_OK)
138  result = ROFL_FAILURE;
139  }
140 
141  //Destroy entries
142  of1x_destroy_flow_entry(flow_entry);
143  of1x_destroy_group_table(group_entry);
144 
145  return result;
146 }
147 
148 //Set the default tables(flow and group tables) configuration according to the new version
149 rofl_result_t __of1x_set_pipeline_tables_defaults(of1x_pipeline_t* pipeline, of_version_t version){
150 
151  unsigned int i;
152 
153  //Reset table defaults according to specific version
154  for(i=OF1X_FIRST_FLOW_TABLE_INDEX; i < pipeline->num_of_tables ; i++){
155  switch(version){
156  case OF_VERSION_10:
157  __of10_set_table_defaults(&pipeline->tables[i]);
158  break;
159  case OF_VERSION_12:
160  __of12_set_table_defaults(&pipeline->tables[i]);
161  __of12_set_group_table_defaults(pipeline->groups);
162  break;
163  case OF_VERSION_13:
164  __of13_set_table_defaults(&pipeline->tables[i]);
165  __of13_set_group_table_defaults(pipeline->groups);
166  break;
167  default:
168  return ROFL_FAILURE;
169 
170  }
171  }
172 
173  return ROFL_SUCCESS;
174 }
175 
176 
177 
178 //
179 // Snapshots
180 //
181 
182 //Creates a snapshot of the running pipeline of an LSI
183 rofl_result_t __of1x_pipeline_get_snapshot(of1x_pipeline_t* pipeline, of1x_pipeline_snapshot_t* sn){
184 
185  int i;
187 
188  //Cleanup stuff coming from the cloning process
189  sn->sw = NULL;
190 
191  //Allocate tables and initialize
192  sn->tables = (of1x_flow_table_t*)platform_malloc_shared(sizeof(of1x_flow_table_t)*pipeline->num_of_tables);
193 
194  if(!sn->tables)
195  return ROFL_FAILURE;
196 
197  //Copy contents of the tables and remove references
198  memcpy(sn->tables, pipeline->tables, sizeof(of1x_flow_table_t)*pipeline->num_of_tables);
199 
200  //Snapshot tables tables
201  for(i=0;i<pipeline->num_of_tables;i++){
203 
204  t = &sn->tables[i];
205 
206  //Consolidate stats
207  __of1x_stats_table_consolidate(&t->stats, &c);
208 
209  //Memset to 0
210  memset(&t->stats,0,sizeof(of1x_stats_table_t));
211 
212  //Assign consolidated
213  t->stats.s.counters = c;
214 
215  t->pipeline = t->rwlock = t->mutex = t->matching_aux[0] = t->matching_aux[1] = NULL;
216 
217 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
218 #else
219  t->timers = NULL;
220 #endif
221  }
222 
223  //TODO: deep entry copy?
224  sn->num_of_tables = pipeline->num_of_tables;
225  sn->num_of_buffers = pipeline->num_of_buffers;
226  sn->capabilities = pipeline->capabilities;
227  sn->miss_send_len = pipeline->miss_send_len;
228 
229  //Allocate GROUPS and initialize
231 
232  platform_rwlock_rdlock(pipeline->groups->rwlock);
233 
234  //Copy contents (config & num of entries)
235  memcpy(sn->groups, pipeline->groups, sizeof(of1x_group_table_t));
236 
237  platform_rwlock_rdunlock(pipeline->groups->rwlock);
238 
239  //clean unnecessary information
240  sn->groups->head = sn->groups->tail = sn->groups->rwlock = NULL;
241 
242  return ROFL_SUCCESS;
243 }
244 
245 //Destroy a previously getd snapshot
246 void __of1x_pipeline_destroy_snapshot(of1x_pipeline_snapshot_t* sn){
247  //Release tables memory
248  platform_free_shared(sn->tables);
249  platform_free_shared(sn->groups);
250 }
of1x_flow_entry_t * of1x_init_flow_entry(bool notify_removal)
Create an empty flow entry.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction.
void platform_rwlock_rdlock(platform_rwlock_t *rwlock)
Performs a read-lock over the platform_rwlock_t mutex platform_mutex_init().
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
OpenFlow-enabled v1.0, 1.2 and 1.3.2 switch abstraction.
Definition: of1x_switch.h:28
void platform_rwlock_rdunlock(platform_rwlock_t *rwlock)
Performs a read-unlock over the platform_rwlock_t mutex platform_mutex_init().
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
rofl_result_t of1x_remove_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t *entry, const enum of1x_flow_removal_strictness strict, uint32_t out_port, uint32_t out_group)
Removes a flow_entry from the table.
OpenFlow v1.X instructions.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
of1x_group_table_t * of1x_init_group_table(struct of1x_pipeline *pipeline)
Initializes the group table.
void of1x_destroy_group_table(of1x_group_table_t *gt)
Destroys the group table.
OpenFlow v1.0, 1.2 and 1.3.2 timers subsystem.
rofl_of1x_gm_result_t of1x_group_delete(of1x_pipeline_t *pipeline, of1x_group_table_t *gt, uint32_t id)
Deletes a group of the table.
matching_auxiliary_t * matching_aux[2]
Place-holder to allow matching algorithms keep its own state.
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...
rofl_result_t of1x_destroy_flow_entry(of1x_flow_entry_t *entry)
Destroy the flow entry, including stats, instructions and actions.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction data structure.
Definition: of1x_pipeline.h:50
void platform_free_shared(void *data)
Frees a chunk of dynamic memory previously allocated with platform_malloc_shared().
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.