[ONOS-7236] Supports simple IPv4 routing on fabric.p4

Change-Id: Ie92b26361b1d646491bd382f698c0f8f61a058a1
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractCriterionTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractCriterionTranslator.java
index d403ec1..4bbb123 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractCriterionTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractCriterionTranslator.java
@@ -127,6 +127,7 @@
                 break;
             case LPM:
                 mask = getMaskFromPrefixLength(prefixLength, value.size());
+                break;
             default:
                 throw new RuntimeException("Unrecognized init type " + initType.name());
         }
@@ -163,8 +164,7 @@
      * @return a byte sequence
      */
     private ImmutableByteSequence getMaskFromPrefixLength(int prefixLength, int maskSize) {
-        // TODO: implement.
-        throw new RuntimeException("getMaskFromPrefixLength() not implemented yet.");
+        return ImmutableByteSequence.prefixOnes(maskSize, prefixLength);
     }
 
     /**
@@ -175,7 +175,32 @@
      * @return optional prefix length
      */
     private Optional<Integer> getPrefixLengthFromMask(ImmutableByteSequence mask) {
-        // TODO: implement.
-        throw new RuntimeException("getPrefixLengthFromMask() not implemented yet.");
+        Integer prefixLength = 0;
+
+        byte[] byteArray = mask.asArray();
+        int byteArrayIndex = 0;
+        while (byteArrayIndex < byteArray.length && byteArray[byteArrayIndex] == (byte) 0xff) {
+            prefixLength += Byte.SIZE;
+            byteArrayIndex++;
+        }
+
+        byte byteVal = byteArray[byteArrayIndex];
+        while (byteVal != 0) {
+            if ((byteVal & Integer.MIN_VALUE) != Integer.MIN_VALUE) {
+                return Optional.empty();
+            }
+            prefixLength++;
+            byteVal <<= 1;
+        }
+
+        byteArrayIndex++;
+        while (byteArrayIndex < byteArray.length) {
+            if (byteArray[byteArrayIndex] != 0) {
+                return Optional.empty();
+            }
+            byteArrayIndex++;
+        }
+
+        return Optional.of(prefixLength);
     }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
index 1938c05..ee27ef2 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiCriterionTranslatorsTest.java
@@ -25,6 +25,7 @@
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onlab.util.ImmutableByteSequence;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.criteria.ArpHaCriterion;
 import org.onosproject.net.flow.criteria.ArpOpCriterion;
@@ -482,4 +483,35 @@
 
         assertThat(exactMatch.value().asReadOnlyBuffer().get(), is(criterion.ipEcn()));
     }
+
+    @Test
+    public void testLpmToTernaryTranslation() throws Exception {
+        IpPrefix ipPrefix = IpPrefix.valueOf("10.0.0.1/23");
+        int bitWidth = ipPrefix.address().toOctets().length * Byte.SIZE;
+
+        IPCriterion criterion = (IPCriterion) Criteria.matchIPDst(ipPrefix);
+        PiTernaryFieldMatch ternaryMatch =
+                (PiTernaryFieldMatch) translateCriterion(criterion, fieldId, TERNARY, bitWidth);
+
+        ImmutableByteSequence expectedMask = ImmutableByteSequence.prefixOnes(Integer.BYTES, 23);
+        ImmutableByteSequence expectedValue = ImmutableByteSequence.copyFrom(ipPrefix.address().toOctets());
+
+        assertThat(ternaryMatch.mask(), is(expectedMask));
+        assertThat(ternaryMatch.value(), is(expectedValue));
+    }
+
+    @Test
+    public void testTernaryToLpmTranslation() throws Exception {
+        EthCriterion criterion =
+                (EthCriterion) Criteria.matchEthDstMasked(MacAddress.ONOS,
+                                                          MacAddress.IPV4_MULTICAST_MASK);
+
+        PiLpmFieldMatch lpmMatch =
+                (PiLpmFieldMatch) translateCriterion(criterion, fieldId, LPM,
+                                                     MacAddress.MAC_ADDRESS_LENGTH * Byte.SIZE);
+        ImmutableByteSequence expectedValue = ImmutableByteSequence.copyFrom(MacAddress.ONOS.toBytes());
+
+        assertThat(lpmMatch.prefixLength(), is(25));
+        assertThat(lpmMatch.value(), is(expectedValue));
+    }
 }