ROFL-pipeline  v0.6.0dev
of1x_action_pp.h
Go to the documentation of this file.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef __OF1X_ACTION_PP_H__
6 #define __OF1X_ACTION_PP_H__
7 
8 #include <inttypes.h>
9 #include <string.h>
10 #include <stdbool.h>
11 #include <assert.h>
12 #include "rofl.h"
13 #include "../../../util/pp_guard.h" //Never forget to include the guard
14 #include "of1x_statistics_pp.h"
15 #include "of1x_action.h"
16 #include "of1x_group_table.h"
17 #include "of1x_flow_table.h"
18 #include "of1x_utils.h"
19 #include "../../../physical_switch.h"
20 #include "../../../util/logging.h"
21 
22 #include "../../../common/protocol_constants.h"
23 #include "../../../common/ternary_fields.h"
24 #include "../../../common/bitmap.h"
25 
26 #include "../../../platform/lock.h"
27 #include "../../../platform/likely.h"
28 #include "../../../platform/memory.h"
29 #include "../../../platform/packet.h"
30 
31 #include "../of1x_async_events_hooks.h"
32 
58 //C++ extern C
59 ROFL_BEGIN_DECLS
60 
61 //Initialize (clear) pkt write actions
62 static inline void __of1x_init_packet_write_actions(of1x_write_actions_t* pkt_write_actions){
63  bitmap128_clean(&pkt_write_actions->bitmap);
64  pkt_write_actions->num_of_actions = 0;
65 }
66 
67 //Update pkt write actions
68 static inline void __of1x_update_packet_write_actions(of1x_write_actions_t* packet_write_actions, const of1x_write_actions_t* entry_write_actions){
69 
70  unsigned int i,j;
71 
72  for(i=0,j=0;i<entry_write_actions->num_of_actions && j < OF1X_AT_NUMBER;j++){
73  if(!bitmap128_is_bit_set(&entry_write_actions->bitmap,j))
74  continue;
75  packet_write_actions->actions[j].__field = entry_write_actions->actions[j].__field;
76  packet_write_actions->actions[j].group = entry_write_actions->actions[j].group;
77  packet_write_actions->actions[j].type = entry_write_actions->actions[j].type;
78 
79  if(!bitmap128_is_bit_set(&packet_write_actions->bitmap,j)){
80  packet_write_actions->num_of_actions++;
81  bitmap128_set(&packet_write_actions->bitmap,j);
82  }
83  i++;
84  }
85 }
86 
87 //Clear packet write actions
88 static inline void __of1x_clear_write_actions(of1x_write_actions_t* pkt_write_actions){
89  bitmap128_clean(&pkt_write_actions->bitmap);
90  pkt_write_actions->num_of_actions = 0;
91 }
92 
93 //fwd decl
94 static inline void __of1x_process_apply_actions(const unsigned int tid, const struct of1x_switch* sw, const unsigned int table_id, datapacket_t* pkt, const of1x_action_group_t* apply_actions_group, bool replicate_pkts, datapacket_t** reinject_pkt);
95 
96 //Process all actions from a group
97 static inline void __of1x_process_group_actions(const unsigned int tid, const struct of1x_switch* sw, const unsigned int table_id, datapacket_t *pkt, uint64_t field, of1x_group_t *group, bool replicate_pkts){
98  datapacket_t* pkt_replica;
99  of1x_bucket_t *it_bk;
100 
101  platform_rwlock_rdlock(group->rwlock);
102 
103  //process the actions in the buckets depending on the type
104  switch(group->type){
105  case OF1X_GROUP_TYPE_ALL:
106  //executes all buckets
107  for (it_bk = group->bc_list->head; it_bk!=NULL;it_bk = it_bk->next){
108 
109  //If there are no output actions, skip bucket
110  if(it_bk->actions->num_of_output_actions == 0)
111  continue;
112 
113  //Clone the packet according to spec before applying the bucket
114  //action list
115  pkt_replica = platform_packet_replicate(pkt);
116  if(unlikely(pkt_replica == NULL)){
117  assert(0);
118  break;
119  }
120 
121  //Process all actions in the bucket
122  __of1x_process_apply_actions(tid, sw, table_id, pkt_replica, it_bk->actions, it_bk->actions->num_of_output_actions > 1, NULL); //No replica
123  __of1x_stats_bucket_update(tid, &it_bk->stats, platform_packet_get_size_bytes(pkt));
124 
125  if(it_bk->actions->num_of_output_actions > 1)
126  platform_packet_drop(pkt_replica);
127  }
128  break;
129  case OF1X_GROUP_TYPE_SELECT:
130  //NOT SUPPORTED
131  assert(0); //Should NEVER be installed
132  break;
133  case OF1X_GROUP_TYPE_INDIRECT:
134  //executes the "one bucket defined"
135  __of1x_process_apply_actions(tid, sw,table_id,pkt,group->bc_list->head->actions, replicate_pkts, NULL);
136  __of1x_stats_bucket_update(tid, &group->bc_list->head->stats, platform_packet_get_size_bytes(pkt));
137  break;
138  case OF1X_GROUP_TYPE_FF:
139  //NOT SUPPORTED
140  assert(0); //Should NEVER be installed
141  break;
142  default:
143  assert(0); //Should NEVER be reached
144  break;
145  }
146 
147  __of1x_stats_group_update(tid, &group->stats, platform_packet_get_size_bytes(pkt));
148  platform_rwlock_rdunlock(group->rwlock);
149 
150 }
151 
152 /* Contains switch with all the different action functions */
153 static inline void __of1x_process_packet_action(const unsigned int tid, const struct of1x_switch* sw, const unsigned int table_id, datapacket_t* pkt, of1x_packet_action_t* action, bool replicate_pkts, datapacket_t** reinject_pkt){
154 
155  uint32_t port_id;
156 
157  switch(action->type){
158  case OF1X_AT_NO_ACTION: assert(0);
159  break;
160 
161  case OF1X_AT_COPY_TTL_IN: platform_packet_copy_ttl_in(pkt);
162  break;
163 
164  //POP
165  case OF1X_AT_POP_VLAN:
166  //Call platform
168  break;
169  case OF1X_AT_POP_MPLS:
170  //Call platform
171  platform_packet_pop_mpls(pkt, action->__field.u16);
172  break;
173 
174  //PUSH
175  case OF1X_AT_PUSH_MPLS:
176  //Call platform
177  platform_packet_push_mpls(pkt, action->__field.u16);
178  break;
179  case OF1X_AT_PUSH_VLAN:
180  //Call platform
181  platform_packet_push_vlan(pkt, action->__field.u16);
182  break;
183 
184  //TTL
185  case OF1X_AT_COPY_TTL_OUT:
186  //Call platform
188  break;
189  case OF1X_AT_DEC_NW_TTL:
190  //Call platform
192  break;
193  case OF1X_AT_DEC_MPLS_TTL:
194  //Call platform
196  break;
197  case OF1X_AT_SET_MPLS_TTL:
198  //Call platform
199  platform_packet_set_mpls_ttl(pkt, action->__field.u8);
200  break;
201  case OF1X_AT_SET_NW_TTL:
202  //Call platform
203  platform_packet_set_nw_ttl(pkt, action->__field.u8);
204  break;
205 
206  //QUEUE
207  case OF1X_AT_SET_QUEUE:
208  //Call platform
209  platform_packet_set_queue(pkt, action->__field.u32);
210  break;
211 
212  //802
213  case OF1X_AT_SET_FIELD_ETH_DST:
214  //Call platform
215  platform_packet_set_eth_dst(pkt, action->__field.u64);
216  break;
217  case OF1X_AT_SET_FIELD_ETH_SRC:
218  //Call platform
219  platform_packet_set_eth_src(pkt, action->__field.u64);
220  break;
221  case OF1X_AT_SET_FIELD_ETH_TYPE:
222  //Call platform
223  platform_packet_set_eth_type(pkt, action->__field.u16);
224  break;
225 
226  //802.1q
227  case OF1X_AT_SET_FIELD_VLAN_VID:
228  //For 1.0 we must first push it if we don't have. wtf...
229  if(sw->of_ver == OF_VERSION_10 && !platform_packet_has_vlan(pkt)){
230  //Push VLAN
231  platform_packet_push_vlan(pkt, ETH_TYPE_8021Q);
233  }
234  //Call platform
235  platform_packet_set_vlan_vid(pkt, action->__field.u16);
236  break;
237  case OF1X_AT_SET_FIELD_VLAN_PCP:
238  //For 1.0 we must first push it if we don't have. wtf...
239  if(sw->of_ver == OF_VERSION_10 && !platform_packet_has_vlan(pkt)){
240  //Push VLAN
241  platform_packet_push_vlan(pkt, ETH_TYPE_8021Q);
243  }
244  //Call platform
245  platform_packet_set_vlan_pcp(pkt, action->__field.u8);
246  break;
247 
248  //ARP
249  case OF1X_AT_SET_FIELD_ARP_OPCODE:
250  //Call plattform
251  platform_packet_set_arp_opcode(pkt, action->__field.u16);
252  break;
253  case OF1X_AT_SET_FIELD_ARP_SHA:
254  //Call platform
255  platform_packet_set_arp_sha(pkt, action->__field.u64);
256  break;
257  case OF1X_AT_SET_FIELD_ARP_SPA:
258  //Call platform
259  platform_packet_set_arp_spa(pkt, action->__field.u32);
260  break;
261  case OF1X_AT_SET_FIELD_ARP_THA:
262  //Call platform
263  platform_packet_set_arp_tha(pkt, action->__field.u64);
264  break;
265  case OF1X_AT_SET_FIELD_ARP_TPA:
266  //Call platform
267  platform_packet_set_arp_tpa(pkt, action->__field.u32);
268  break;
269 
270  //NW
271  case OF1X_AT_SET_FIELD_NW_PROTO:
272  if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_IPV4){
273  //Call platform
274  platform_packet_set_ip_proto(pkt, action->__field.u8);
275  }else if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_ARP){
276  //Call plattform
277  platform_packet_set_arp_opcode(pkt, action->__field.u8);
278  }
279 
280  break;
281  case OF1X_AT_SET_FIELD_NW_SRC:
282  if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_IPV4){
283  //Call platform
284  platform_packet_set_ipv4_src(pkt, action->__field.u32);
285  }else if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_ARP){
286  //Call platform
287  platform_packet_set_arp_spa(pkt, action->__field.u32);
288  }
289  break;
290  case OF1X_AT_SET_FIELD_NW_DST:
291  if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_IPV4){
292  //Call platform
293  platform_packet_set_ipv4_dst(pkt, action->__field.u32);
294  }else if(*platform_packet_get_eth_type(pkt) == ETH_TYPE_ARP){
295  //Call platform
296  platform_packet_set_arp_tpa(pkt, action->__field.u32);
297  }
298  break;
299 
300  //IP
301  case OF1X_AT_SET_FIELD_IP_DSCP:
302  //Call platform
303  platform_packet_set_ip_dscp(pkt, action->__field.u8);
304  break;
305  case OF1X_AT_SET_FIELD_IP_ECN:
306  //Call platform
307  platform_packet_set_ip_ecn(pkt, action->__field.u8);
308  break;
309  case OF1X_AT_SET_FIELD_IP_PROTO:
310  //Call platform
311  platform_packet_set_ip_proto(pkt, action->__field.u8);
312  break;
313 
314  //IPv4
315  case OF1X_AT_SET_FIELD_IPV4_SRC:
316  //Call platform
317  platform_packet_set_ipv4_src(pkt, action->__field.u32);
318  break;
319  case OF1X_AT_SET_FIELD_IPV4_DST:
320  //Call platform
321  platform_packet_set_ipv4_dst(pkt, action->__field.u32);
322  break;
323 
324  //TP
325  case OF1X_AT_SET_FIELD_TP_SRC:
326  if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_TCP){
327  //Call platform
328  platform_packet_set_tcp_src(pkt, action->__field.u16);
329  }else if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_UDP){
330  //Call platform
331  platform_packet_set_udp_src(pkt, action->__field.u16);
332  }else if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_ICMPV4){
333  //Call platform
334  platform_packet_set_icmpv4_type(pkt, action->__field.u8);
335  }
336  break;
337  case OF1X_AT_SET_FIELD_TP_DST:
338  if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_TCP){
339  //Call platform
340  platform_packet_set_tcp_dst(pkt, action->__field.u16);
341  }else if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_UDP){
342  //Call platform
343  platform_packet_set_udp_dst(pkt, action->__field.u16);
344  }else if(*platform_packet_get_ip_proto(pkt) == IP_PROTO_ICMPV4){
345  //Call platform
346  platform_packet_set_icmpv4_code(pkt, action->__field.u8);
347  }
348  break;
349 
350  //TCP
351  case OF1X_AT_SET_FIELD_TCP_SRC:
352  //Call platform
353  platform_packet_set_tcp_src(pkt, action->__field.u16);
354  break;
355  case OF1X_AT_SET_FIELD_TCP_DST:
356  //Call platform
357  platform_packet_set_tcp_dst(pkt, action->__field.u16);
358  break;
359 
360  //UDP
361  case OF1X_AT_SET_FIELD_UDP_SRC:
362  //Call platform
363  platform_packet_set_udp_src(pkt, action->__field.u16);
364  break;
365  case OF1X_AT_SET_FIELD_UDP_DST:
366  //Call platform
367  platform_packet_set_udp_dst(pkt, action->__field.u16);
368  break;
369  //SCTP
370  case OF1X_AT_SET_FIELD_SCTP_SRC:
371  //Call platform
372  platform_packet_set_sctp_src(pkt, action->__field.u16);
373  break;
374  case OF1X_AT_SET_FIELD_SCTP_DST:
375  //Call platform
376  platform_packet_set_sctp_dst(pkt, action->__field.u16);
377  break;
378 
379 
380  //ICMPv4
381  case OF1X_AT_SET_FIELD_ICMPV4_TYPE:
382  //Call platform
383  platform_packet_set_icmpv4_type(pkt, action->__field.u8);
384  break;
385  case OF1X_AT_SET_FIELD_ICMPV4_CODE:
386  //Call platform
387  platform_packet_set_icmpv4_code(pkt, action->__field.u8);
388  break;
389 
390  //MPLS
391  case OF1X_AT_SET_FIELD_MPLS_LABEL:
392  //Call platform
393  platform_packet_set_mpls_label(pkt, action->__field.u32);
394  break;
395  case OF1X_AT_SET_FIELD_MPLS_TC:
396  //Call platform
397  platform_packet_set_mpls_tc(pkt, action->__field.u8);
398  break;
399  case OF1X_AT_SET_FIELD_MPLS_BOS:
400  //Call platform
401  platform_packet_set_mpls_bos(pkt, action->__field.u8);
402  break;
403 
404 
405  //IPv6
406  case OF1X_AT_SET_FIELD_IPV6_SRC:
407  //Call platform
408  platform_packet_set_ipv6_src(pkt, action->__field.u128);
409  break;
410  case OF1X_AT_SET_FIELD_IPV6_DST:
411  //Call platform
412  platform_packet_set_ipv6_dst(pkt, action->__field.u128);
413  break;
414  case OF1X_AT_SET_FIELD_IPV6_FLABEL:
415  //Call platform
416  platform_packet_set_ipv6_flabel(pkt, action->__field.u32);
417  break;
418  case OF1X_AT_SET_FIELD_IPV6_ND_TARGET:
419  //Call platform
420  platform_packet_set_ipv6_nd_target(pkt, action->__field.u128);
421  break;
422  case OF1X_AT_SET_FIELD_IPV6_ND_SLL:
423  //Call platform
424  platform_packet_set_ipv6_nd_sll(pkt, action->__field.u64);
425  break;
426  case OF1X_AT_SET_FIELD_IPV6_ND_TLL:
427  //Call platform
428  platform_packet_set_ipv6_nd_tll(pkt, action->__field.u64);
429  break;
430  case OF1X_AT_SET_FIELD_IPV6_EXTHDR:
431  //Call platform
432  platform_packet_set_ipv6_exthdr(pkt, action->__field.u16);
433  break;
434  //ICMPv6
435  case OF1X_AT_SET_FIELD_ICMPV6_TYPE:
436  //Call platform
437  platform_packet_set_icmpv6_type(pkt, action->__field.u8);
438  break;
439 
440  case OF1X_AT_SET_FIELD_ICMPV6_CODE:
441  //Call platform
442  platform_packet_set_icmpv6_code(pkt, action->__field.u8);
443  break;
444 
445 #ifdef ROFL_EXPERIMENTAL
446 
447  case OF1X_AT_POP_PPPOE:
448  //Call platform
449  platform_packet_pop_pppoe(pkt, action->__field.u16);
450  break;
451  case OF1X_AT_PUSH_PPPOE:
452  //Call platform
453  platform_packet_push_pppoe(pkt, action->__field.u16);
454  break;
455 
456  //PPPoE
457  case OF1X_AT_SET_FIELD_PPPOE_CODE:
458  //Call platform
459  platform_packet_set_pppoe_code(pkt, action->__field.u8);
460  break;
461  case OF1X_AT_SET_FIELD_PPPOE_TYPE:
462  //Call platform
463  platform_packet_set_pppoe_type(pkt, action->__field.u8);
464  break;
465  case OF1X_AT_SET_FIELD_PPPOE_SID:
466  //Call platform
467  platform_packet_set_pppoe_sid(pkt, action->__field.u16);
468  break;
469 
470  //PPP
471  case OF1X_AT_SET_FIELD_PPP_PROT:
472  //Call platform
473  platform_packet_set_ppp_proto(pkt, action->__field.u16);
474  break;
475 
476  //GTP
477  case OF1X_AT_SET_FIELD_GTP_MSG_TYPE:
478  //Call platform
479  platform_packet_set_gtp_msg_type(pkt, action->__field.u8);
480  break;
481  case OF1X_AT_SET_FIELD_GTP_TEID:
482  //Call platform
483  platform_packet_set_gtp_teid(pkt, action->__field.u32);
484  break;
485  case OF1X_AT_POP_GTP:
486  //Call platform
487  platform_packet_pop_gtp(pkt, action->__field.u16);
488  break;
489  case OF1X_AT_PUSH_GTP:
490  //Call platform
491  platform_packet_push_gtp(pkt, action->__field.u16);
492  break;
493 
494  //CAPWAP
495  case OF1X_AT_SET_FIELD_CAPWAP_WBID:
496  //Call platform
497  platform_packet_set_capwap_wbid(pkt, action->__field.u8);
498  break;
499  case OF1X_AT_SET_FIELD_CAPWAP_RID:
500  //Call platform
501  platform_packet_set_capwap_rid(pkt, action->__field.u8);
502  break;
503  case OF1X_AT_SET_FIELD_CAPWAP_FLAGS:
504  //Call platform
505  platform_packet_set_capwap_flags(pkt, action->__field.u16);
506  break;
507  case OF1X_AT_POP_CAPWAP:
508  //Call platform
509  platform_packet_pop_capwap(pkt);
510  break;
511  case OF1X_AT_PUSH_CAPWAP:
512  //Call platform
513  platform_packet_push_capwap(pkt);
514  break;
515 
516  //IEEE80211 WLAN
517  case OF1X_AT_SET_FIELD_WLAN_FC:
518  //Call platform
519  platform_packet_set_wlan_fc(pkt, action->__field.u16);
520  break;
521  case OF1X_AT_SET_FIELD_WLAN_TYPE:
522  //Call platform
523  platform_packet_set_wlan_type(pkt, action->__field.u8);
524  break;
525  case OF1X_AT_SET_FIELD_WLAN_SUBTYPE:
526  //Call platform
527  platform_packet_set_wlan_subtype(pkt, action->__field.u8);
528  break;
529  case OF1X_AT_SET_FIELD_WLAN_DIRECTION:
530  //Call platform
531  platform_packet_set_wlan_direction(pkt, action->__field.u8);
532  break;
533  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_1:
534  //Call platform
535  platform_packet_set_wlan_address_1(pkt, action->__field.u64);
536  break;
537  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_2:
538  //Call platform
539  platform_packet_set_wlan_address_2(pkt, action->__field.u64);
540  break;
541  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_3:
542  //Call platform
543  platform_packet_set_wlan_address_3(pkt, action->__field.u64);
544  break;
545  case OF1X_AT_POP_WLAN:
546  //Call platform
547  platform_packet_pop_wlan(pkt);
548  break;
549  case OF1X_AT_PUSH_WLAN:
550  //Call platform
551  platform_packet_push_wlan(pkt);
552  break;
553 
554  //GRE
555  case OF1X_AT_SET_FIELD_GRE_VERSION:
556  //Call platform
557  platform_packet_set_gre_version(pkt, action->__field.u16);
558  break;
559  case OF1X_AT_SET_FIELD_GRE_PROT_TYPE:
560  //Call platform
561  platform_packet_set_gre_prot_type(pkt, action->__field.u16);
562  break;
563  case OF1X_AT_SET_FIELD_GRE_KEY:
564  //Call platform
565  platform_packet_set_gre_key(pkt, action->__field.u32);
566  break;
567  case OF1X_AT_POP_GRE:
568  //Call platform
569  platform_packet_pop_gre(pkt, action->__field.u16);
570  break;
571  case OF1X_AT_PUSH_GRE:
572  //Call platform
573  platform_packet_push_gre(pkt, action->__field.u16);
574  break;
575 
576 #else
577  case OF1X_AT_POP_PPPOE:
578  case OF1X_AT_PUSH_PPPOE:
579  case OF1X_AT_SET_FIELD_PPPOE_CODE:
580  case OF1X_AT_SET_FIELD_PPPOE_TYPE:
581  case OF1X_AT_SET_FIELD_PPPOE_SID:
582  case OF1X_AT_SET_FIELD_PPP_PROT:
583  case OF1X_AT_SET_FIELD_GTP_MSG_TYPE:
584  case OF1X_AT_SET_FIELD_GTP_TEID:
585  case OF1X_AT_POP_GTP:
586  case OF1X_AT_PUSH_GTP:
587  case OF1X_AT_SET_FIELD_CAPWAP_WBID:
588  case OF1X_AT_SET_FIELD_CAPWAP_RID:
589  case OF1X_AT_SET_FIELD_CAPWAP_FLAGS:
590  case OF1X_AT_POP_CAPWAP:
591  case OF1X_AT_PUSH_CAPWAP:
592  case OF1X_AT_SET_FIELD_WLAN_FC:
593  case OF1X_AT_SET_FIELD_WLAN_TYPE:
594  case OF1X_AT_SET_FIELD_WLAN_SUBTYPE:
595  case OF1X_AT_SET_FIELD_WLAN_DIRECTION:
596  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_1:
597  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_2:
598  case OF1X_AT_SET_FIELD_WLAN_ADDRESS_3:
599  case OF1X_AT_POP_WLAN:
600  case OF1X_AT_PUSH_WLAN:
601  case OF1X_AT_SET_FIELD_GRE_VERSION:
602  case OF1X_AT_SET_FIELD_GRE_PROT_TYPE:
603  case OF1X_AT_SET_FIELD_GRE_KEY:
604  case OF1X_AT_POP_GRE:
605  case OF1X_AT_PUSH_GRE:
606  break;
607 #endif
608  //PBB
609  case OF1X_AT_SET_FIELD_PBB_ISID:
610  //Call platform
611  platform_packet_set_pbb_isid(pkt, action->__field.u32);
612  break;
613  case OF1X_AT_POP_PBB:
614  //Call platform
616  break;
617  case OF1X_AT_PUSH_PBB:
618  //Call platform
619  platform_packet_push_pbb(pkt, action->__field.u16);
620  break;
621 
622  //TUNNEL ID
623  case OF1X_AT_SET_FIELD_TUNNEL_ID:
624  //Call platform
625  platform_packet_set_tunnel_id(pkt, action->__field.u64);
626  break;
627 
628  case OF1X_AT_GROUP:
629  __of1x_process_group_actions(tid, sw, table_id, pkt, action->__field.u32, action->group, replicate_pkts);
630  break;
631 
632  case OF1X_AT_EXPERIMENTER: //FIXME: implement
633  break;
634 
635  case OF1X_AT_OUTPUT:
636 
637  //Store in automatic
638  port_id = action->__field.u32;
639 
640  //Pointer for the packet to be sent
641  datapacket_t* pkt_to_send;
642 
643  //Duplicate the packet only if necessary
644  if(replicate_pkts){
645  pkt_to_send = platform_packet_replicate(pkt);
646 
647  //check for wrong copy
648  if(unlikely(pkt_to_send == NULL)){
649  ROFL_PIPELINE_INFO("Packet[%p] could NOT be cloned during OUTPUT action\n", pkt);
650  return;
651  }
652  pkt_to_send->__cookie = pkt->__cookie;
653  ROFL_PIPELINE_INFO("Packet[%p] was cloned into [%p] during OUTPUT action\n", pkt, pkt_to_send);
654 
655  }else
656  pkt_to_send = pkt;
657 
658  //Perform output
659  if( port_id < LOGICAL_SWITCH_MAX_LOG_PORTS && unlikely(NULL != sw->logical_ports[port_id].port) ){
660 
661  //Single port output
662  //According to the spec a packet cannot be sent to the incoming port
663  //unless IN_PORT meta port is used
664  if(unlikely(port_id == *platform_packet_get_port_in(pkt))){
665  ROFL_PIPELINE_DEBUG("Packet[%p] dropped. Attempting to output to the incoming port %u\n", pkt_to_send, port_id);
666  platform_packet_drop(pkt_to_send);
667  }else{
668 #ifdef DEBUG
669  dump_packet_matches(pkt_to_send, false);
670 #endif
671  ROFL_PIPELINE_INFO("Packet[%p] outputting to port num. %u\n", pkt_to_send, port_id);
672  platform_packet_output(pkt_to_send, sw->logical_ports[port_id].port);
673  }
674 
675  }else if(port_id == OF1X_PORT_FLOOD){
676  //Flood
677  ROFL_PIPELINE_INFO("Packet[%p] outputting to FLOOD\n", pkt_to_send);
679  }else if(port_id == OF1X_PORT_CONTROLLER ||
680  port_id == OF1X_PORT_NORMAL){
681  //Controller
682  ROFL_PIPELINE_INFO("Packet[%p] outputting to CONTROLLER\n", pkt_to_send);
683  platform_of1x_packet_in(sw, table_id, pkt_to_send, action->send_len, OF1X_PKT_IN_ACTION);
684  }else if(port_id == OF1X_PORT_ALL){
685  //All
686  ROFL_PIPELINE_INFO("Packet[%p] outputting to ALL_PORT\n", pkt_to_send);
688  }else if(port_id == OF1X_PORT_IN_PORT){
689  //in port
690  ROFL_PIPELINE_INFO("Packet[%p] outputting to IN_PORT\n", pkt_to_send);
692  }else if(port_id == OF1X_PORT_TABLE){
693  if(likely(reinject_pkt != NULL)){
694  //OFPP_TABLE
695  ROFL_PIPELINE_INFO("Packet[%p] reinjecting pkt to the sw(%p) pipeline\n", sw, pkt_to_send);
696  *reinject_pkt = pkt_to_send;
697  assert(action->next == NULL);
698  return;
699  }else{
700  ROFL_PIPELINE_INFO("ERROR: packet[%p->%p] trying to execute an output to meta-port 'TABLE' from a non-PKT_OUT action list.\n", pkt, pkt_to_send);
701  assert(0);
702  }
704  }else{
705  //This condition can only happen when flowmods are left for ports that are non-existent anymore
706  //or port id has been corrupted
707  ROFL_PIPELINE_INFO("Packet[%p] WARNING output to UNKNOWN port %u. Dropping...\n", pkt_to_send, port_id);
708 
709  //Drop the pkt
710  platform_packet_drop(pkt_to_send);
711  }
712  break;
713  }
714 }
715 
716 
717 
718 //Process apply actions
719 static inline void __of1x_process_apply_actions(const unsigned int tid, const struct of1x_switch* sw, const unsigned int table_id, datapacket_t* pkt, const of1x_action_group_t* apply_actions_group, bool replicate_pkts, datapacket_t** reinject_pkt){
720 
722 
723  for(it=apply_actions_group->head;it;it=it->next){
724  __of1x_process_packet_action(tid, sw, table_id, pkt, it, replicate_pkts, reinject_pkt);
725  }
726 }
727 
728 /*
729 * The of1x_process_write_actions is meant to encapsulate the processing of the write actions
730 *
731 */
732 static inline void __of1x_process_write_actions(const unsigned int tid, const struct of1x_switch* sw, const unsigned int table_id, datapacket_t* pkt, bool replicate_pkts){
733 
734  unsigned int i,j;
735 
736  of1x_write_actions_t* write_actions = &pkt->write_actions.of1x;
737 
738  for(i=0,j=0;(i<write_actions->num_of_actions) && (j < OF1X_AT_NUMBER);j++){
739  if( bitmap128_is_bit_set(&write_actions->bitmap,j) ){
740  //Process action
741  __of1x_process_packet_action(tid, sw, table_id, pkt, &write_actions->actions[j], replicate_pkts, NULL);
742  i++;
743  }
744  }
745 }
746 
747 //C++ extern C
748 ROFL_END_DECLS
749 
750 #endif //OF1X_ACTION_PP
void platform_packet_pop_mpls(datapacket_t *pkt, uint16_t ether_type)
Pop outer-most MPLS tag, setting the BoS accordingly.
void platform_packet_set_pbb_isid(datapacket_t *pkt, uint32_t pbb_isid)
Set a new value for the PBB I-SID of the packet.
void platform_packet_set_tcp_dst(datapacket_t *pkt, uint16_t tcp_dst)
Set a new value for the TCP dst port.
void platform_packet_set_sctp_src(datapacket_t *pkt, uint16_t sctp_src)
Set a new value for the SCTP src port.
void platform_packet_set_nw_ttl(datapacket_t *pkt, uint8_t new_ttl)
Set new ttl value.
void platform_rwlock_rdlock(platform_rwlock_t *rwlock)
Performs a read-lock over the platform_rwlock_t mutex platform_mutex_init().
void platform_packet_push_vlan(datapacket_t *pkt, uint16_t ether_type)
Push a new 802.1q VLAN tag (outer-most)
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
void platform_packet_set_mpls_bos(datapacket_t *pkt, bool bos)
Set a new MPLS BoS value to the outer-most MPLS tag of the packet.
Packet action abstraction data structure.
Definition: of1x_action.h:278
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().
Group structure definition.
void platform_packet_output(datapacket_t *pkt, switch_port_t *port)
Output packet to the port(s) The action HAS to implement the destruction/release of the pkt (includin...
void platform_packet_set_arp_tha(datapacket_t *pkt, uint64_t arp_tha)
Set a new value for the ARP THA header field.
void platform_packet_set_mpls_ttl(datapacket_t *pkt, uint8_t new_ttl)
Set a new TTL value to the outer-most MPLS tag of the packet.
Group bucket.
static void bitmap128_clean(bitmap128_t *bitmap)
Set bitmap to 0.
Definition: bitmap.h:29
void platform_packet_set_udp_src(datapacket_t *pkt, uint16_t udp_src)
Set a new value for the UDP src port.
ROFL_BEGIN_DECLS uint32_t platform_packet_get_size_bytes(datapacket_t *const pkt)
Gets the complete packet size in bytes.
void platform_packet_set_icmpv6_code(datapacket_t *pkt, uint8_t icmpv6_code)
Set a new value for the ICMPv6 code.
void platform_packet_set_icmpv6_type(datapacket_t *pkt, uint8_t icmpv6_type)
Set a new value for the ICMPv6 type.
bool platform_packet_has_vlan(datapacket_t *const pkt)
Retrieves boolean if the packet contains a 802.1q VLAN tag.
void platform_packet_set_arp_tpa(datapacket_t *pkt, uint32_t arp_tpa)
Set a new value for the ARP TPA header field.
void platform_packet_set_arp_opcode(datapacket_t *pkt, uint16_t arp_opcode)
Set a new value for the ARP OPCODE header field.
void platform_packet_set_icmpv4_type(datapacket_t *pkt, uint8_t type)
Set a new value for the ICMPv4 type.
void platform_packet_set_sctp_dst(datapacket_t *pkt, uint16_t sctp_dst)
Set a new value for the SCTP dst port.
datapacket_t * platform_packet_replicate(datapacket_t *pkt)
Creates a copy (in heap) of the datapacket_t structure including any platform specific state (->platf...
Statistics related to packet processing routines.
switch_port_t * all_meta_port
Special meta port: ALL.
void platform_packet_pop_vlan(datapacket_t *pkt)
Pop the outer-most 802.1q VLAN tag.
Write actions structure.
Definition: of1x_action.h:330
void platform_packet_set_eth_dst(datapacket_t *pkt, uint64_t eth_dst)
Set a new Ethernet dst MAC address to the packet.
void platform_packet_pop_pbb(datapacket_t *pkt)
Pop outer-most PBB header.
void platform_packet_set_ip_ecn(datapacket_t *pkt, uint8_t ip_ecn)
Set a new value for the IP ECN header field.
uint16_t * platform_packet_get_eth_type(datapacket_t *const pkt)
Retrieve the Ethernet ETH_TYPE of the packet.
static bool bitmap128_is_bit_set(const bitmap128_t *bitmap, unsigned int pos)
Check if bit is set in the 128bit bitmap.
Definition: bitmap.h:45
void platform_packet_set_tcp_src(datapacket_t *pkt, uint16_t tcp_src)
Set a new value for the TCP src port.
void platform_packet_set_arp_spa(datapacket_t *pkt, uint32_t arp_spa)
Set a new value for the ARP SPA header field.
OpenFlow v1.0, 1.2 and 1.3.2 actions.
void platform_packet_set_ipv6_dst(datapacket_t *pkt, uint128__t ipv6_dst)
Set a new value for the IPv6 dst address.
void platform_packet_dec_nw_ttl(datapacket_t *pkt)
Decrement ttl.
void platform_packet_set_ipv6_flabel(datapacket_t *pkt, uint64_t ipv6_flabel)
Set a new value for the IPv6 label.
uint8_t * platform_packet_get_ip_proto(datapacket_t *const pkt)
Get the ip proto value of the packet.
Action group (apply-actions) structure.
Definition: of1x_action.h:303
void platform_packet_set_mpls_tc(datapacket_t *pkt, uint8_t tc)
Set a new TC value to the outer-most MPLS MPLS tag of the packet.
void platform_packet_set_queue(datapacket_t *pkt, uint32_t queue)
Set output queue of the packet.
void platform_of1x_packet_in(const of1x_switch_t *sw, uint8_t table_id, datapacket_t *pkt, uint16_t send_len, of_packet_in_reason_t reason)
Packet in event notification.
void platform_packet_set_ipv4_dst(datapacket_t *pkt, uint32_t ip_dst)
Set a new value for the IPv4 dst address.
void platform_packet_set_ipv4_src(datapacket_t *pkt, uint32_t ip_src)
Set a new value for the IPv4 src address.
void platform_packet_set_ipv6_nd_tll(datapacket_t *pkt, uint64_t ipv6_nd_tll)
Set a new value for the IPv6 nd tll.
void platform_packet_set_vlan_pcp(datapacket_t *pkt, uint8_t vlan_pcp)
Set a new VLAN PCP value to the outer-most VLAN of the packet.
void platform_packet_set_mpls_label(datapacket_t *pkt, uint32_t label)
Set a new label to the outer-most MPLS tag of the packet.
void platform_packet_push_mpls(datapacket_t *pkt, uint16_t ether_type)
Push a new MPLS tag (outer-most), and set inner and outer tag BoS accordingly.
uint32_t * platform_packet_get_port_in(datapacket_t *const pkt)
Retrieves the port in identifier (position in the of1x_switch_t->logical_ports array) where the packe...
void platform_packet_set_udp_dst(datapacket_t *pkt, uint16_t udp_dst)
Set a new value for the UDP dst port.
void platform_packet_copy_ttl_out(datapacket_t *pkt)
Copy ttl out.
void platform_packet_set_eth_src(datapacket_t *pkt, uint64_t eth_src)
Set a new Ethernet src MAC address to the packet.
void dump_packet_matches(datapacket_t *const pkt, bool raw_nbo)
Dump the values of packet (header values)
void platform_packet_set_ipv6_exthdr(datapacket_t *pkt, uint16_t ipv6_exthdr)
Set a new value for the IPv6 exthdr.
Data packet abstraction.
Definition: datapacket.h:49
void platform_packet_set_ipv6_nd_target(datapacket_t *pkt, uint128__t ipv6_nd_target)
Set a new value for the IPv6 nd target.
void platform_packet_set_ipv6_src(datapacket_t *pkt, uint128__t ipv6_src)
Set a new value for the IPv6 src address.
void platform_packet_set_arp_sha(datapacket_t *pkt, uint64_t arp_sha)
Set a new value for the ARP SHA header field.
void platform_packet_set_ip_dscp(datapacket_t *pkt, uint8_t ip_dscp)
Set a new value for the IP DSCP header field.
void platform_packet_dec_mpls_ttl(datapacket_t *pkt)
Decrement the ttl from the outer-most MPLS tag of the packet.
void platform_packet_set_icmpv4_code(datapacket_t *pkt, uint8_t code)
Set a new value for the ICMPv4 code.
void platform_packet_set_tunnel_id(datapacket_t *pkt, uint64_t tunnel_id)
Set Tunnel ID.
void platform_packet_set_ipv6_nd_sll(datapacket_t *pkt, uint64_t ipv6_nd_sll)
Set a new value for the IPv6 nd sll.
void platform_packet_drop(datapacket_t *pkt)
Creates a copy (in heap) of the datapacket_t structure including any platform specific state (->platf...
void platform_packet_push_pbb(datapacket_t *pkt, uint16_t ether_type)
Push PBB header (outer-most)
switch_port_t * in_port_meta_port
Special meta port: IN_PORT.
void platform_packet_set_eth_type(datapacket_t *pkt, uint16_t eth_type)
Set a new ETH_TYPE to the packet if it is 802.X.
void platform_packet_set_vlan_vid(datapacket_t *pkt, uint16_t vlan_vid)
Set a new VLAN VID value to the outer-most VLAN of the packet.
void platform_packet_copy_ttl_in(datapacket_t *pkt)
Copy ttl in.
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.
void platform_packet_set_ip_proto(datapacket_t *pkt, uint8_t ip_proto)
Set a new value for the IP PROTO header field.
switch_port_t * flood_meta_port
Special meta port: FLOOD.
static void bitmap128_set(bitmap128_t *bitmap, unsigned int pos)
Set a bit in the 128bit bitmap.
Definition: bitmap.h:55