ROFL-pipeline  v0.6.0dev
of1x_pipeline_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_PIPELINE_PP_H__
6 #define __OF1X_PIPELINE_PP_H__
7 
8 #include "rofl.h"
9 #include "../../../util/pp_guard.h" //Never forget to include the guard
10 #include "../of1x_switch.h"
11 #include "of1x_pipeline.h"
12 #include "of1x_flow_table_pp.h"
13 #include "of1x_instruction_pp.h"
14 #include "of1x_statistics_pp.h"
15 
16 //This block is not necessary but it is useful to prevent
17 //double definitions of static inline methods
18 #include "of1x_action.h"
19 #include "of1x_instruction.h"
20 #include "of1x_flow_table.h"
21 #include "of1x_group_table.h"
22 #include "of1x_timers.h"
23 
24 //Platform stuff
25 #include "../../../platform/lock.h"
26 #include "../../../platform/likely.h"
27 #include "../../../platform/memory.h"
28 #include "../../../platform/packet.h"
29 #include "../../../platform/atomic_operations.h"
30 #include "../of1x_async_events_hooks.h"
31 
32 #include "matching_algorithms/available_ma_pp.h"
33 
34 #include "../../../util/logging.h"
35 
36 
44 //C++ extern C
45 ROFL_BEGIN_DECLS
46 
47 
48 /*
49 * Packet processing through pipeline
50 *
51 */
52 static inline void __of1x_process_packet_pipeline(const unsigned int tid, const of_switch_t *sw, datapacket_t *const pkt){
53 
54  //Loop over tables
55  unsigned int i, table_to_go, num_of_outputs;
56  of1x_flow_table_t* table;
57  of1x_flow_entry_t* match;
58 
59  //Initialize packet for OF1.X pipeline processing
60  __init_packet_metadata(pkt);
61  __of1x_init_packet_write_actions(&pkt->write_actions.of1x);
62 
63  //Mark packet as being processed by this sw
64  pkt->sw = sw;
65 
66  ROFL_PIPELINE_INFO("Packet[%p] entering switch %s [%p] pipeline (1.X)\n",pkt,sw->name, sw);
67 
68  for(i=OF1X_FIRST_FLOW_TABLE_INDEX; i < ((of1x_switch_t*)sw)->pipeline.num_of_tables ; i++){
69 
70  table = &((of1x_switch_t*)sw)->pipeline.tables[i];
71 
72 #ifdef ROFL_PIPELINE_LOCKLESS
73  //Mark core presence
74  tid_mark_as_present(tid, &table->tid_presence_mask);
75 #endif
76 
77 #ifdef DEBUG
78  dump_packet_matches(pkt, false);
79 #endif
80 
81  //Perform lookup
82  match = __of1x_find_best_match_table(tid, (of1x_flow_table_t* const)table, pkt);
83 
84  if(likely(match != NULL)){
85 
86  //store cookie field of this last match in pkt
87  pkt->__cookie = match->cookie;
88 
89  ROFL_PIPELINE_INFO("Packet[%p] matched at table: %u, entry: %p\n", pkt, i,match);
90 
91  //Update table and entry statistics
92  __of1x_stats_table_update_match(tid, &table->stats);
93 
94  //Update flow statistics
95  __of1x_stats_flow_update_match(tid, &match->stats, platform_packet_get_size_bytes(pkt));
96 
97  //Process instructions
98  table_to_go = __of1x_process_instructions(tid, (of1x_switch_t*)sw, i, pkt, &match->inst_grp);
99 
100  if(table_to_go > i && likely(table_to_go < OF1X_MAX_FLOWTABLES)){
101 
102  ROFL_PIPELINE_INFO("Packet[%p] Going to table %u->%u\n",pkt, i,table_to_go);
103  i = table_to_go-1;
104 
105 #ifdef ROFL_PIPELINE_LOCKLESS
106  //Unmark core presence in the table
107  tid_mark_as_not_present(tid, &table->tid_presence_mask);
108 #else
109  //Unlock the entry so that it can eventually be modified/deleted
110  platform_rwlock_rdunlock(match->rwlock);
111 #endif
112  continue;
113  }
114 
115  //Process WRITE actions
116  __of1x_process_write_actions(tid, (of1x_switch_t*)sw, i, pkt, __of1x_process_instructions_must_replicate(&match->inst_grp));
117 
118  //Recover the num_of_outputs to release the lock asap
119  num_of_outputs = match->inst_grp.num_of_outputs;
120 
121 #ifdef ROFL_PIPELINE_LOCKLESS
122  //Unmark core presence in the table
123  tid_mark_as_not_present(tid, &table->tid_presence_mask);
124 #else
125  //Unlock the entry so that it can eventually be modified/deleted
126  platform_rwlock_rdunlock(match->rwlock);
127 #endif
128 
129  //Drop packet Only if there has been copy(cloning of the packet) due to
130  //multiple output actions
131  if(num_of_outputs != 1)
133 
134  return;
135  }else{
136 #ifdef ROFL_PIPELINE_LOCKLESS
137  //Unmark core presence in the table
138  tid_mark_as_not_present(tid, &table->tid_presence_mask);
139 #endif
140 
141  //Update table statistics
142  __of1x_stats_table_update_no_match(tid, &table->stats);
143 
144  //Not matched, look for table_miss behaviour
145  if(table->default_action == OF1X_TABLE_MISS_DROP){
146 
147  ROFL_PIPELINE_INFO("Packet[%p] table MISS_DROP %u\n",pkt, i);
149  return;
150 
151  }else if(table->default_action == OF1X_TABLE_MISS_CONTROLLER){
152 
153  ROFL_PIPELINE_INFO("Packet[%p] table MISS_CONTROLLER. Generating a PACKET_IN event towards the controller\n",pkt);
154 
155  platform_of1x_packet_in((of1x_switch_t*)sw, i, pkt, ((of1x_switch_t*)sw)->pipeline.miss_send_len, OF1X_PKT_IN_NO_MATCH);
156  return;
157  }
158  //else -> continue with the pipeline
159  }
160  }
161 
162  //No match/default table action -> DROP the packet
164 
165 }
166 
171 static inline void of1x_process_packet_out_pipeline(const unsigned int tid, const of1x_switch_t *sw, datapacket_t *const pkt, const of1x_action_group_t* apply_actions_group){
172 
173  bool has_multiple_outputs=false;
174  datapacket_t* reinject_pkt=NULL;
175  of1x_group_table_t *gt = sw->pipeline.groups;
176 
177  //Validate apply_actions_group
178  __of1x_validate_action_group(NULL, (of1x_action_group_t*)apply_actions_group, gt, true);
179 
180 #ifdef DEBUG
181  ROFL_PIPELINE_INFO("Packet[%p] Processing PKT_OUT, action group: ",pkt);
182  __of1x_dump_action_group((of1x_action_group_t*)apply_actions_group, false);
183  ROFL_PIPELINE_INFO_NO_PREFIX("\n");
184 #endif
185 
186  if(apply_actions_group->num_of_output_actions == 0){
187  //No output actions or groups; drop and return
188  ROFL_PIPELINE_INFO("Packet[%p] WARNING: dropping! No output/group actions.\n",pkt);
190  return;
191  }
192 
193  has_multiple_outputs = (apply_actions_group->num_of_output_actions > 1);
194 
195 
196  //Just process the action group
197  __of1x_process_apply_actions(tid, (of1x_switch_t*)sw, 0, pkt, apply_actions_group, has_multiple_outputs, &reinject_pkt);
198 
199  //Reinject if necessary
200  if(reinject_pkt)
201  __of1x_process_packet_pipeline(ROFL_PIPELINE_LOCKED_TID, (const of_switch_t*)sw, reinject_pkt);
202 
203  if(has_multiple_outputs){
204  //Packet was replicated. Drop original packet
205  ROFL_PIPELINE_DEBUG("Packet[%p] Dropping original pkt (previously cloned due to multiple output actions).\n", pkt);
207  }
208 }
209 
210 //C++ extern C
211 ROFL_END_DECLS
212 
213 #endif //OF1X_PIPELINE_PP
OpenFlow-enabled switch abstraction (version-indepedent part).
Definition: of_switch.h:55
OpenFlow v1.0, 1.2 and 1.3.2 pipeline abstraction.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
OpenFlow-enabled v1.0, 1.2 and 1.3.2 switch abstraction.
Definition: of1x_switch.h:28
void platform_rwlock_rdunlock(platform_rwlock_t *rwlock)
Performs a read-unlock over the platform_rwlock_t mutex platform_mutex_init().
static void of1x_process_packet_out_pipeline(const unsigned int tid, const of1x_switch_t *sw, datapacket_t *const pkt, const of1x_action_group_t *apply_actions_group)
Processes a packet-out through the OpenFlow pipeline.
OpenFlow v1.0, 1.2 and 1.3.2 flow entry structure.
ROFL_BEGIN_DECLS uint32_t platform_packet_get_size_bytes(datapacket_t *const pkt)
Gets the complete packet size in bytes.
OpenFlow v1.X instructions.
Statistics related to packet processing routines.
OpenFlow v1.0, 1.2 and 1.3.2 flow table abstraction.
OpenFlow v1.0, 1.2 and 1.3.2 actions.
Action group (apply-actions) structure.
Definition: of1x_action.h:303
OpenFlow v1.0, 1.2 and 1.3.2 timers subsystem.
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.
static unsigned int __of1x_process_instructions(const unsigned int tid, const struct of1x_switch *sw, const unsigned int table_id, datapacket_t *const pkt, const of1x_instruction_group_t *instructions)
void dump_packet_matches(datapacket_t *const pkt, bool raw_nbo)
Dump the values of packet (header values)
OpenFlow v1.X instructions packet processing routines.
Data packet abstraction.
Definition: datapacket.h:49
void platform_packet_drop(datapacket_t *pkt)
Creates a copy (in heap) of the datapacket_t structure including any platform specific state (->platf...
OpenFlow v1.0, 1.2 and 1.3.2 group table subsystem.