ROFL-pipeline  v0.6.0dev
of1x_instruction.c
1 #include "of1x_instruction.h"
2 #include "of1x_pipeline.h"
3 #include "../of1x_switch.h"
4 #include "of1x_flow_entry.h"
5 #include "of1x_group_table.h"
6 
7 #include <assert.h>
8 #include "../../../util/logging.h"
9 #include "../../../platform/likely.h"
10 #include "../../../platform/memory.h"
11 
12 /* Instructions init and destroyers */
13 static void __of1x_init_instruction(of1x_instruction_t* inst, of1x_instruction_type_t type, of1x_action_group_t* apply_actions, of1x_write_actions_t* write_actions, of1x_write_metadata_t* write_metadata, unsigned int go_to_table){
14 
15  if( unlikely(type==OF1X_IT_NO_INSTRUCTION) )
16  return;
17 
18  inst->type = type; //mark that is present
19 
20  inst->apply_actions = apply_actions;
21  inst->write_actions = write_actions;
22 
23  if(write_metadata)
24  inst->write_metadata = *write_metadata;
25 
26  if(type == OF1X_IT_GOTO_TABLE)
27  inst->go_to_table = go_to_table;
28 
29 }
30 
31 static void __of1x_destroy_instruction(of1x_instruction_t* inst){
32  //Check if empty
33  if(inst->type == OF1X_IT_NO_INSTRUCTION)
34  return;
35 
36  if(inst->apply_actions)
37  of1x_destroy_action_group(inst->apply_actions);
38 
39  if(inst->write_actions)
40  __of1x_destroy_write_actions(inst->write_actions);
41 }
42 
43 /* Instruction groups init and destroy */
44 void __of1x_init_instruction_group(of1x_instruction_group_t* group){
45 
46  platform_memset(group,0,sizeof(of1x_instruction_group_t));
47 }
48 
49 void __of1x_destroy_instruction_group(of1x_instruction_group_t* group){
50 
51  unsigned int i;
52 
53  for(i=0;i<OF1X_IT_MAX;i++)
54  __of1x_destroy_instruction(&group->instructions[i]);
55 
56  group->num_of_instructions=0;
57 }
58 
59 //Removal of instruction from the group.
61 
62  __of1x_destroy_instruction(&group->instructions[type]);
63  group->num_of_instructions--;
64 }
65 
66 //Addition of instruction to group
67 void of1x_add_instruction_to_group(of1x_instruction_group_t* group, of1x_instruction_type_t type, of1x_action_group_t* apply_actions, of1x_write_actions_t* write_actions, of1x_write_metadata_t* write_metadata, unsigned int go_to_table){
68 
69  if(group->instructions[type].type != OF1X_IT_NO_INSTRUCTION)
71 
72  __of1x_init_instruction(&group->instructions[type], type, apply_actions, write_actions, write_metadata, go_to_table);
73  group->num_of_instructions++;
74 
75 
76  //Note: Num of actions and has_multiple_outputs are calculated during validation of the flow, since
77  //they depend on GROUPS which may not exist at this point and we don't know in which LSI will the
78  //flow be installed/modified/deleted
79 }
80 
81 
82 //Update instructions
83 rofl_result_t __of1x_update_instructions(of1x_instruction_group_t* group, of1x_instruction_group_t* new_group){
84 
85 
86  //Apply Actions
87  if(__of1x_update_apply_actions(&group->instructions[OF1X_IT_APPLY_ACTIONS].apply_actions, new_group->instructions[OF1X_IT_APPLY_ACTIONS].apply_actions)!=ROFL_SUCCESS)
88  return ROFL_FAILURE;
89 
90  //Make sure apply actions inst is marked as NULL, so that is not released
91  platform_memset(&new_group->instructions[OF1X_IT_APPLY_ACTIONS],0,sizeof(of1x_instruction_t));
92 
93  //Write actions
94  if(__of1x_update_write_actions(&group->instructions[OF1X_IT_WRITE_ACTIONS].write_actions, new_group->instructions[OF1X_IT_WRITE_ACTIONS].write_actions) != ROFL_SUCCESS)
95  return ROFL_FAILURE;
96 
97  //Make sure write actions inst is marked as NULL, so that is not freed
98  platform_memset(&new_group->instructions[OF1X_IT_WRITE_ACTIONS],0,sizeof(of1x_instruction_t));
99 
100 
101  //Static ones
102  //TODO: METADATA && EXPERIMENTER
103 
104  //Static stuff
105  group->instructions[OF1X_IT_CLEAR_ACTIONS] = new_group->instructions[OF1X_IT_CLEAR_ACTIONS];
106  group->instructions[OF1X_IT_GOTO_TABLE] = new_group->instructions[OF1X_IT_GOTO_TABLE];
107 
108 
109  //Static stuff
110  group->num_of_instructions = new_group->num_of_instructions;
111 
112  return ROFL_SUCCESS;
113 }
114 
115 /* Check whether instructions contain group */
116 bool __of1x_instructions_contain_group(of1x_flow_entry_t *const entry, const unsigned int group_id){
117 
118  return __of1x_write_actions_has(entry->inst_grp.instructions[OF1X_IT_WRITE_ACTIONS].write_actions,OF1X_AT_GROUP,group_id)
119  || __of1x_apply_actions_has(entry->inst_grp.instructions[OF1X_IT_APPLY_ACTIONS].apply_actions,OF1X_AT_GROUP,group_id);
120 }
121 
122 
123 //Copy (clone) instructions: TODO evaluate if is necessary to check for errors
124 void __of1x_copy_instruction_group(of1x_instruction_group_t* origin, of1x_instruction_group_t* dest){
125 
126  unsigned int i;
127 
128  for(i=0;i<OF1X_IT_MAX;i++){
129 
130  //Check all instructions in order
131  switch(origin->instructions[i].type){
132 
133  case OF1X_IT_CLEAR_ACTIONS:
134  case OF1X_IT_EXPERIMENTER:
135  case OF1X_IT_WRITE_METADATA:
136  case OF1X_IT_GOTO_TABLE:
137  dest->instructions[i] = origin->instructions[i];
138  break;
139 
140  case OF1X_IT_APPLY_ACTIONS:
141  dest->instructions[i] = origin->instructions[i];
142  dest->instructions[i].apply_actions = __of1x_copy_action_group(origin->instructions[i].apply_actions);
143  break;
144  case OF1X_IT_WRITE_ACTIONS:
145  dest->instructions[i] = origin->instructions[i];
146  dest->instructions[i].write_actions = __of1x_copy_write_actions(origin->instructions[i].write_actions);
147  break;
148 
149  default: //Empty instruction
150  dest->instructions[i] = origin->instructions[i];
151  break;
152  }
153  }
154 }
155 
156 
157 
158 void __of1x_dump_instructions(of1x_instruction_group_t group, bool raw_nbo){
159 
160  unsigned int i,has_write_actions=0, has_apply_actions=0;
161 
162  ROFL_PIPELINE_INFO("\t\tInst->> ");
163 
164  for(i=0;i<OF1X_IT_MAX;i++){
165 
166  //Check all instructions in order
167  switch(group.instructions[i].type){
168  case OF1X_IT_APPLY_ACTIONS:
169  ROFL_PIPELINE_INFO_NO_PREFIX(" APPLY, ");
170  has_apply_actions++;
171  break;
172  case OF1X_IT_CLEAR_ACTIONS:
173  ROFL_PIPELINE_INFO_NO_PREFIX(" CLEAR, ");
174  break;
175  case OF1X_IT_WRITE_ACTIONS:
176  ROFL_PIPELINE_INFO_NO_PREFIX(" WRITE, ");
177  has_write_actions++;
178  break;
179  case OF1X_IT_WRITE_METADATA:
180  ROFL_PIPELINE_INFO_NO_PREFIX(" WRITE-META(0x%"PRIx64":0x%"PRIx64"), ", group.instructions[i].write_metadata.metadata, group.instructions[i].write_metadata.metadata_mask);
181  break;
182  case OF1X_IT_EXPERIMENTER: //TODO:
183  ROFL_PIPELINE_INFO_NO_PREFIX(" EXP, ");
184  break;
185  case OF1X_IT_GOTO_TABLE:
186  ROFL_PIPELINE_INFO_NO_PREFIX(" GOTO(%u), ",group.instructions[i].go_to_table);
187  break;
188 
189  case OF1X_IT_METER: //TODO implement
190  assert(0);
191  break;
192 
193  case OF1X_IT_NO_INSTRUCTION: //Empty instruction
194  break;
195  }
196  }
197  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
198  if( has_apply_actions ){
199  ROFL_PIPELINE_INFO("\t\t\tAPP.ACTIONs:");
200  __of1x_dump_action_group(group.instructions[OF1X_IT_APPLY_ACTIONS].apply_actions, raw_nbo);
201  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
202  }
203  if( has_write_actions ){
204  ROFL_PIPELINE_INFO("\t\t\tWR.ACTIONs:");
205  __of1x_dump_write_actions(group.instructions[OF1X_IT_WRITE_ACTIONS].write_actions, raw_nbo);
206  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
207  }
208 }
209 
212 
213  return ( __of1x_write_actions_has(inst_grp->instructions[OF1X_IT_WRITE_ACTIONS].write_actions, type, value) ||
214  __of1x_apply_actions_has(inst_grp->instructions[OF1X_IT_APPLY_ACTIONS].apply_actions, type, value) );
215 }
216 
217 rofl_result_t __of1x_validate_instructions(of1x_instruction_group_t* inst_grp, of1x_pipeline_t* pipeline, unsigned int table_id){
218  int i, num_of_output_actions=0;
219  of1x_group_table_t *gt = pipeline->groups;
220  of_version_t version = pipeline->sw->of_ver;
221  of1x_flow_table_t* table = &pipeline->tables[table_id];
222 
223  //if there is a group action we should check that the group exists
224  for(i=0;i<OF1X_IT_MAX;i++){
225  switch(inst_grp->instructions[i].type){
226  case OF1X_IT_NO_INSTRUCTION:
227  continue;
228  break;
229 
230  case OF1X_IT_APPLY_ACTIONS:
231  if(__of1x_validate_action_group(&table->config.apply_actions, inst_grp->instructions[i].apply_actions, gt, false) != ROFL_SUCCESS)
232  return ROFL_FAILURE;
233  num_of_output_actions+=inst_grp->instructions[i].apply_actions->num_of_output_actions;
234  if( (version < inst_grp->instructions[i].apply_actions->ver_req.min_ver) ||
235  (version > inst_grp->instructions[i].apply_actions->ver_req.max_ver) )
236  return ROFL_FAILURE;
237 
238  break;
239 
240  case OF1X_IT_WRITE_ACTIONS:
241  //Fast check WRITE actions supported from 1.2
242  if( (version < OF_VERSION_12))
243  return ROFL_FAILURE;
244 
245  if(__of1x_validate_write_actions(&table->config.write_actions, inst_grp->instructions[i].write_actions, gt) != ROFL_SUCCESS)
246  return ROFL_FAILURE;
247 
248  num_of_output_actions+=inst_grp->instructions[i].write_actions->num_of_output_actions;
249  if( (version < inst_grp->instructions[i].write_actions->ver_req.min_ver) ||
250  (version > inst_grp->instructions[i].write_actions->ver_req.max_ver) )
251  return ROFL_FAILURE;
252 
253  break;
254 
255  case OF1X_IT_GOTO_TABLE:
256  break;
257  case OF1X_IT_WRITE_METADATA:
258  case OF1X_IT_CLEAR_ACTIONS:
259  case OF1X_IT_EXPERIMENTER:
260  //Fast check WRITE actions supported from 1.2
261  if( (version < OF_VERSION_12))
262  return ROFL_FAILURE;
263 
264  break;
265  case OF1X_IT_METER:
266  //Fast check WRITE actions supported from 1.3
267  if( (version < OF_VERSION_13))
268  return ROFL_FAILURE;
269 
270  break;
271 
272  }
273  }
274 
275  //update has multiple outputs flag
276  inst_grp->num_of_outputs = num_of_output_actions;
277 
278  return ROFL_SUCCESS;
279 }
of1x_packet_action_type_t
Actions over a packet as per defined in OF10, OF12, OF13.
Definition: of1x_action.h:89
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction.
bool __of1x_instruction_has(of1x_instruction_group_t *inst_grp, of1x_packet_action_type_t type, uint64_t value)
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
OpenFlow v1.X instructions.
void * platform_memset(void *src, int c, size_t length)
Sets 'c' to the whole chunk of memory.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
Write actions structure.
Definition: of1x_action.h:330
void of1x_destroy_action_group(of1x_action_group_t *group)
Destroy an action group.
Definition: of1x_action.c:480
void of1x_add_instruction_to_group(of1x_instruction_group_t *group, of1x_instruction_type_t type, of1x_action_group_t *apply_actions, of1x_write_actions_t *write_actions, of1x_write_metadata_t *write_metadata, unsigned int go_to_table)
Adds an instruction of the group.
Action group (apply-actions) structure.
Definition: of1x_action.h:303
OpenFlow v1.0, 1.2 and 1.3.2 flow entry abstraction.
void of1x_remove_instruction_from_the_group(of1x_instruction_group_t *group, of1x_instruction_type_t type)
Remove an instruction of the group.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction data structure.
Definition: of1x_pipeline.h:50
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.
of1x_instruction_type_t
Instruction type.