/**
  * @param $contextVSYS VirtualSystem
  * @param $orderByNarrowest bool
  * @return array
  */
 public function getIPtoZoneRouteMapping($contextVSYS, $orderByNarrowest = true)
 {
     $ipv4 = array();
     $ipv6 = array();
     $ipv4sort = array();
     foreach ($this->staticRoutes() as $route) {
         $ipv4Mapping = $route->destinationIP4Mapping();
         $nexthopIf = $route->nexthopInterface();
         if ($nexthopIf !== null) {
             if (!$this->attachedInterfaces->hasInterfaceNamed($nexthopIf->name())) {
                 mwarning("route {$route->name()}/{$route->destination()} ignored because its attached to interface {$nexthopIf->name()} but this interface does not belong to this virtual router'");
                 continue;
             }
             if ($contextVSYS->importedInterfaces->hasInterfaceNamed($nexthopIf->name())) {
                 $findZone = $contextVSYS->zoneStore->findZoneMatchingInterfaceName($nexthopIf->name());
                 if ($findZone === null) {
                     mwarning("route {$route->name()}/{$route->destination()} ignored because its attached to interface {$nexthopIf->name()} but this interface is not attached to a Zone in vsys {$contextVSYS->name()}'");
                     continue;
                 } else {
                     $record = array('network' => $route->destination(), 'start' => $ipv4Mapping['start'], 'end' => $ipv4Mapping['end'], 'zone' => $findZone->name(), 'origin' => 'static', 'priority' => 2);
                     $ipv4sort[$record['end'] - $record['start']][$record['start']][] =& $record;
                     unset($record);
                 }
             } else {
                 $findVsys = $contextVSYS->owner->network->findVsysInterfaceOwner($nexthopIf->name());
                 if ($findVsys === null) {
                     mwarning("route {$route->name()}/{$route->destination()} ignored because its attached to interface {$nexthopIf->name()} but this interface is attached to no VSYS");
                     continue;
                 }
                 $externalZone = $contextVSYS->zoneStore->findZoneWithExternalVsys($findVsys);
                 if ($externalZone == null) {
                     mwarning("route {$route->name()}/{$route->destination()} ignored because its attached to interface {$nexthopIf->name()} but this interface is attached to wrong vsys '{$findVsys->name()}' and no external zone could be found");
                     continue;
                 }
                 $record = array('network' => $route->destination(), 'start' => $ipv4Mapping['start'], 'end' => $ipv4Mapping['end'], 'zone' => $externalZone->name(), 'origin' => 'static', 'priority' => 2);
                 $ipv4sort[$record['end'] - $record['start']][$record['start']][] =& $record;
                 unset($record);
             }
         } else {
             if ($route->nexthopType() == 'ip-address') {
                 $nextHopType = $route->nexthopType();
                 $nexthopIP = $route->nexthopIP();
                 $findZone = null;
                 foreach ($this->attachedInterfaces->interfaces() as $if) {
                     if (($if->isEthernetType() || $if->isAggregateType()) && $if->type() == 'layer3' || $if->isLoopbackType()) {
                         if (!$contextVSYS->importedInterfaces->hasInterfaceNamed($if->name())) {
                             continue;
                         }
                         if ($if->isLoopbackType()) {
                             $ips = $if->getIPv4Addresses();
                         } else {
                             $ips = $if->getLayer3IPv4Addresses();
                         }
                         foreach ($ips as &$interfaceIP) {
                             if (cidr::netMatch($nexthopIP, $interfaceIP) > 0) {
                                 $findZone = $contextVSYS->zoneStore->findZoneMatchingInterfaceName($if->name());
                                 if ($findZone === null) {
                                     mwarning("route {$route->name()}/{$route->destination()} ignored because its attached to interface {$if->name()} but this interface is not attached to a Zone in vsys {$contextVSYS->name()}'");
                                     continue;
                                 }
                                 break;
                             }
                         }
                         if ($findZone !== null) {
                             break;
                         }
                     } else {
                         continue;
                     }
                 }
                 if ($findZone === null) {
                     mwarning("route {$route->name()}/{$route->destination()} ignored because no matching interface was found for nexthop={$nexthopIP}");
                     continue;
                 }
                 $record = array('network' => $route->destination(), 'start' => $ipv4Mapping['start'], 'end' => $ipv4Mapping['end'], 'zone' => $findZone->name(), 'origin' => 'static', 'priority' => 2);
                 $ipv4sort[$record['end'] - $record['start']][$record['start']][] =& $record;
                 unset($record);
             } else {
                 mwarning("route {$route->name()}/{$route->destination()} ignored because of unknown type '{$nextHopType}'");
                 continue;
             }
         }
     }
     foreach ($this->attachedInterfaces->interfaces() as $if) {
         if (!$contextVSYS->importedInterfaces->hasInterfaceNamed($if->name())) {
             continue;
         }
         if (($if->isEthernetType() || $if->isAggregateType()) && $if->type() == 'layer3') {
             $findZone = $contextVSYS->zoneStore->findZoneMatchingInterfaceName($if->name());
             if ($findZone === null) {
                 continue;
             }
             $ipAddresses = $if->getLayer3IPv4Addresses();
             foreach ($ipAddresses as $interfaceIP) {
                 $ipv4Mapping = cidr::stringToStartEnd($interfaceIP);
                 $record = array('network' => $interfaceIP, 'start' => $ipv4Mapping['start'], 'end' => $ipv4Mapping['end'], 'zone' => $findZone->name(), 'origin' => 'connected', 'priority' => 1);
                 $ipv4sort[$record['end'] - $record['start']][$record['start']][] =& $record;
                 unset($record);
             }
         } elseif ($if->isLoopbackType()) {
             $findZone = $contextVSYS->zoneStore->findZoneMatchingInterfaceName($if->name());
             if ($findZone === null) {
                 continue;
             }
             $ipAddresses = $if->getIPv4Addresses();
             foreach ($ipAddresses as $interfaceIP) {
                 $ipv4Mapping = cidr::stringToStartEnd($interfaceIP);
                 $record = array('network' => $interfaceIP, 'start' => $ipv4Mapping['start'], 'end' => $ipv4Mapping['end'], 'zone' => $findZone->name(), 'origin' => 'connected', 'priority' => 1);
                 $ipv4sort[$record['end'] - $record['start']][$record['start']][] =& $record;
                 unset($record);
             }
         }
     }
     ksort($ipv4sort);
     foreach ($ipv4sort as &$record) {
         ksort($record);
         foreach ($record as &$subRecord) {
             foreach ($subRecord as &$subSubRecord) {
                 $ipv4[] =& $subSubRecord;
             }
         }
     }
     $result = array('ipv4' => &$ipv4, 'ipv6' => &$ipv6);
     return $result;
 }