ROFL-pipeline  v0.6.0dev
of1x_flow_table.c
1 #include "of1x_flow_table.h"
2 
3 #include "../../../platform/likely.h"
4 #include "../../../platform/lock.h"
5 #include "../../../util/logging.h"
6 
7 #include "of1x_group_table.h"
8 #include "of1x_pipeline.h"
9 #include "of1x_action.h"
10 #include "of1x_match.h"
11 #include "../of1x_switch.h"
12 
13 
14 //Nice dumping strings
15 const char* __of1x_flow_table_miss_config_str[__OF1X_TABLE_MISS_MAX]={"CONTROLLER", "CONTINUE", "DROP", "INVALID"};
16 
17 /*
18 * OpenFlow table operations
19 *
20 * Assumptions:
21 * - A Table MUST always have entries ordered by NÂș of OF hits first, and for the priority field in second place
22 * - A Table contains no more than OF1X_MAX_NUMBER_OF_TABLE_ENTRIES
23 * -
24 */
25 
26 /*
27 * Table mgmt
28 */
29 
30 void __of10_set_table_defaults(of1x_flow_table_t* table){
31 
32  //Set default behaviour MISS Controller
33  //XXX: Original of10 was not not handling more than one table, why does
34  //the spec now have it?
35  table->default_action = OF1X_TABLE_MISS_CONTROLLER;
36 
37  /* Setting up basic characteristics of the table */
38  table->config.table_miss_config = 0x0; //No meaning in OF1.0
39 
40  //Match
41  bitmap128_clean(&table->config.match);
42  bitmap128_set(&table->config.match, OF1X_MATCH_IN_PORT);
43  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_DST);
44  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_SRC);
45  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_TYPE);
46  bitmap128_set(&table->config.match, OF1X_MATCH_VLAN_VID);
47  bitmap128_set(&table->config.match, OF1X_MATCH_VLAN_PCP);
48  bitmap128_set(&table->config.match, OF1X_MATCH_IP_DSCP);
49  bitmap128_set(&table->config.match, OF1X_MATCH_NW_PROTO);
50  bitmap128_set(&table->config.match, OF1X_MATCH_NW_SRC);
51  bitmap128_set(&table->config.match, OF1X_MATCH_NW_DST);
52  bitmap128_set(&table->config.match, OF1X_MATCH_TP_SRC); //Only for OF10
53  bitmap128_set(&table->config.match, OF1X_MATCH_TP_DST); //Only for OF10
54  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_CODE);
55  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_TYPE);
56  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_SID);
57  bitmap128_set(&table->config.match, OF1X_MATCH_PPP_PROT);
58  bitmap128_set(&table->config.match, OF1X_MATCH_GTP_MSG_TYPE);
59  bitmap128_set(&table->config.match, OF1X_MATCH_GTP_TEID);
60  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_VERSION);
61  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_PROT_TYPE);
62  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_KEY);
63 
64  //Wildcards
65  bitmap128_clean(&table->config.wildcards);
66  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ETH_DST);
67  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ETH_SRC);
68  bitmap128_set(&table->config.wildcards, OF1X_MATCH_NW_SRC);
69  bitmap128_set(&table->config.wildcards, OF1X_MATCH_NW_DST);
70  bitmap128_set(&table->config.wildcards, OF1X_MATCH_MPLS_LABEL);
71  bitmap128_set(&table->config.wildcards, OF1X_MATCH_GTP_TEID);
72 
73  //Apply actions
74  bitmap128_clean(&table->config.apply_actions);
75  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ETH_DST);
76  bitmap128_set(&table->config.apply_actions, OF1X_AT_COPY_TTL_IN);
77  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_VLAN);
78  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_PPPOE);
79  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_PPPOE);
80  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_VLAN);
81  bitmap128_set(&table->config.apply_actions, OF1X_AT_DEC_NW_TTL);
82  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_NW_TTL);
83  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_QUEUE);
84  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_DST);
85  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_SRC);
86  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_TYPE);
87  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_VLAN_VID);
88  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_VLAN_PCP);
89  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_PROTO);
90  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_SRC);
91  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_DST);
92  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_DSCP);
93  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_ECN);
94  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_PROTO);
95  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV4_SRC);
96  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV4_DST);
97  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TP_SRC);
98  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TP_DST);
99  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_CODE);
100  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_TYPE);
101  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_SID);
102  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPP_PROT);
103  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GTP_MSG_TYPE);
104  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GTP_TEID);
105  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_VERSION);
106  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_PROT_TYPE);
107  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_KEY);
108  bitmap128_set(&table->config.apply_actions, OF1X_AT_OUTPUT);
109 
110  //Write actions
111  bitmap128_clean(&table->config.write_actions); //Not supported in OF10
112 
113  //METADATA
114  table->config.metadata_match = 0x0; //Not supported in OF10
115  table->config.metadata_write = 0x0; //Not supported in OF10
116 
117  //Instructions
118  table->config.instructions = 0x0; //Not supported in OF10
119 
120 }
121 
122 void __of12_set_table_defaults(of1x_flow_table_t* table){
123 
124  //Set default behaviour MISS Controller
125  table->default_action = OF1X_TABLE_MISS_CONTROLLER;
126 
127  /* Setting up basic characteristics of the table */
128  table->config.table_miss_config = (1 << OF1X_TABLE_MISS_CONTROLLER) | (1 << OF1X_TABLE_MISS_CONTINUE) | (1 << OF1X_TABLE_MISS_DROP);
129 
130  //Match
131  bitmap128_clean(&table->config.match);
132  bitmap128_set(&table->config.match, OF1X_MATCH_IN_PORT);
133  bitmap128_set(&table->config.match, OF1X_MATCH_IN_PHY_PORT);
134  bitmap128_set(&table->config.match, OF1X_MATCH_METADATA);
135  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_DST);
136  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_SRC);
137  bitmap128_set(&table->config.match, OF1X_MATCH_ETH_TYPE);
138  bitmap128_set(&table->config.match, OF1X_MATCH_VLAN_VID);
139  bitmap128_set(&table->config.match, OF1X_MATCH_VLAN_PCP);
140  bitmap128_set(&table->config.match, OF1X_MATCH_ARP_OP);
141  bitmap128_set(&table->config.match, OF1X_MATCH_ARP_SHA);
142  bitmap128_set(&table->config.match, OF1X_MATCH_ARP_SPA);
143  bitmap128_set(&table->config.match, OF1X_MATCH_ARP_THA);
144  bitmap128_set(&table->config.match, OF1X_MATCH_ARP_TPA);
145  bitmap128_set(&table->config.match, OF1X_MATCH_IP_DSCP);
146  bitmap128_set(&table->config.match, OF1X_MATCH_IP_ECN);
147  bitmap128_set(&table->config.match, OF1X_MATCH_IP_PROTO);
148  bitmap128_set(&table->config.match, OF1X_MATCH_IPV4_SRC);
149  bitmap128_set(&table->config.match, OF1X_MATCH_IPV4_DST);
150  bitmap128_set(&table->config.match, OF1X_MATCH_TCP_SRC);
151  bitmap128_set(&table->config.match, OF1X_MATCH_TCP_DST);
152  bitmap128_set(&table->config.match, OF1X_MATCH_UDP_SRC);
153  bitmap128_set(&table->config.match, OF1X_MATCH_UDP_DST);
154  bitmap128_set(&table->config.match, OF1X_MATCH_SCTP_SRC);
155  bitmap128_set(&table->config.match, OF1X_MATCH_SCTP_DST);
156  bitmap128_set(&table->config.match, OF1X_MATCH_ICMPV4_TYPE);
157  bitmap128_set(&table->config.match, OF1X_MATCH_ICMPV4_CODE);
158  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_SRC);
159  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_DST);
160  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_FLABEL);
161  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_ND_TARGET);
162  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_ND_SLL);
163  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_ND_TLL);
164  bitmap128_set(&table->config.match, OF1X_MATCH_ICMPV6_CODE);
165  bitmap128_set(&table->config.match, OF1X_MATCH_ICMPV6_TYPE);
166  bitmap128_set(&table->config.match, OF1X_MATCH_MPLS_LABEL);
167  bitmap128_set(&table->config.match, OF1X_MATCH_MPLS_TC);
168  bitmap128_set(&table->config.match, OF1X_MATCH_MPLS_BOS);
169  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_CODE);
170  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_TYPE);
171  bitmap128_set(&table->config.match, OF1X_MATCH_PPPOE_SID);
172  bitmap128_set(&table->config.match, OF1X_MATCH_PPP_PROT);
173  bitmap128_set(&table->config.match, OF1X_MATCH_GTP_MSG_TYPE);
174  bitmap128_set(&table->config.match, OF1X_MATCH_GTP_TEID);
175  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_VERSION);
176  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_PROT_TYPE);
177  bitmap128_set(&table->config.match, OF1X_MATCH_GRE_KEY);
178 
179  //Wildcards
180  bitmap128_clean(&table->config.wildcards);
181  bitmap128_set(&table->config.wildcards, OF1X_MATCH_METADATA);
182  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ETH_DST);
183  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ETH_SRC);
184  bitmap128_set(&table->config.wildcards, OF1X_MATCH_VLAN_VID);
185  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ARP_SHA);
186  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ARP_SPA);
187  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ARP_THA);
188  bitmap128_set(&table->config.wildcards, OF1X_MATCH_ARP_TPA);
189  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV4_SRC);
190  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV4_DST);
191  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV6_SRC);
192  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV6_DST);
193  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV6_FLABEL);
194  bitmap128_set(&table->config.wildcards, OF1X_MATCH_GTP_TEID);
195 
196 
197  //Apply actions
198  bitmap128_clean(&table->config.apply_actions);
199  bitmap128_set(&table->config.apply_actions, OF1X_AT_COPY_TTL_IN);
200  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_VLAN);
201  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_MPLS);
202  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_GRE);
203  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_GTP);
204  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_PPPOE);
205  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_PPPOE);
206  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_GTP);
207  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_GRE);
208  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_MPLS);
209  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_VLAN);
210  bitmap128_set(&table->config.apply_actions, OF1X_AT_COPY_TTL_OUT);
211  bitmap128_set(&table->config.apply_actions, OF1X_AT_DEC_NW_TTL);
212  bitmap128_set(&table->config.apply_actions, OF1X_AT_DEC_MPLS_TTL);
213  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_MPLS_TTL);
214  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_NW_TTL);
215  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_QUEUE);
216  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_DST);
217  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_SRC);
218  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ETH_TYPE);
219  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_MPLS_LABEL);
220  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_MPLS_TC);
221  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_VLAN_VID);
222  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_VLAN_PCP);
223  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ARP_OPCODE);
224  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ARP_SHA);
225  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ARP_SPA);
226  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ARP_THA);
227  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ARP_TPA);
228  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_PROTO);
229  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_SRC);
230  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_NW_DST);
231  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_DSCP);
232  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_ECN);
233  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IP_PROTO);
234  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV4_SRC);
235  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV4_DST);
236  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_SRC);
237  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_DST);
238  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_FLABEL);
239  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_ND_TARGET);
240  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_ND_SLL);
241  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_ND_TLL);
242  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TCP_SRC);
243  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TCP_DST);
244  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_UDP_SRC);
245  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_UDP_DST);
246  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_SCTP_SRC);
247  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_SCTP_DST);
248  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TP_SRC);
249  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TP_DST);
250  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ICMPV4_TYPE);
251  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ICMPV4_CODE);
252  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ICMPV6_TYPE);
253  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_ICMPV6_CODE);
254  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_CODE);
255  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_TYPE);
256  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPPOE_SID);
257  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PPP_PROT);
258  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GTP_MSG_TYPE);
259  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GTP_TEID);
260  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_VERSION);
261  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_PROT_TYPE);
262  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_GRE_KEY);
263  bitmap128_set(&table->config.apply_actions, OF1X_AT_GROUP);
264  bitmap128_set(&table->config.apply_actions, OF1X_AT_EXPERIMENTER);
265  bitmap128_set(&table->config.apply_actions, OF1X_AT_OUTPUT);
266 
267  //Write actions
268  table->config.write_actions = table->config.apply_actions;
269 
270  //METADATA (full metadata support)
271  table->config.metadata_match = 0xFFFFFFFFFFFFFFFFULL;
272  table->config.metadata_write = 0xFFFFFFFFFFFFFFFFULL;
273 
274  //Instructions
275  table->config.instructions = (1 << OF1X_IT_APPLY_ACTIONS) |
276  (1 << OF1X_IT_CLEAR_ACTIONS) |
277  (1 << OF1X_IT_WRITE_ACTIONS) |
278  (1 << OF1X_IT_WRITE_METADATA) |
279  (1 << OF1X_IT_GOTO_TABLE);
280 }
281 
282 void __of13_set_table_defaults(of1x_flow_table_t* table){
283 
284  //Being lazy...
285  __of12_set_table_defaults(table);
286 
287  //Setting the default behaviour to drop accroding to the spec.
288  table->default_action = OF1X_TABLE_MISS_DROP;
289 
290  //Adding OF1.3 matches
291  bitmap128_set(&table->config.match, OF1X_MATCH_MPLS_BOS);
292 
293  bitmap128_set(&table->config.match, OF1X_MATCH_IPV6_EXTHDR);
294  bitmap128_set(&table->config.wildcards, OF1X_MATCH_IPV6_EXTHDR);
295 
296  bitmap128_set(&table->config.match, OF1X_MATCH_PBB_ISID);
297  bitmap128_set(&table->config.wildcards, OF1X_MATCH_PBB_ISID);
298 
299  bitmap128_set(&table->config.match, OF1X_MATCH_TUNNEL_ID);
300  bitmap128_set(&table->config.wildcards, OF1X_MATCH_TUNNEL_ID);
301 
302  //Adding OF1.3 actions
303 
304  bitmap128_set(&table->config.apply_actions, OF1X_AT_POP_PBB);
305  bitmap128_set(&table->config.apply_actions, OF1X_AT_PUSH_PBB);
306  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_MPLS_BOS);
307  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_PBB_ISID);
308  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_IPV6_EXTHDR);
309  bitmap128_set(&table->config.apply_actions, OF1X_AT_SET_FIELD_TUNNEL_ID);
310 
311  //Write actions
312  table->config.write_actions = table->config.apply_actions;
313 
314  //TODO: add METER instruction when implemented
315 
316 
317  //Instructions
318  table->config.instructions |= (1 << OF1X_IT_METER);
319 
320  table->config.table_miss_config = 0x0;
321 }
322 
323 
324 /* Initalizer. Table struct has been allocated by pipeline initializer. */
325 rofl_result_t __of1x_init_table(struct of1x_pipeline* pipeline, of1x_flow_table_t* table, const unsigned int table_index, const enum of1x_matching_algorithm_available algorithm){
326 
327  //Safety checks
328  if( unlikely(pipeline==NULL) || unlikely(table==NULL) )
329  return ROFL_FAILURE;
330 
331  //Initializing mutexes
332  table->mutex = platform_mutex_init(NULL);
333  if( unlikely(NULL==table->mutex) )
334  return ROFL_FAILURE;
335  table->rwlock = platform_rwlock_init(NULL);
336  if( unlikely(NULL==table->rwlock) )
337  return ROFL_FAILURE;
338 
339 #ifdef ROFL_PIPELINE_LOCKLESS
340  tid_init_presence_mask(&table->tid_presence_mask);
341 #endif
342 
343  table->pipeline = pipeline;
344  table->number = table_index;
345  table->entries = NULL;
346  table->num_of_entries = 0;
347  table->max_entries = OF1X_MAX_NUMBER_OF_TABLE_ENTRIES;
348 
349  //Set name
350  snprintf(table->name, OF1X_MAX_TABLE_NAME_LEN, "table%u", table_index);
351 
352  //Setting up the matching algorithm
353  if(! (algorithm < of1x_matching_algorithm_count)){
354  platform_mutex_destroy(table->mutex);
355  platform_rwlock_destroy(table->rwlock);
356  return ROFL_FAILURE;
357  }
358 
359  //Set algorithm
360  table->matching_algorithm = algorithm;
361 
362  //Auxiliary matching algorithm structs
363  table->matching_aux[0] = NULL;
364  table->matching_aux[1] = NULL;
365 
366  //Initializing timers. NOTE does that need to be done here or somewhere else?
367 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
368  if(__of1x_timer_group_static_init(table) != ROFL_SUCCESS){
369  platform_mutex_destroy(table->mutex);
370  platform_rwlock_destroy(table->rwlock);
371  return ROFL_FAILURE;
372  }
373 #else
374  table->timers = NULL;
375 #endif
376 
377  switch(pipeline->sw->of_ver){
378  case OF_VERSION_10:
379  __of10_set_table_defaults(table);
380  break;
381  case OF_VERSION_12:
382  __of12_set_table_defaults(table);
383  break;
384  case OF_VERSION_13:
385  __of13_set_table_defaults(table);
386  break;
387  default:
388  platform_mutex_destroy(table->mutex);
389  platform_rwlock_destroy(table->rwlock);
390  return ROFL_FAILURE;
391  }
392 
393  //Init stats
395 
396  //Allow matching algorithms to do stuff
397  if(of1x_matching_algorithms[table->matching_algorithm].init_hook){
398  rofl_result_t result;
399 
400  result = of1x_matching_algorithms[table->matching_algorithm].init_hook(table);
401 
402  if(result != ROFL_SUCCESS){
403  platform_mutex_destroy(table->mutex);
404  platform_rwlock_destroy(table->rwlock);
405  return result;
406  }
407  }
408 
409  return ROFL_SUCCESS;
410 }
411 
412 /* Destructor. Table object is freed by pipeline destructor */
413 rofl_result_t __of1x_destroy_table(of1x_flow_table_t* table){
414 
415  platform_mutex_lock(table->mutex);
416  platform_rwlock_wrlock(table->rwlock);
417 
418  //Let the matching algorithm destroy its own state
419  if(of1x_matching_algorithms[table->matching_algorithm].destroy_hook)
420  of1x_matching_algorithms[table->matching_algorithm].destroy_hook(table);
421 
422  platform_mutex_destroy(table->mutex);
423  platform_rwlock_destroy(table->rwlock);
424 
425  //Destroy timers
426 #if OF1X_TIMER_STATIC_ALLOCATION_SLOTS
428 #endif
429  //Destroy stats
431 
432  //Do NOT free table, since it was allocated in a single buffer in pipeline.c
433  return ROFL_SUCCESS;
434 }
435 
436 
437 /*
438 * Interfaces for generic add/remove flow entry
439 * Specific matchings may point them to their own routines, but they MUST always call
440 * of1x_[whatever]_flow_entry_table_imp in order to update the main tables
441 */
442 inline rofl_of1x_fm_result_t of1x_add_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t **const entry, bool check_overlap, bool reset_counts){
443 
444  rofl_of1x_fm_result_t result;
445  of1x_flow_table_t* table;
446 
447 #ifdef DEBUG
448  //Dump entry
449  ROFL_PIPELINE_INFO("[flowmod-add(%p)] Starting operation at switch %s(%p), table %u, with flags: %s %s\n", *entry, pipeline->sw->name, pipeline->sw, table_id, check_overlap ? "CHK_OVERLAP ": "", (reset_counts)? "RESET_COUNTERS":"" );
450  ROFL_PIPELINE_INFO("");
451  of1x_dump_flow_entry(*entry, false);
452 #endif
453  //Verify table_id
454  if(unlikely(table_id >= pipeline->num_of_tables)){
455  ROFL_PIPELINE_ERR("[flowmod-add(%p)] ERROR: invalid table id %u > switch max table id: %u\n", *entry, table_id, pipeline->num_of_tables-1);
456  assert(0);
457  return ROFL_OF1X_FM_FAILURE;
458  }
459 
460  table = &pipeline->tables[table_id];
461 
462  //Take rd lock over the grouptable (avoid deletion of groups while flow entry insertion)
463  platform_rwlock_rdlock(pipeline->groups->rwlock);
464 
465  //Verify entry
466  if(unlikely(__of1x_validate_flow_entry(*entry, pipeline, table_id) != ROFL_SUCCESS)){
467  //Release rdlock
468  platform_rwlock_rdunlock(pipeline->groups->rwlock);
469  ROFL_PIPELINE_INFO("[flowmod-add(%p)] FAILED validation. Ignoring...\n", *entry);
470  return ROFL_OF1X_FM_FAILURE;
471  }
472 
473 
474  //Perform insertion (node that in 1.0 operation ADD must always reset counters on overlap)
475  result = of1x_matching_algorithms[table->matching_algorithm].add_flow_entry_hook(table, *entry, check_overlap, reset_counts || ( pipeline->sw->of_ver == OF_VERSION_10 ));
476 
477  if(result != ROFL_OF1X_FM_SUCCESS){
478  //Release rdlock
479  platform_rwlock_rdunlock(pipeline->groups->rwlock);
480  ROFL_PIPELINE_INFO("[flowmod-add(%p)] FAILED, reason: %u\n", *entry, result);
481  return result;
482  }
483 
484  //Add timer
485  __of1x_add_timer(table, *entry);
486 
487  ROFL_PIPELINE_INFO("[flowmod-add(%p)] Succesful.\n", *entry);
488 
489  //Release rdlock
490  platform_rwlock_rdunlock(pipeline->groups->rwlock);
491 
492  //Was successful set the pointer to NULL
493  //so that is not further used outside the pipeline
494  *entry = NULL;
495 
496  //Return value
497  return result;
498 }
499 
500 
501 inline rofl_result_t of1x_modify_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t **const entry, const enum of1x_flow_removal_strictness strict, bool reset_counts){
502  rofl_result_t result;
503  of1x_flow_table_t* table;
504 
505 #ifdef DEBUG
506  //Dump entry
507  ROFL_PIPELINE_INFO("[flowmod-modify(%p)] Starting operation at switch %s(%p), table %u, with flags: %s %s\n", *entry, pipeline->sw->name, pipeline->sw, table_id, (strict) ? "STRICT ": "NOT STRICT", (reset_counts)? "RESET_COUNTERS":"" );
508  ROFL_PIPELINE_INFO("");
509  of1x_dump_flow_entry(*entry, false);
510 #endif
511 
512  //Verify table_id
513  if(table_id >= pipeline->num_of_tables){
514  ROFL_PIPELINE_ERR("[flowmod-modify(%p)] ERROR: invalid table id %u > switch max table id: %u\n", *entry, table_id, pipeline->num_of_tables-1);
515  assert(0);
516  return ROFL_FAILURE;
517  }
518 
519  table = &pipeline->tables[table_id];
520 
521  //Take rd lock over the grouptable (avoid deletion of groups while flow entry insertion)
522  platform_rwlock_rdlock(pipeline->groups->rwlock);
523 
524  //Verify entry
525  if(__of1x_validate_flow_entry(*entry, pipeline, table_id) != ROFL_SUCCESS){
526  //Release rdlock
527  platform_rwlock_rdunlock(pipeline->groups->rwlock);
528  ROFL_PIPELINE_INFO("[flowmod-modify(%p)] FAILED validation. Ignoring...\n", *entry);
529  return ROFL_FAILURE;
530  }
531 
532  //Perform insertion
533  result = of1x_matching_algorithms[table->matching_algorithm].modify_flow_entry_hook(table, *entry, strict, reset_counts);
534 
535  if(result != ROFL_SUCCESS){
536  //Release rdlock
537  platform_rwlock_rdunlock(pipeline->groups->rwlock);
538  ROFL_PIPELINE_INFO("[flowmod-modify(%p)] FAILED\n", *entry);
539  return result;
540  }
541 
542  ROFL_PIPELINE_INFO("[flowmod-modify(%p)] Succesful.\n", *entry);
543 
544  //Release rdlock
545  platform_rwlock_rdunlock(pipeline->groups->rwlock);
546 
547 
548  //Was successful set the pointer to NULL
549  //so that is not further used outside the pipeline
550  *entry = NULL;
551 
552  //Return value
553  return result;
554 }
555 
556 inline 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){
557 
558  of1x_flow_table_t* table;
559  rofl_result_t result;
560 
561 #ifdef DEBUG
562  //Dump entry
563  ROFL_PIPELINE_INFO("[flowmod-remove(%p)] Starting operation at switch %s(%p), table %u, %s, ", entry, pipeline->sw->name, pipeline->sw, table_id, (strict) ? "STRICT ": "NOT STRICT");
564 
565  if(out_port == OF1X_PORT_ANY){
566  ROFL_PIPELINE_INFO_NO_PREFIX("out_port: %s, ", "ANY");
567  }else{
568  ROFL_PIPELINE_INFO_NO_PREFIX("out_port: %u, ", out_port);
569  }
570  if(out_group == OF1X_GROUP_ANY){
571  ROFL_PIPELINE_INFO_NO_PREFIX("out_group: %s", "ANY");
572  }else{
573  ROFL_PIPELINE_INFO_NO_PREFIX("out_group: %u", out_group);
574  }
575  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
576  ROFL_PIPELINE_INFO("");
577  of1x_dump_flow_entry(entry, false);
578 #endif
579 
580  //Verify table_id
581  if(table_id >= pipeline->num_of_tables){
582  ROFL_PIPELINE_ERR("[flowmod-remove(%p)] ERROR: invalid table id %u > switch max table id: %u\n", entry, table_id, pipeline->num_of_tables-1);
583  assert(0);
584  return ROFL_FAILURE;
585  }
586 
587  //Verify entry
588  if(__of1x_validate_flow_entry(entry, pipeline, table_id) != ROFL_SUCCESS){
589  ROFL_PIPELINE_INFO("[flowmod-remove(%p)] FAILED validation. Ignoring...\n", entry);
590  return ROFL_FAILURE;
591  }
592 
593  //Recover table pointer
594  table = &pipeline->tables[table_id];
595 
596  result = of1x_matching_algorithms[table->matching_algorithm].remove_flow_entry_hook(table, entry, NULL, strict, out_port, out_group, OF1X_FLOW_REMOVE_DELETE, MUTEX_NOT_ACQUIRED);
597 
598 #ifdef DEBUG
599  if(result != ROFL_SUCCESS)
600  ROFL_PIPELINE_INFO("[flowmod-remove(%p)] FAILED\n", entry);
601  else
602  ROFL_PIPELINE_INFO("[flowmod-remove(%p)] Succesful.\n", entry);
603 #endif
604  return result;
605 
606 }
607 
608 //This API call should NOT be called from outside pipeline library
609 rofl_result_t __of1x_remove_specific_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t *const specific_entry, of1x_flow_remove_reason_t reason, of1x_mutex_acquisition_required_t mutex_acquired){
610  of1x_flow_table_t* table;
611 
612  //Verify table_id
613  if(table_id >= pipeline->num_of_tables)
614  return ROFL_FAILURE;
615 
616  //Recover table pointer
617  table = &pipeline->tables[table_id];
618 
619  return of1x_matching_algorithms[table->matching_algorithm].remove_flow_entry_hook(table, NULL, specific_entry, STRICT, OF1X_PORT_ANY, OF1X_GROUP_ANY, reason, mutex_acquired);
620 }
621 
622 /* Dump methods */
623 void of1x_dump_table(of1x_flow_table_t* table, bool raw_nbo){
624  of1x_flow_entry_t* entry;
625  int i;
626 
628 
629  //Consolidate stats
630  __of1x_stats_table_consolidate(&table->stats, &c);
631 
632  ROFL_PIPELINE_INFO("\n"); //This is done in purpose
633  ROFL_PIPELINE_INFO("Dumping table # %u (%p). Default action: %s, num. of entries: %d, ma: %u statistics {looked up: %u, matched: %u}\n", table->number, table, __of1x_flow_table_miss_config_str[table->default_action],table->num_of_entries, table->matching_algorithm, c.lookup_count, c.matched_count);
634 
635  if(!table->entries){
636  ROFL_PIPELINE_INFO("\t[*] No entries\n");
637  return;
638  }
639  for(entry=table->entries, i=0;entry!=NULL;entry=entry->next,i++){
640  ROFL_PIPELINE_INFO("\t[%d] ",i);
641  of1x_dump_flow_entry(entry, raw_nbo);
642  }
643 
644  ROFL_PIPELINE_INFO("\t[*] No more entries...\n");
645 
646  if(of1x_matching_algorithms[table->matching_algorithm].dump_hook){
647  ROFL_PIPELINE_INFO("\tMatching algorithm %u specific state\n", table->matching_algorithm);
648  of1x_matching_algorithms[table->matching_algorithm].dump_hook(table, raw_nbo);
649  }
650  ROFL_PIPELINE_INFO("\n");
651 }
rofl_result_t of1x_modify_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t **const entry, const enum of1x_flow_removal_strictness strict, bool reset_counts)
Modify flow_entry(s) in the table.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction.
void __of1x_timer_group_static_destroy(struct of1x_flow_table *table)
of1x_timer_group_static_destroy Destroys the timers table initializes the values for the entry lists ...
Definition: of1x_timers.c:151
void platform_rwlock_rdlock(platform_rwlock_t *rwlock)
Performs a read-lock over the platform_rwlock_t mutex platform_mutex_init().
void platform_mutex_lock(platform_mutex_t *mutex)
Locks the platform_mutex_t mutex.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
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.
enum of1x_flow_remove_reason of1x_flow_remove_reason_t
Flow remove reasons (enum ofp_flow_removed_reason)
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.
static void bitmap128_clean(bitmap128_t *bitmap)
Set bitmap to 0.
Definition: bitmap.h:29
rofl_of1x_fm_result_t(* add_flow_entry_hook)(struct of1x_flow_table *const table, of1x_flow_entry_t *const entry, bool check_overlap, bool reset_counts)
Adds a flow entry to the table.
void platform_rwlock_wrlock(platform_rwlock_t *rwlock)
Performs a write-lock over the platform_rwlock_t mutex platform_mutex_init().
ROFL_BEGIN_DECLS platform_mutex_t * platform_mutex_init(void *params)
Allocates and initializes a mutex.
void of1x_dump_flow_entry(of1x_flow_entry_t *entry, bool raw_nbo)
Dumps the flow entry for debugging purposes.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
of1x_flow_removal_strictness
Flow removal operations strictness.
platform_rwlock_t * platform_rwlock_init(void *params)
Allocates and initializes a rwlock.
rofl_result_t(* remove_flow_entry_hook)(struct of1x_flow_table *const table, of1x_flow_entry_t *const entry, of1x_flow_entry_t *const specific_entry, const enum of1x_flow_removal_strictness strict, uint32_t out_port, uint32_t out_group, of1x_flow_remove_reason_t reason, of1x_mutex_acquisition_required_t mutex_acquired)
Removes one or more flow entries in the table.
OpenFlow v1.0, 1.2 and 1.3.2 actions.
rofl_result_t(* modify_flow_entry_hook)(struct of1x_flow_table *const table, of1x_flow_entry_t *const entry, const enum of1x_flow_removal_strictness strict, bool reset_counts)
Modifies a set of flow entries in the table.
rofl_of1x_fm_result_t of1x_add_flow_entry_table(of1x_pipeline_t *const pipeline, const unsigned int table_id, of1x_flow_entry_t **const entry, bool check_overlap, bool reset_counts)
Add a flow_entry to a table.
void platform_rwlock_destroy(platform_rwlock_t *rwlock)
Destroys and deallocates a rwlock previously inited by platform_rwlock_init().
void __of1x_stats_table_destroy(struct of1x_flow_table *table)
Destroys table statistics state.
matching_auxiliary_t * matching_aux[2]
Place-holder to allow matching algorithms keep its own state.
void platform_mutex_destroy(platform_mutex_t *mutex)
Destroys and deallocates a mutex previously inited by platform_mutex_init().
enum rofl_of1x_fm_result rofl_of1x_fm_result_t
Extended flowmod return codes.
of1x_flow_entry_t * entries
This pointer may or may not be used depending on the matching algorithm.
void __of1x_stats_table_init(struct of1x_flow_table *table)
Initializes table statistics state.
OpenFlow v1.0, 1.2 and 1.3.2 matches.
rofl_result_t(* destroy_hook)(struct of1x_flow_table *const table)
Allows to destroy matching algorithm table state.
rofl_result_t(* init_hook)(struct of1x_flow_table *const table)
Allows to initialize matching algorithm table state.
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction data structure.
Definition: of1x_pipeline.h:50
void(* dump_hook)(struct of1x_flow_table *const table, bool raw_nbo)
Dump hook.
rofl_result_t __of1x_timer_group_static_init(struct of1x_flow_table *table)
of1x_timer_group_static_init initializes the timeout values initializes the values for the entry list...
Definition: of1x_timers.c:121
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.
rofl_result_t __of1x_validate_flow_entry(of1x_flow_entry_t *entry, struct of1x_pipeline *pipeline, unsigned int table_id)
Check if the entry(matches, actions and instructions is valid for insertion)
static void bitmap128_set(bitmap128_t *bitmap, unsigned int pos)
Set a bit in the 128bit bitmap.
Definition: bitmap.h:55