2121import com .google .common .collect .Maps ;
2222import com .google .common .util .concurrent .Futures ;
2323import com .google .common .util .concurrent .Striped ;
24+ import org .onosproject .drivers .p4runtime .mirror .P4RuntimeDefaultEntryMirror ;
2425import org .onosproject .drivers .p4runtime .mirror .P4RuntimeTableMirror ;
2526import org .onosproject .drivers .p4runtime .mirror .TimedEntry ;
2627import org .onosproject .net .flow .DefaultFlowEntry ;
2728import org .onosproject .net .flow .FlowEntry ;
2829import org .onosproject .net .flow .FlowRule ;
2930import org .onosproject .net .flow .FlowRuleProgrammable ;
3031import org .onosproject .net .pi .model .PiCounterType ;
31- import org .onosproject .net .pi .model .PiPipelineInterpreter ;
3232import org .onosproject .net .pi .model .PiPipelineModel ;
3333import org .onosproject .net .pi .model .PiTableId ;
3434import org .onosproject .net .pi .runtime .PiCounterCell ;
3737import org .onosproject .net .pi .runtime .PiCounterCellId ;
3838import org .onosproject .net .pi .runtime .PiEntityType ;
3939import org .onosproject .net .pi .runtime .PiHandle ;
40+ import org .onosproject .net .pi .runtime .PiMatchKey ;
4041import org .onosproject .net .pi .runtime .PiTableEntry ;
4142import org .onosproject .net .pi .runtime .PiTableEntryHandle ;
4243import org .onosproject .net .pi .service .PiFlowRuleTranslator ;
5859import java .util .concurrent .locks .Lock ;
5960import java .util .stream .Collectors ;
6061
61- import static org .onosproject .drivers .p4runtime .P4RuntimeDriverUtils .getInterpreter ;
62+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DEFAULT_DELETE_BEFORE_UPDATE ;
63+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES ;
64+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DEFAULT_READ_FROM_MIRROR ;
65+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY ;
66+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DEFAULT_SUPPORT_TABLE_COUNTERS ;
67+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .DELETE_BEFORE_UPDATE ;
68+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .READ_COUNTERS_WITH_TABLE_ENTRIES ;
69+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .READ_FROM_MIRROR ;
70+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .SUPPORT_DEFAULT_TABLE_ENTRY ;
71+ import static org .onosproject .drivers .p4runtime .P4RuntimeDriverProperties .SUPPORT_TABLE_COUNTERS ;
6272import static org .onosproject .drivers .p4runtime .P4RuntimeFlowRuleProgrammable .Operation .APPLY ;
6373import static org .onosproject .drivers .p4runtime .P4RuntimeFlowRuleProgrammable .Operation .REMOVE ;
6474import static org .onosproject .net .flow .FlowEntry .FlowEntryState .ADDED ;
@@ -73,40 +83,14 @@ public class P4RuntimeFlowRuleProgrammable
7383 extends AbstractP4RuntimeHandlerBehaviour
7484 implements FlowRuleProgrammable {
7585
76- // When updating an existing rule, if true, we issue a DELETE operation
77- // before inserting the new one, otherwise we issue a MODIFY operation. This
78- // is useful fore devices that do not support MODIFY operations for table
79- // entries.
80- private static final String DELETE_BEFORE_UPDATE = "tableDeleteBeforeUpdate" ;
81- private static final boolean DEFAULT_DELETE_BEFORE_UPDATE = false ;
82-
83- // If true, we avoid querying the device and return what's already known by
84- // the ONOS store.
85- private static final String READ_FROM_MIRROR = "tableReadFromMirror" ;
86- private static final boolean DEFAULT_READ_FROM_MIRROR = false ;
87-
88- // If true, we read counters when reading table entries (if table has
89- // counters). Otherwise, we don't.
90- private static final String SUPPORT_TABLE_COUNTERS = "supportTableCounters" ;
91- private static final boolean DEFAULT_SUPPORT_TABLE_COUNTERS = true ;
92-
93- // If true, assumes that the device returns table entry message populated
94- // with direct counter values. If false, we issue a second P4Runtime request
95- // to read the direct counter values.
96- private static final String READ_COUNTERS_WITH_TABLE_ENTRIES = "tableReadCountersWithTableEntries" ;
97- private static final boolean DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES = true ;
98-
99- // True if target supports reading and writing table entries.
100- private static final String SUPPORT_DEFAULT_TABLE_ENTRY = "supportDefaultTableEntry" ;
101- private static final boolean DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY = true ;
102-
10386 // Used to make sure concurrent calls to write flow rules are serialized so
10487 // that each request gets consistent access to mirror state.
10588 private static final Striped <Lock > WRITE_LOCKS = Striped .lock (30 );
10689
10790 private PiPipelineModel pipelineModel ;
10891 private P4RuntimeTableMirror tableMirror ;
10992 private PiFlowRuleTranslator translator ;
93+ private P4RuntimeDefaultEntryMirror defaultEntryMirror ;
11094
11195 @ Override
11296 protected boolean setupBehaviour (String opName ) {
@@ -118,6 +102,7 @@ protected boolean setupBehaviour(String opName) {
118102 pipelineModel = pipeconf .pipelineModel ();
119103 tableMirror = handler ().get (P4RuntimeTableMirror .class );
120104 translator = translationService .flowRuleTranslator ();
105+ defaultEntryMirror = handler ().get (P4RuntimeDefaultEntryMirror .class );
121106 return true ;
122107 }
123108
@@ -128,7 +113,8 @@ public Collection<FlowEntry> getFlowEntries() {
128113 return Collections .emptyList ();
129114 }
130115
131- if (driverBoolProperty (READ_FROM_MIRROR , DEFAULT_READ_FROM_MIRROR )) {
116+ if (driverBoolProperty (READ_FROM_MIRROR ,
117+ DEFAULT_READ_FROM_MIRROR )) {
132118 return getFlowEntriesFromMirror ();
133119 }
134120
@@ -237,8 +223,12 @@ private FlowEntry forgeFlowEntry(PiTableEntry entry,
237223 translatedEntity = translator .lookup (handle );
238224 final TimedEntry <PiTableEntry > timedEntry = tableMirror .get (handle );
239225
226+ // A default entry might not be present in the translation store if it
227+ // was not inserted by an app. No need to log.
240228 if (!translatedEntity .isPresent ()) {
241- log .warn ("Table entry handle not found in translation store: {}" , handle );
229+ if (!isOriginalDefaultEntry (entry )) {
230+ log .warn ("Table entry handle not found in translation store: {}" , handle );
231+ }
242232 return null ;
243233 }
244234 if (!translatedEntity .get ().translated ().equals (entry )) {
@@ -390,9 +380,11 @@ private boolean appendEntryToWriteRequestOrSkip(
390380 final UpdateType updateType ;
391381
392382 final boolean supportDefaultEntry = driverBoolProperty (
393- SUPPORT_DEFAULT_TABLE_ENTRY , DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY );
383+ SUPPORT_DEFAULT_TABLE_ENTRY ,
384+ DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY );
394385 final boolean deleteBeforeUpdate = driverBoolProperty (
395- DELETE_BEFORE_UPDATE , DEFAULT_DELETE_BEFORE_UPDATE );
386+ DELETE_BEFORE_UPDATE ,
387+ DEFAULT_DELETE_BEFORE_UPDATE );
396388
397389 if (driverOperation == APPLY ) {
398390 if (piEntryOnDevice == null ) {
@@ -419,8 +411,8 @@ private boolean appendEntryToWriteRequestOrSkip(
419411 } else {
420412 // REMOVE.
421413 if (piEntryToApply .isDefaultAction ()) {
422- // Cannot remove default action. Instead we should use the
423- // original defined by the interpreter (if any) .
414+ // Cannot remove default action. Instead we should modify it to
415+ // use the original one as specified in the P4 program .
424416 final PiTableEntry originalDefaultEntry = getOriginalDefaultEntry (
425417 piEntryToApply .table ());
426418 if (originalDefaultEntry == null ) {
@@ -443,31 +435,32 @@ private boolean appendEntryToWriteRequestOrSkip(
443435 }
444436
445437 private PiTableEntry getOriginalDefaultEntry (PiTableId tableId ) {
446- final PiPipelineInterpreter interpreter = getInterpreter (handler ());
447- if (interpreter == null ) {
448- log .warn ("Missing interpreter for {}, cannot get default action" ,
449- deviceId );
450- return null ;
451- }
452- if (!interpreter .getOriginalDefaultAction (tableId ).isPresent ()) {
453- log .warn ("Interpreter of {} doesn't define a default action for " +
454- "table {}, cannot produce default action entry" ,
455- deviceId , tableId );
456- return null ;
457- }
458- return PiTableEntry .builder ()
438+ final PiTableEntryHandle handle = PiTableEntry .builder ()
459439 .forTable (tableId )
460- .withAction (interpreter .getOriginalDefaultAction (tableId ).get ())
461- .build ();
440+ .withMatchKey (PiMatchKey .EMPTY )
441+ .build ()
442+ .handle (deviceId );
443+ final TimedEntry <PiTableEntry > originalDefaultEntry = defaultEntryMirror .get (handle );
444+ if (originalDefaultEntry != null ) {
445+ return originalDefaultEntry .entry ();
446+ }
447+ return null ;
462448 }
463449
464450 private boolean isOriginalDefaultEntry (PiTableEntry entry ) {
465451 if (!entry .isDefaultAction ()) {
466452 return false ;
467453 }
468454 final PiTableEntry originalDefaultEntry = getOriginalDefaultEntry (entry .table ());
469- return originalDefaultEntry != null &&
470- originalDefaultEntry .action ().equals (entry .action ());
455+ if (originalDefaultEntry == null ) {
456+ return false ;
457+ }
458+ // Sometimes the default action may be null
459+ // e.g. In basic pipeline, the default action in wcmp_table is null
460+ if (originalDefaultEntry .action () == null ) {
461+ return entry .action () == null ;
462+ }
463+ return originalDefaultEntry .action ().equals (entry .action ());
471464 }
472465
473466 private Map <PiTableEntryHandle , PiCounterCellData > readEntryCounters (
0 commit comments