ROFL-pipeline  v0.6.0dev
of1x_group_table.c
1 /*
2  * A group table is a list of group entries, each one of them contain:
3  * - Group ID
4  * - Group type
5  * - Counters
6  * - Action bucket list
7  *
8  * What is going on in this file?
9  * groups may be added , deleted & modifyed
10  * if a table has an action that says so, the actions of the bucket will be applied
11  */
12 #include "of1x_group_table.h"
13 #include "of1x_pipeline.h"
14 #include "../of1x_switch.h"
15 #include "../../../platform/lock.h"
16 #include "../../../platform/memory.h"
17 #include "../../../platform/likely.h"
18 #include "../../../util/logging.h"
19 #include <stdio.h>
20 
21 static void __of1x_destroy_group(of1x_group_table_t *gt, of1x_group_t *ge);
22 bool __of1x_bucket_list_has_weights(of1x_bucket_list_t *bl);
23 
24 void __of12_set_group_table_defaults(of1x_group_table_t *gt){
25  bitmap128_clean(&gt->config.supported_actions);
26 
27  //We initialize with the support of all possible actions. This can be customized via the init hook
28  bitmap128_set(&gt->config.supported_actions, OF1X_AT_COPY_TTL_IN);
29  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_VLAN);
30  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_MPLS);
31  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_GRE);
32  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_GTP);
33  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_PPPOE);
34  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_PPPOE);
35  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_GTP);
36  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_GRE);
37  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_MPLS);
38  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_VLAN);
39  bitmap128_set(&gt->config.supported_actions, OF1X_AT_COPY_TTL_OUT);
40  bitmap128_set(&gt->config.supported_actions, OF1X_AT_DEC_NW_TTL);
41  bitmap128_set(&gt->config.supported_actions, OF1X_AT_DEC_MPLS_TTL);
42  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_MPLS_TTL);
43  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_NW_TTL);
44  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_QUEUE);
45  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ETH_DST);
46  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ETH_SRC);
47  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ETH_TYPE);
48  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_MPLS_LABEL);
49  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_MPLS_TC);
50  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_VLAN_VID);
51  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_VLAN_PCP);
52  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ARP_OPCODE);
53  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ARP_SHA);
54  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ARP_SPA);
55  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ARP_THA);
56  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ARP_TPA);
57  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_NW_PROTO);
58  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_NW_SRC);
59  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_NW_DST);
60  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IP_DSCP);
61  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IP_ECN);
62  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IP_PROTO);
63  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV4_SRC);
64  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV4_DST);
65  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_SRC);
66  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_DST);
67  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_FLABEL);
68  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_ND_TARGET);
69  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_ND_SLL);
70  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_ND_TLL);
71  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_TCP_SRC);
72  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_TCP_DST);
73  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_UDP_SRC);
74  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_UDP_DST);
75  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_SCTP_SRC);
76  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_SCTP_DST);
77  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_TP_SRC);
78  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_TP_DST);
79  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ICMPV4_TYPE);
80  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ICMPV4_CODE);
81  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ICMPV6_TYPE);
82  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_ICMPV6_CODE);
83  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_PPPOE_CODE);
84  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_PPPOE_TYPE);
85  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_PPPOE_SID);
86  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_PPP_PROT);
87  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_GTP_MSG_TYPE);
88  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_GTP_TEID);
89  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_GRE_VERSION);
90  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_GRE_PROT_TYPE);
91  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_GRE_KEY);
92  //bitmap128_set(&gt->config.supported_actions, OF1X_AT_GROUP); //WE DON'T SUPPORT INDIRECT GROUP reference
93 
94  bitmap128_set(&gt->config.supported_actions, OF1X_AT_OUTPUT);
95 }
96 
97 void __of13_set_group_table_defaults(of1x_group_table_t *gt){
98  __of12_set_group_table_defaults(gt);
99 
100  bitmap128_set(&gt->config.supported_actions, OF1X_AT_POP_PBB);
101  bitmap128_set(&gt->config.supported_actions, OF1X_AT_PUSH_PBB);
102  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_MPLS_BOS);
103  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_PBB_ISID);
104  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_TUNNEL_ID);
105  bitmap128_set(&gt->config.supported_actions, OF1X_AT_SET_FIELD_IPV6_EXTHDR);
106 }
107 
109  of1x_group_table_t *gt;
111 
112  if( unlikely(gt==NULL) ){
113  return NULL;
114  }
115 
116  gt->num_of_entries = 0;
117  gt->head = NULL;
118  gt->tail = NULL;
119 
120  gt->mutex = platform_mutex_init(NULL);
121  gt->rwlock = platform_rwlock_init(NULL);
122 
123  switch(pipeline->sw->of_ver){
124  case OF_VERSION_10:
125  break;
126  case OF_VERSION_12:
127  __of12_set_group_table_defaults(gt);
128  break;
129  case OF_VERSION_13:
130  __of13_set_group_table_defaults(gt);
131  break;
132  default:
133  platform_mutex_destroy(gt->mutex);
134  platform_rwlock_destroy(gt->rwlock);
136  return NULL;
137  }
138 
139  //Reference back
140  gt->pipeline = pipeline;
141 
142  return gt;
143 }
144 
146  of1x_group_t *iterator=NULL, *next=NULL;
147  //check if there are existing entries and deleting them
148 
149  platform_mutex_lock(gt->mutex);
150  platform_rwlock_wrlock(gt->rwlock);
151 
152  for(iterator=gt->head; iterator!=NULL; iterator=next){
153  next=iterator->next;
154  __of1x_destroy_group(gt,iterator);
155  }
156 
157  platform_mutex_destroy(gt->mutex);
158  platform_rwlock_destroy(gt->rwlock);
159 
160 
162 }
163 
164 static
165 rofl_of1x_gm_result_t __of1x_validate_group(of1x_group_table_t* gt, of1x_action_group_t* actions){
166 
167  //we dont allow OF1X_AT_GROUP
168  //and neither OF1X_AT_OUTPUT in the case of OF1X_PORT_TABLE
170 
171  for(it=actions->head; it; it=it->next){
172  if(it->type == OF1X_AT_GROUP)
173  return ROFL_OF1X_GM_CHAIN;
174  if(it->type == OF1X_AT_OUTPUT && it->__field.u64 == OF1X_PORT_TABLE)
175  return ROFL_OF1X_GM_INVAL;
176  }
177 
178  //verify apply actions
179  if(__of1x_validate_action_group(&gt->config.supported_actions, actions, gt, false) != ROFL_SUCCESS)
180  return ROFL_OF1X_GM_INVAL;
181 
182  return ROFL_OF1X_GM_OK;
183 }
184 
185 
191  of1x_group_t *iterator=NULL, *next=NULL;
192 
193  platform_rwlock_rdlock(gt->rwlock);
194 
195  for(iterator=gt->head; iterator!=NULL; iterator=next){
196  next=iterator->next;
197  if(iterator->id == id){
198  platform_rwlock_rdunlock(gt->rwlock);
199  return iterator;
200  }
201  }
202 
203  platform_rwlock_rdunlock(gt->rwlock);
204 
205  return NULL;
206 }
207 
208 rofl_of1x_gm_result_t __of1x_check_group_parameters(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t *buckets){
209  of1x_bucket_t* bu_it;
210  rofl_of1x_gm_result_t ret_val;
211 
212  if(id == OF1X_GROUP_ALL || id == OF1X_GROUP_ANY || id > OF1X_GROUP_MAX)
213  return ROFL_OF1X_GM_INVAL;
214 
215  //Validate action set
216  for(bu_it=buckets->head;bu_it!=NULL;bu_it=bu_it->next){
217  if((ret_val=__of1x_validate_group(gt, bu_it->actions))!=ROFL_OF1X_GM_OK)
218  return ret_val;
219  }
220 
221  //Group types not supported
222  if (type == OF1X_GROUP_TYPE_SELECT || type == OF1X_GROUP_TYPE_FF){
223  ROFL_PIPELINE_ERR("Warning; group type %u NOT supported\n", type);
224  return ROFL_OF1X_GM_INVAL;
225  }
226 
227 
228  if(type == OF1X_GROUP_TYPE_INDIRECT && buckets->num_of_buckets>1)
229  return ROFL_OF1X_GM_INVAL;
230  if( (type == OF1X_GROUP_TYPE_ALL || type == OF1X_GROUP_TYPE_INDIRECT) && __of1x_bucket_list_has_weights(buckets))
231  return ROFL_OF1X_GM_INVAL;
232  if (type == OF1X_GROUP_TYPE_SELECT && __of1x_bucket_list_has_weights(buckets) == false)
233  return ROFL_OF1X_GM_INVAL;
234 
235  return ROFL_OF1X_GM_OK;
236 }
237 
238 static
239 rofl_of1x_gm_result_t __of1x_init_group(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t *buckets){
240  //uint32_t weigth, uint32_t group, uint32_t port, of1x_action_group_t **actions){
241  rofl_of1x_gm_result_t ret_val;
242  of1x_group_t* ge=NULL;
243 
245  if ( unlikely(ge==NULL) ){
246  return ROFL_OF1X_GM_OGRUPS;
247  }
248 
249  if((ret_val=__of1x_check_group_parameters(gt,type,id,buckets))!=ROFL_OF1X_GM_OK){
251  return ret_val;
252  }
253 
254  ge->bc_list = buckets;
255  ge->id = id;
256  ge->type = type;
257  ge->group_table = gt;
258  ge->rwlock = platform_rwlock_init(NULL);
259  __of1x_init_group_stats(&ge->stats);
260 
261  // Count the number of output actions existing inside the group. WARNING For select type groups the count depends on the bucket used!
262  ge->num_of_output_actions = 0;
263  of1x_bucket_t *bc;
264  for( bc=buckets->head; bc !=NULL; bc=bc->next){
265  ge->num_of_output_actions += bc->actions->num_of_output_actions;
266  }
267 
268  platform_rwlock_wrlock(gt->rwlock);
269 
270  //insert in the end
271  if (gt->head == NULL && gt->tail == NULL){
272  gt->head = ge;
273  gt->tail = ge;
274  ge->prev = NULL;
275  } else {
276  gt->tail->next = ge;
277  ge->prev = gt->tail;
278  }
279  ge->next = NULL;
280  gt->tail = ge;
281  gt->num_of_entries++;
282 
283  platform_rwlock_wrunlock(gt->rwlock);
284 
285  return ROFL_OF1X_GM_OK;
286 }
287 
288 rofl_of1x_gm_result_t of1x_group_add(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t **buckets){
289  rofl_of1x_gm_result_t ret_val;
290  ROFL_PIPELINE_INFO("[groupmod-add(%p)] Starting operation at switch %s(%p), group id: %u\n", *buckets, gt->pipeline->sw->name, gt->pipeline->sw, id);
291 
292  //serialize mgmt actions
293  platform_mutex_lock(gt->mutex);
294 
295  //check wether onither entry with this ID already exists
296  if(__of1x_group_search(gt,id)!=NULL){
297  platform_mutex_unlock(gt->mutex);
298  ROFL_PIPELINE_INFO("[groupmod-add(%p)] FAILED validation. Group exists...\n", *buckets);
299  return ROFL_OF1X_GM_EXISTS;
300  }
301 
302  ret_val = __of1x_init_group(gt,type,id,*buckets);
303  if (ret_val!=ROFL_OF1X_GM_OK){
304  platform_mutex_unlock(gt->mutex);
305  ROFL_PIPELINE_INFO("[groupmod-add(%p)] FAILED, reason %u\n", *buckets, ret_val);
306  return ret_val;
307  }
308 
309  ROFL_PIPELINE_INFO("[groupmod-add(%p)] Successful\n", *buckets);
310 
311  platform_mutex_unlock(gt->mutex);
312 
313  //Was successful set the pointer to NULL
314  //so that is not further used outside the pipeline
315  *buckets = NULL;
316 
317  return ROFL_OF1X_GM_OK;
318 }
319 
320 static
321 void __of1x_destroy_group(of1x_group_table_t *gt, of1x_group_t *ge){
322 
323  platform_rwlock_wrlock(ge->rwlock);
324 
325  //destroy buckets & actions inside
326  of1x_destroy_bucket_list(ge->bc_list);
327 
328  __of1x_destroy_group_stats(&ge->stats);
329 
330  platform_rwlock_destroy(ge->rwlock);
331 
332  //free
334 }
335 
336 static
337 rofl_result_t __of1x_extract_group(of1x_group_table_t *gt, of1x_group_t *ge){
338 
339  //take write lock of the table
340  platform_rwlock_wrlock(gt->rwlock);
341  //check if the group is still in the table
342  if( unlikely(ge->group_table==NULL) ){
343  platform_rwlock_wrunlock(gt->rwlock);
344  return ROFL_FAILURE;
345  }
346  ge->group_table = NULL;
347 
348  //detach
349  if(ge->next)
350  ge->next->prev = ge->prev;
351  if(ge->prev)
352  ge->prev->next = ge->next;
353 
354  //check head and tail
355  if (gt->head == ge)
356  gt->head = ge->next;
357  if (gt->tail == ge)
358  gt->tail = ge->prev;
359 
360  gt->num_of_entries--;
361  //leave write lock of the table
362  platform_rwlock_wrunlock(gt->rwlock);
363  return ROFL_SUCCESS;
364 }
365 
366 rofl_of1x_gm_result_t of1x_group_delete(of1x_pipeline_t *pipeline, of1x_group_table_t *gt, uint32_t id){
367  int i;
368  of1x_flow_entry_t* entry;
369  of1x_group_t *ge, *next;
370 
371  //serialize mgmt actions
372  platform_mutex_lock(gt->mutex);
373 
374  if(id == OF1X_GROUP_ALL){
375  for(ge = gt->head; ge; ge=next){
376  next = ge->next;
377  //extract the group without destroying it (only the first thread that comes gets it)
378  if(__of1x_extract_group(gt, ge)==ROFL_FAILURE){
379  platform_mutex_unlock(gt->mutex);
380  return ROFL_OF1X_GM_OK; //if it is not found no need to throw an error
381  }
382 
383  //loop for all the tables and erase entries that point to the group
384  for(i=0; i<pipeline->num_of_tables; i++){
385  while((entry=of1x_matching_algorithms[pipeline->tables[i].matching_algorithm].find_entry_using_group_hook(&pipeline->tables[i],ge->id))!=NULL){
386  __of1x_remove_specific_flow_entry_table(pipeline,i,entry, OF1X_FLOW_REMOVE_GROUP_DELETE, MUTEX_NOT_ACQUIRED);
387  }
388  }
389  //destroy the group
390  __of1x_destroy_group(gt,ge);
391  }
392  platform_mutex_unlock(gt->mutex);
393  return ROFL_OF1X_GM_OK;
394  }
395 
396  //search the table for the group
397  if((ge=__of1x_group_search(gt,id))==NULL){
398  platform_mutex_unlock(gt->mutex);
399  return ROFL_OF1X_GM_OK; //if it is not found no need to throw an error
400  }
401 
402  //extract the group without destroying it (only the first thread that comes gets it)
403  if(__of1x_extract_group(gt, ge)==ROFL_FAILURE){
404  platform_mutex_unlock(gt->mutex);
405  return ROFL_OF1X_GM_OK; //if it is not found no need to throw an error
406  }
407 
408  //loop for all the tables and erase entries that point to the group
409  for(i=0; i<pipeline->num_of_tables; i++){
410  while((entry=of1x_matching_algorithms[pipeline->tables[i].matching_algorithm].find_entry_using_group_hook(&pipeline->tables[i],ge->id))!=NULL){
411  __of1x_remove_specific_flow_entry_table(pipeline,i,entry, OF1X_FLOW_REMOVE_GROUP_DELETE, MUTEX_NOT_ACQUIRED);
412  }
413  }
414 
415  //destroy the group
416  __of1x_destroy_group(gt,ge);
417 
418  platform_mutex_unlock(gt->mutex);
419 
420  return ROFL_OF1X_GM_OK;
421 }
422 
428 rofl_of1x_gm_result_t of1x_group_modify(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t **buckets){
429  rofl_of1x_gm_result_t ret_val;
430 
431  if((ret_val=__of1x_check_group_parameters(gt,type,id,*buckets))!=ROFL_OF1X_GM_OK)
432  return ret_val;
433 
434  of1x_group_t *ge = __of1x_group_search(gt,id);
435  if (ge == NULL){
436  return ROFL_OF1X_GM_UNKGRP;
437  }
438 
439  platform_rwlock_wrlock(ge->rwlock);
440 
441  of1x_destroy_bucket_list(ge->bc_list);
442  ge->bc_list = *buckets;
443  ge->id = id;
444  ge->type = type;
445  ge->group_table = gt;
446 
447  platform_rwlock_wrunlock(ge->rwlock);
448 
449  //Was successful set the pointer to NULL
450  //so that is not further used outside the pipeline
451  *buckets = NULL;
452 
453  return ROFL_OF1X_GM_OK;
454 }
455 
458  if ( unlikely(bl==NULL) )
459  return NULL;
460 
461  bl->num_of_buckets=0;
462  bl->head = NULL;
463  bl->tail = NULL;
464  return bl;
465 }
466 
468 
469  if(bu_list->head==NULL && bu_list->tail==NULL){
470  bu_list->head = bucket;
471  bu_list->tail = bucket;
472  }
473  else{
474  bu_list->tail->next = bucket;
475  bu_list->tail = bucket;
476  }
477  bu_list->num_of_buckets++;
478  return ROFL_SUCCESS;
479 }
480 
481 of1x_bucket_t* of1x_init_bucket(uint16_t weight, uint32_t port, uint32_t group, of1x_action_group_t* actions){
482 
484  if ( unlikely(bk==NULL) )
485  return NULL;
486 
487  bk->next= NULL;
488  bk->weight= weight;
489  bk->port= port;
490  bk->group= group;
491  bk->actions = actions;// actions must be already initialized
492  __of1x_init_bucket_stats(&bk->stats);
493 
494  return bk;
495 }
496 
498  of1x_bucket_t *bk_it, *next;
499 
500  for(bk_it=bc_list->head;bk_it!=NULL;bk_it=next){
501  next = bk_it->next;
502  //NOTE were are the action groups created and deleted?
503  of1x_destroy_action_group(bk_it->actions);
504  __of1x_destroy_buckets_stats(&bk_it->stats);
505  platform_free_shared(bk_it);
506  }
507  platform_free_shared(bc_list);
508 }
509 
510 bool __of1x_bucket_list_has_weights(of1x_bucket_list_t *bl){
511  of1x_bucket_t *bu_it;
512  for(bu_it = bl->head; bu_it!=NULL; bu_it=bu_it->next){
513  if(bu_it->weight!=0)
514  return true;
515  }
516  return false;
517 }
518 
519 void of1x_dump_bucket(of1x_bucket_t *bc, bool raw_nbo){
520 
522  __of1x_stats_bucket_consolidate(&bc->stats, &c);
523 
524  ROFL_PIPELINE_INFO_NO_PREFIX("Weight %u, port %u, actions: ", bc->weight, bc->port);
525  __of1x_dump_action_group(bc->actions, raw_nbo);
526  ROFL_PIPELINE_INFO_NO_PREFIX(" statistics {pkt_count: %u}", c.packet_count);
527  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
528 }
529 
530 void of1x_dump_group(of1x_group_t* group, bool raw_nbo){
531  of1x_bucket_t *bc_it;
532  unsigned int i;
534 
535  ROFL_PIPELINE_INFO_NO_PREFIX("id %u, ", group->id);
536  switch(group->type){
537  case OF1X_GROUP_TYPE_ALL:
538  ROFL_PIPELINE_INFO_NO_PREFIX("GROUP_TYPE_ALL, ");
539  break;
540  case OF1X_GROUP_TYPE_SELECT:
541  ROFL_PIPELINE_INFO_NO_PREFIX("GROUP_TYPE_SELECT, ");
542  break;
543  case OF1X_GROUP_TYPE_INDIRECT:
544  ROFL_PIPELINE_INFO_NO_PREFIX("GROUP_TYPE_INDIRECT, ");
545  break;
546  case OF1X_GROUP_TYPE_FF:
547  ROFL_PIPELINE_INFO_NO_PREFIX("GROUP_TYPE_FF, ");
548  break;
549  default:
550  ROFL_PIPELINE_INFO_NO_PREFIX("UNEXPECTED GROUP_TYPE (%u), ", group->type);
551  break;
552  }
553 
554  __of1x_stats_group_consolidate(&group->stats, &c);
555 
556  ROFL_PIPELINE_INFO_NO_PREFIX("num of buckets %u, statistics {pkt_count: %u} \n", group->bc_list->num_of_buckets, c.packet_count);
557 
558  for(bc_it=group->bc_list->head, i=0; bc_it; bc_it=bc_it->next, i++){
559  ROFL_PIPELINE_INFO("\t\t[%u] Bucket (%p). ", i, bc_it);
560  of1x_dump_bucket(bc_it, raw_nbo);
561  }
562  ROFL_PIPELINE_INFO("\n");
563 }
564 
565 void of1x_dump_group_table(of1x_group_table_t *gt, bool raw_nbo){
566  of1x_group_t* it;
567  unsigned int i;
568 
569  ROFL_PIPELINE_INFO("Dumping group table. Num of group entries: %u\n",gt->num_of_entries);
570  if (gt->num_of_entries > 0){
571  for(it=gt->head, i=0; it; it=it->next, i++){
572  ROFL_PIPELINE_INFO("\t[%u] Group (%p). ", i, it);
573  of1x_dump_group(it, raw_nbo);
574  }
575  }
576  else{
577  ROFL_PIPELINE_INFO("\t[*] No entries\n");
578  ROFL_PIPELINE_INFO("\n");
579  }
580 }
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().
void platform_mutex_lock(platform_mutex_t *mutex)
Locks the platform_mutex_t mutex.
Packet action abstraction data structure.
Definition: of1x_action.h:278
void platform_rwlock_rdunlock(platform_rwlock_t *rwlock)
Performs a read-unlock over the platform_rwlock_t mutex platform_mutex_init().
Group structure definition.
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
void platform_mutex_unlock(platform_mutex_t *mutex)
Unlocks the platform_mutex_t mutex.
of1x_bucket_t * of1x_init_bucket(uint16_t weight, uint32_t port, uint32_t group, of1x_action_group_t *actions)
Initializes a bucket.
Group bucket.
static void bitmap128_clean(bitmap128_t *bitmap)
Set bitmap to 0.
Definition: bitmap.h:29
of1x_flow_entry_t *(* find_entry_using_group_hook)(struct of1x_flow_table *const table, const unsigned int group_id)
The find_entry_using_group_hook() must retrieve the first entry in the table that contain actions ref...
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.
rofl_result_t of1x_insert_bucket_in_list(of1x_bucket_list_t *bu_list, of1x_bucket_t *bucket)
Inserts an initialized bucket in the list of buckets.
void of1x_destroy_action_group(of1x_action_group_t *group)
Destroy an action group.
Definition: of1x_action.c:480
rofl_of1x_gm_result_t of1x_group_modify(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t **buckets)
Function that searches a group and modifies the action buckets inside.
void platform_rwlock_wrunlock(platform_rwlock_t *rwlock)
Performs a write-unlock over the platform_rwlock_t mutex platform_mutex_init().
enum of1x_group_type of1x_group_type_t
Group type.
platform_rwlock_t * platform_rwlock_init(void *params)
Allocates and initializes a rwlock.
of1x_bucket_list_t * of1x_init_bucket_list(void)
Initializes a list of buckets.
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.
Action group (apply-actions) structure.
Definition: of1x_action.h:303
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.
void platform_rwlock_destroy(platform_rwlock_t *rwlock)
Destroys and deallocates a rwlock previously inited by platform_rwlock_init().
void platform_mutex_destroy(platform_mutex_t *mutex)
Destroys and deallocates a mutex previously inited by platform_mutex_init().
rofl_of1x_gm_result_t of1x_group_add(of1x_group_table_t *gt, of1x_group_type_t type, uint32_t id, of1x_bucket_list_t **buckets)
Adds a group to the table.
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...
Group bucket list.
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().
void of1x_destroy_bucket_list(of1x_bucket_list_t *bc_list)
Destroys the bucket list.
of1x_group_t * __of1x_group_search(of1x_group_table_t *gt, uint32_t id)
Searches in the table for an entry with a specific id returns pointer if found or NULL if not...
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.
static void bitmap128_set(bitmap128_t *bitmap, unsigned int pos)
Set a bit in the 128bit bitmap.
Definition: bitmap.h:55