private void populateRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
    String osSubNetId = host.annotations().value(SUBNET_ID);
    if (osSubNetId == null) {
      return;
    }

    DeviceId localDevice = host.location().deviceId();
    PortNumber localPort = host.location().port();
    if (!nodeService.dataIp(localDevice).isPresent()) {
      log.warn("Failed to populate L3 rules");
      return;
    }

    Map<String, String> vniMap = new HashMap<>();
    openstackService.networks().stream().forEach(n -> vniMap.put(n.id(), n.segmentId()));

    // TODO improve pipeline, do we have to install access rules between networks
    // for every single VMs?
    osSubNets
        .stream()
        .filter(osSubNet -> !osSubNet.id().equals(osSubNetId))
        .forEach(
            osSubNet -> {
              populateRoutingRulestoSameNode(
                  host.ipAddresses().stream().findFirst().get().getIp4Address(),
                  host.mac(),
                  localPort,
                  localDevice,
                  Long.valueOf(vniMap.get(osSubNet.networkId())),
                  osSubNet.cidr());

              nodeService
                  .completeNodes()
                  .stream()
                  .filter(node -> node.type().equals(COMPUTE))
                  .filter(node -> !node.intBridge().equals(localDevice))
                  .forEach(
                      node ->
                          populateRoutingRulestoDifferentNode(
                              host.ipAddresses().stream().findFirst().get().getIp4Address(),
                              Long.valueOf(vniMap.get(osSubNet.networkId())),
                              node.intBridge(),
                              nodeService.dataIp(localDevice).get().getIp4Address(),
                              osSubNet.cidr()));
            });
  }