From 76dc892491948adae5e5e62cf94448967e8d865b Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Sun, 6 Dec 2015 07:15:03 -0800 Subject: Fixes bad POM file with ONOS commit 8c68536972f63069c263635c9d9f4f31d7f3e9a2 Change-Id: I7adb5a2d3738d53dbc41db7577768b0e7ced5450 Signed-off-by: Ashlee Young --- build.sh | 58 +- framework/src/onos/apps/cpman/pom.xml | 39 + .../org/onosproject/cpman/ControlMessageType.java | 43 + .../org/onosproject/cpman/ControlMetricType.java | 34 + .../org/onosproject/cpman/ControlPlaneLoad.java | 42 + .../org/onosproject/cpman/ControlPlaneManager.java | 47 + .../org/onosproject/cpman/ControlPlaneMetric.java | 41 + .../cpman/ControlPlaneStatsService.java | 59 + .../java/org/onosproject/cpman/package-info.java | 20 + .../org/onosproject/dhcp/rest/DhcpWebResource.java | 8 +- .../src/onos/apps/faultmanagement/app/app.xml | 24 + .../src/onos/apps/faultmanagement/app/features.xml | 25 + .../src/onos/apps/faultmanagement/app/pom.xml | 46 + .../src/onos/apps/faultmanagement/fmmgr/pom.xml | 54 + .../faultmanagement/impl/AlarmsManager.java | 222 +++ .../faultmanagement/impl/package-info.java | 20 + .../src/onos/apps/faultmanagement/fmweb/pom.xml | 141 ++ .../faultmanagement/web/AlarmCodec.java | 101 ++ .../faultmanagement/web/AlarmsWebResource.java | 148 ++ .../faultmanagement/web/package-info.java | 20 + .../fmweb/src/main/webapp/WEB-INF/web.xml | 42 + .../faultmanagement/web/AlarmCodecContext.java | 73 + .../faultmanagement/web/AlarmCodecTest.java | 140 ++ .../faultmanagement/web/AlarmJsonMatcher.java | 135 ++ .../faultmanagement/web/AlarmsWebResourceTest.java | 72 + .../faultmanagement/web/alarm-full.json | 15 + .../faultmanagement/web/alarm-minimal.json | 12 + framework/src/onos/apps/faultmanagement/pom.xml | 56 + framework/src/onos/apps/iptopology-api/pom.xml | 29 + .../org/onosproject/iptopology/api/AreaId.java | 70 + .../org/onosproject/iptopology/api/AsNumber.java | 70 + .../java/org/onosproject/iptopology/api/Color.java | 72 + .../iptopology/api/DefaultDeviceIntf.java | 79 + .../iptopology/api/DefaultDevicePrefix.java | 95 ++ .../iptopology/api/DefaultIpDevice.java | 113 ++ .../onosproject/iptopology/api/DefaultIpLink.java | 105 ++ .../iptopology/api/DeviceInterface.java | 100 ++ .../org/onosproject/iptopology/api/DeviceIntf.java | 37 + .../onosproject/iptopology/api/DevicePrefix.java | 46 + .../org/onosproject/iptopology/api/DeviceTed.java | 173 ++ .../org/onosproject/iptopology/api/DomainId.java | 71 + .../iptopology/api/ExtendedRouteTag.java | 70 + .../org/onosproject/iptopology/api/IgpFlags.java | 114 ++ .../iptopology/api/InterfaceIdentifier.java | 71 + .../org/onosproject/iptopology/api/IpDevice.java | 68 + .../iptopology/api/IpDeviceIdentifier.java | 141 ++ .../org/onosproject/iptopology/api/IpLink.java | 54 + .../iptopology/api/IpLinkIdentifier.java | 161 ++ .../onosproject/iptopology/api/IpReachability.java | 73 + .../onosproject/iptopology/api/IsIsPseudonode.java | 93 ++ .../org/onosproject/iptopology/api/IsoNodeId.java | 79 + .../org/onosproject/iptopology/api/LinkTed.java | 349 ++++ .../org/onosproject/iptopology/api/Metric.java | 70 + .../onosproject/iptopology/api/OspfPseudonode.java | 96 ++ .../org/onosproject/iptopology/api/Position.java | 84 + .../iptopology/api/PrefixIdentifier.java | 98 ++ .../org/onosproject/iptopology/api/PrefixTed.java | 138 ++ .../onosproject/iptopology/api/ProtectionType.java | 97 ++ .../iptopology/api/RouteDistinguisher.java | 74 + .../iptopology/api/RouteIdentifier.java | 54 + .../onosproject/iptopology/api/RouteInstance.java | 70 + .../org/onosproject/iptopology/api/RouteTag.java | 70 + .../org/onosproject/iptopology/api/RouteType.java | 96 ++ .../org/onosproject/iptopology/api/RouterId.java | 78 + .../org/onosproject/iptopology/api/Signalling.java | 83 + .../java/org/onosproject/iptopology/api/Srlg.java | 70 + .../iptopology/api/TerminationPoint.java | 104 ++ .../org/onosproject/iptopology/api/TopologyId.java | 70 + .../api/device/DefaultInterfaceDescription.java | 97 ++ .../api/device/DefaultIpDeviceDescription.java | 117 ++ .../api/device/DefaultPrefixDescription.java | 86 + .../api/device/InterfaceDescription.java | 51 + .../iptopology/api/device/IpDeviceDescription.java | 61 + .../iptopology/api/device/IpDeviceEvent.java | 183 ++ .../iptopology/api/device/IpDeviceListener.java | 24 + .../iptopology/api/device/IpDeviceProvider.java | 25 + .../api/device/IpDeviceProviderRegistry.java | 25 + .../api/device/IpDeviceProviderService.java | 78 + .../iptopology/api/device/IpDeviceService.java | 111 ++ .../iptopology/api/device/IpDeviceStore.java | 164 ++ .../api/device/IpDeviceStoreDelegate.java | 24 + .../iptopology/api/device/PrefixDescription.java | 41 + .../iptopology/api/device/package-info.java | 20 + .../api/link/DefaultIpLinkDescription.java | 95 ++ .../iptopology/api/link/IpLinkDescription.java | 55 + .../iptopology/api/link/IpLinkEvent.java | 68 + .../iptopology/api/link/IpLinkListener.java | 24 + .../iptopology/api/link/IpLinkProvider.java | 25 + .../api/link/IpLinkProviderRegistry.java | 25 + .../iptopology/api/link/IpLinkProviderService.java | 57 + .../iptopology/api/link/IpLinkService.java | 108 ++ .../iptopology/api/link/IpLinkStore.java | 115 ++ .../iptopology/api/link/IpLinkStoreDelegate.java | 24 + .../iptopology/api/link/package-info.java | 20 + .../onosproject/iptopology/api/package-info.java | 20 + .../onos/apps/openstackswitching/app/features.xml | 1 - .../src/onos/apps/openstackswitching/app/pom.xml | 1 - framework/src/onos/apps/pathpainter/pom.xml | 38 + .../java/org/onosproject/pathpainter/PathLink.java | 51 + .../org/onosproject/pathpainter/PathLinkMap.java | 30 + .../org/onosproject/pathpainter/PathPainter.java | 86 + .../PathPainterTopovMessageHandler.java | 388 +++++ .../pathpainter/PathPainterTopovOverlay.java | 56 + .../org/onosproject/pathpainter/package-info.java | 20 + .../main/resources/app/view/ppTopov/ppTopov.css | 2 + .../main/resources/app/view/ppTopov/ppTopov.html | 4 + .../src/main/resources/app/view/ppTopov/ppTopov.js | 119 ++ .../resources/app/view/ppTopov/ppTopovOverlay.js | 260 +++ .../src/main/resources/ppTopov/css.html | 1 + .../pathpainter/src/main/resources/ppTopov/js.html | 2 + framework/src/onos/apps/pom.xml | 4 + .../org/onosproject/sdnip/IntentSynchronizer.java | 1 + .../java/org/onosproject/sdnip/IntentUtils.java | 89 - .../onosproject/sdnip/PeerConnectivityManager.java | 1 + .../java/org/onosproject/sdnip/IntentSyncTest.java | 1 + .../onosproject/sdnip/TestIntentServiceHelper.java | 1 + framework/src/onos/apps/segmentrouting/pom.xml | 5 + .../org/onosproject/segmentrouting/ArpHandler.java | 26 +- .../segmentrouting/DefaultRoutingHandler.java | 1 + .../onosproject/segmentrouting/IcmpHandler.java | 2 +- .../org/onosproject/segmentrouting/IpHandler.java | 2 +- .../segmentrouting/RoutingRulePopulator.java | 63 +- .../segmentrouting/SegmentRoutingManager.java | 146 +- .../onosproject/segmentrouting/TunnelHandler.java | 2 +- .../segmentrouting/config/DeviceConfiguration.java | 45 +- .../config/SegmentRoutingConfig.java | 219 ++- .../grouphandler/DefaultEdgeGroupHandler.java | 6 +- .../grouphandler/DefaultGroupHandler.java | 139 +- .../grouphandler/DefaultTransitGroupHandler.java | 6 +- .../grouphandler/PolicyGroupHandler.java | 6 +- .../grouphandler/PortNextObjectiveStoreKey.java | 77 + .../config/SegmentRoutingConfigTest.java | 157 ++ .../intentperf/IntentPerfCollector.java | 2 +- framework/src/onos/apps/vtn/pom.xml | 6 + .../sfc/forwarder/ServiceFunctionForwarder.java | 43 - .../forwarder/ServiceFunctionForwarderService.java | 51 + .../impl/ServiceFunctionForwarderImpl.java | 293 ++++ .../sfc/forwarder/impl/package-info.java | 20 + .../sfc/manager/NshSpiIdGenerators.java | 51 + .../org/onosproject/sfc/manager/SfcService.java | 37 +- .../onosproject/sfc/manager/impl/SfcManager.java | 159 +- .../sfc/manager/impl/SfcManagerTest.java | 269 +++ .../sfc/util/FlowClassifierManagerTestImpl.java | 93 ++ .../sfc/util/FlowObjectiveServiceTestImpl.java | 53 + .../sfc/util/PortChainManagerTestImpl.java | 85 + .../sfc/util/PortPairGroupManagerTestImpl.java | 89 + .../sfc/util/PortPairManagerTestImpl.java | 89 + .../sfc/util/VirtualPortManagerTestImpl.java | 98 ++ .../sfc/util/VtnRscManagerTestImpl.java | 72 + .../org/onosproject/vtn/manager/VTNService.java | 29 + .../onosproject/vtn/manager/impl/VTNManager.java | 476 +++++- .../java/org/onosproject/vtn/table/ArpService.java | 6 +- .../onosproject/vtn/table/impl/ArpServiceImpl.java | 113 ++ .../java/org/onosproject/vtn/util/VtnData.java | 82 + .../vtnrsc/classifier/ClassifierService.java | 41 + .../vtnrsc/classifier/impl/ClassifierManager.java | 78 + .../vtnrsc/classifier/impl/package-info.java | 20 + .../vtnrsc/classifier/package-info.java | 20 + .../vtnrsc/cli/subnet/SubnetCreateCommand.java | 2 +- .../vtnrsc/cli/subnet/SubnetUpdateCommand.java | 2 +- .../org/onosproject/vtnrsc/event/VtnRscEvent.java | 50 +- .../vtnrsc/event/VtnRscEventFeedback.java | 133 +- .../vtnrsc/floatingip/impl/FloatingIpManager.java | 59 +- .../vtnrsc/flowclassifier/FlowClassifierEvent.java | 63 + .../flowclassifier/FlowClassifierListener.java | 25 + .../flowclassifier/FlowClassifierService.java | 3 +- .../flowclassifier/impl/FlowClassifierManager.java | 18 +- .../vtnrsc/portchain/PortChainEvent.java | 63 + .../vtnrsc/portchain/PortChainListener.java | 25 + .../vtnrsc/portchain/PortChainService.java | 3 +- .../vtnrsc/portchain/impl/PortChainManager.java | 10 +- .../onosproject/vtnrsc/portpair/PortPairEvent.java | 63 + .../vtnrsc/portpair/PortPairListener.java | 25 + .../vtnrsc/portpair/PortPairService.java | 14 + .../vtnrsc/portpair/impl/PortPairManager.java | 22 +- .../vtnrsc/portpairgroup/PortPairGroupEvent.java | 63 + .../portpairgroup/PortPairGroupListener.java | 25 + .../vtnrsc/portpairgroup/PortPairGroupService.java | 14 + .../portpairgroup/impl/PortPairGroupManager.java | 22 +- .../onosproject/vtnrsc/service/VtnRscService.java | 18 +- .../vtnrsc/service/impl/VtnRscManager.java | 152 +- .../vtnrsc/virtualport/VirtualPortService.java | 10 + .../virtualport/impl/VirtualPortManager.java | 22 + .../resources/FlowClassifierWebResource.java | 27 +- .../vtnweb/resources/PortChainWebResource.java | 45 +- .../vtnweb/resources/PortPairGroupWebResource.java | 51 +- .../vtnweb/resources/PortPairWebResource.java | 39 +- .../vtnweb/web/VtnCodecRegistrator.java | 56 + .../resources/FlowClassifierResourceTest.java | 9 +- .../vtnweb/resources/PortChainResourceTest.java | 247 +++ .../resources/PortPairGroupResourceTest.java | 234 +++ .../vtnweb/resources/PortPairResourceTest.java | 7 +- .../onosproject/vtnweb/web/SfcCodecContext.java | 41 +- .../vtnweb/resources/post-PortChain.json | 15 + .../vtnweb/resources/post-PortPairGroup.json | 11 + framework/src/onos/bgp/api/pom.xml | 95 -- .../org/onosproject/bgp/controller/BgpCfg.java | 297 ---- .../onosproject/bgp/controller/BgpConnectPeer.java | 28 - .../onosproject/bgp/controller/BgpController.java | 117 -- .../org/onosproject/bgp/controller/BgpDpid.java | 130 -- .../java/org/onosproject/bgp/controller/BgpId.java | 121 -- .../bgp/controller/BgpLinkListener.java | 35 - .../onosproject/bgp/controller/BgpLocalRib.java | 60 - .../bgp/controller/BgpNodeListener.java | 35 - .../onosproject/bgp/controller/BgpPacketStats.java | 52 - .../org/onosproject/bgp/controller/BgpPeer.java | 113 -- .../org/onosproject/bgp/controller/BgpPeerCfg.java | 180 -- .../onosproject/bgp/controller/BgpPeerManager.java | 54 - .../onosproject/bgp/controller/BgpSessionInfo.java | 70 - .../onosproject/bgp/controller/package-info.java | 20 - framework/src/onos/bgp/bgpio/pom.xml | 76 - .../bgpio/exceptions/BgpParseException.java | 106 -- .../onosproject/bgpio/exceptions/package-info.java | 20 - .../onosproject/bgpio/protocol/BgpFactories.java | 82 - .../org/onosproject/bgpio/protocol/BgpFactory.java | 60 - .../bgpio/protocol/BgpKeepaliveMsg.java | 48 - .../org/onosproject/bgpio/protocol/BgpLSNlri.java | 54 - .../onosproject/bgpio/protocol/BgpLinkLsNlri.java | 47 - .../org/onosproject/bgpio/protocol/BgpMessage.java | 71 - .../bgpio/protocol/BgpMessageReader.java | 36 - .../bgpio/protocol/BgpMessageWriter.java | 36 - .../onosproject/bgpio/protocol/BgpNodeLSNlri.java | 30 - .../bgpio/protocol/BgpNotificationMsg.java | 77 - .../org/onosproject/bgpio/protocol/BgpOpenMsg.java | 127 -- .../bgpio/protocol/BgpPrefixLSNlri.java | 40 - .../org/onosproject/bgpio/protocol/BgpType.java | 45 - .../onosproject/bgpio/protocol/BgpUpdateMsg.java | 48 - .../org/onosproject/bgpio/protocol/BgpVersion.java | 45 - .../onosproject/bgpio/protocol/IGPRouterID.java | 23 - .../org/onosproject/bgpio/protocol/NlriType.java | 45 - .../org/onosproject/bgpio/protocol/Writeable.java | 35 - .../protocol/linkstate/BgpLinkLSIdentifier.java | 296 ---- .../protocol/linkstate/BgpLinkLsNlriVer4.java | 210 --- .../protocol/linkstate/BgpNodeLSIdentifier.java | 122 -- .../protocol/linkstate/BgpNodeLSNlriVer4.java | 212 --- .../linkstate/BgpPrefixIPv4LSNlriVer4.java | 205 --- .../protocol/linkstate/BgpPrefixLSIdentifier.java | 271 --- .../bgpio/protocol/linkstate/NodeDescriptors.java | 262 --- .../protocol/linkstate/PathAttrNlriDetails.java | 135 -- .../linkstate/PathAttrNlriDetailsLocalRib.java | 122 -- .../bgpio/protocol/linkstate/package-info.java | 20 - .../onosproject/bgpio/protocol/package-info.java | 20 - .../bgpio/protocol/ver4/BgpFactoryVer4.java | 58 - .../bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java | 157 -- .../bgpio/protocol/ver4/BgpMessageVer4.java | 111 -- .../protocol/ver4/BgpNotificationMsgVer4.java | 263 --- .../bgpio/protocol/ver4/BgpOpenMsgVer4.java | 518 ------ .../bgpio/protocol/ver4/BgpPathAttributes.java | 195 --- .../bgpio/protocol/ver4/BgpUpdateMsgVer4.java | 285 ---- .../bgpio/protocol/ver4/package-info.java | 20 - .../org/onosproject/bgpio/types/AreaIDTlv.java | 130 -- .../java/org/onosproject/bgpio/types/As4Path.java | 175 -- .../java/org/onosproject/bgpio/types/AsPath.java | 214 --- .../bgpio/types/AutonomousSystemTlv.java | 130 -- .../org/onosproject/bgpio/types/BgpErrorType.java | 74 - .../org/onosproject/bgpio/types/BgpHeader.java | 161 -- .../bgpio/types/BgpLSIdentifierTlv.java | 131 -- .../org/onosproject/bgpio/types/BgpValueType.java | 47 - .../bgpio/types/FourOctetAsNumCapabilityTlv.java | 120 -- .../bgpio/types/IPReachabilityInformationTlv.java | 165 -- .../onosproject/bgpio/types/IPv4AddressTlv.java | 133 -- .../onosproject/bgpio/types/IPv6AddressTlv.java | 133 -- .../onosproject/bgpio/types/IsIsNonPseudonode.java | 124 -- .../onosproject/bgpio/types/IsIsPseudonode.java | 146 -- .../bgpio/types/LinkLocalRemoteIdentifiersTlv.java | 142 -- .../bgpio/types/LinkStateAttributes.java | 314 ---- .../org/onosproject/bgpio/types/LocalPref.java | 121 -- .../main/java/org/onosproject/bgpio/types/Med.java | 121 -- .../org/onosproject/bgpio/types/MpReachNlri.java | 225 --- .../org/onosproject/bgpio/types/MpUnReachNlri.java | 210 --- .../types/MultiProtocolExtnCapabilityTlv.java | 166 -- .../java/org/onosproject/bgpio/types/NextHop.java | 139 -- .../onosproject/bgpio/types/OSPFNonPseudonode.java | 121 -- .../onosproject/bgpio/types/OSPFPseudonode.java | 132 -- .../onosproject/bgpio/types/OSPFRouteTypeTlv.java | 168 -- .../java/org/onosproject/bgpio/types/Origin.java | 168 -- .../bgpio/types/RouteDistinguisher.java | 79 - .../bgpio/types/attr/BgpAttrNodeFlagBitTlv.java | 199 --- .../bgpio/types/attr/BgpAttrNodeIsIsAreaId.java | 136 -- .../types/attr/BgpAttrNodeMultiTopologyId.java | 164 -- .../bgpio/types/attr/BgpAttrNodeName.java | 135 -- .../bgpio/types/attr/BgpAttrOpaqueNode.java | 138 -- .../bgpio/types/attr/BgpAttrRouterIdV4.java | 140 -- .../bgpio/types/attr/BgpAttrRouterIdV6.java | 143 -- .../bgpio/types/attr/BgpLinkAttrIgpMetric.java | 178 -- .../types/attr/BgpLinkAttrIsIsAdminstGrp.java | 136 -- .../types/attr/BgpLinkAttrMaxLinkBandwidth.java | 156 -- .../types/attr/BgpLinkAttrMplsProtocolMask.java | 158 -- .../bgpio/types/attr/BgpLinkAttrName.java | 134 -- .../bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java | 139 -- .../types/attr/BgpLinkAttrProtectionType.java | 246 --- .../bgpio/types/attr/BgpLinkAttrSrlg.java | 136 -- .../types/attr/BgpLinkAttrTeDefaultMetric.java | 138 -- .../attr/BgpLinkAttrUnRsrvdLinkBandwidth.java | 163 -- .../bgpio/types/attr/BgpPrefixAttrExtRouteTag.java | 145 -- .../bgpio/types/attr/BgpPrefixAttrIgpFlags.java | 204 --- .../bgpio/types/attr/BgpPrefixAttrMetric.java | 137 -- .../bgpio/types/attr/BgpPrefixAttrOpaqueData.java | 139 -- .../bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java | 193 --- .../bgpio/types/attr/BgpPrefixAttrRouteTag.java | 142 -- .../onosproject/bgpio/types/attr/package-info.java | 20 - .../org/onosproject/bgpio/types/package-info.java | 20 - .../java/org/onosproject/bgpio/util/Constants.java | 37 - .../bgpio/util/UnSupportedAttribute.java | 51 - .../org/onosproject/bgpio/util/Validation.java | 223 --- .../org/onosproject/bgpio/util/package-info.java | 20 - .../bgp/BgpLinkAttrMaxLinkBandwidthTest.java | 44 - .../bgp/BgpLinkAttrTeDefaultMetricTest.java | 42 - .../bgp/BgpPrefixAttrOpaqueDataTest.java | 42 - .../bgpio/protocol/BgpKeepaliveMsgTest.java | 66 - .../bgpio/protocol/BgpNotificationMsgTest.java | 224 --- .../onosproject/bgpio/protocol/BgpOpenMsgTest.java | 314 ---- .../org/onosproject/bgpio/types/AreaIdTest.java | 39 - .../org/onosproject/bgpio/types/As4PathTest.java | 55 - .../org/onosproject/bgpio/types/AsPathTest.java | 55 - .../bgpio/types/AutonomousSystemTest.java | 39 - .../bgpio/types/BgpLSIdentifierTest.java | 39 - .../bgpio/types/IPReachabilityInformationTest.java | 40 - .../onosproject/bgpio/types/IPv4AddressTest.java | 40 - .../onosproject/bgpio/types/IPv6AddressTest.java | 40 - .../bgpio/types/IsIsNonPseudonodeTest.java | 39 - .../bgpio/types/IsIsPseudonodeTest.java | 39 - .../types/LinkLocalRemoteIdentifiersTest.java | 39 - .../org/onosproject/bgpio/types/LocalPrefTest.java | 36 - .../java/org/onosproject/bgpio/types/MedTest.java | 36 - .../org/onosproject/bgpio/types/NextHopTest.java | 40 - .../org/onosproject/bgpio/types/OriginTest.java | 39 - .../bgpio/types/OspfPseudonodeTest.java | 42 - .../onosproject/bgpio/types/OspfRouteTypeTest.java | 39 - .../types/attr/BgpAttrNodeFlagBitTlvTest.java | 50 - .../bgpio/types/attr/BgpAttrRouterIdV6Test.java | 49 - .../bgpio/types/attr/BgpLinkAttrIgpMetricTest.java | 43 - .../attr/BgpLinkAttrMaxLinkBandwidthTest.java | 43 - .../attr/BgpLinkAttrMplsProtocolMaskTest.java | 42 - .../bgpio/types/attr/BgpLinkAttrNameTest.java | 38 - .../types/attr/BgpLinkAttrOpaqLnkAttribTest.java | 41 - .../types/attr/BgpLinkAttrProtectionTypeTest.java | 56 - .../types/attr/BgpLinkAttrTeDefaultMetricTest.java | 40 - .../attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java | 56 - .../types/attr/BgpPrefixAttrIgpFlagsTest.java | 53 - .../bgpio/types/attr/BgpPrefixAttrMetricTest.java | 39 - .../types/attr/BgpPrefixAttrOpaqueDataTest.java | 41 - .../types/attr/BgpPrefixAttrOspfFwdAddrTest.java | 51 - .../types/attr/BgpPrefixAttrRouteTagTest.java | 54 - framework/src/onos/bgp/ctl/pom.xml | 65 - .../onosproject/bgp/controller/impl/AdjRibIn.java | 132 -- .../bgp/controller/impl/BgpChannelHandler.java | 911 ---------- .../onosproject/bgp/controller/impl/BgpConfig.java | 344 ---- .../bgp/controller/impl/BgpConnectPeerImpl.java | 133 -- .../bgp/controller/impl/BgpControllerImpl.java | 218 --- .../bgp/controller/impl/BgpKeepAliveTimer.java | 72 - .../bgp/controller/impl/BgpMessageDecoder.java | 60 - .../bgp/controller/impl/BgpMessageEncoder.java | 60 - .../bgp/controller/impl/BgpPacketStatsImpl.java | 124 -- .../bgp/controller/impl/BgpPeerConfig.java | 121 -- .../bgp/controller/impl/BgpPeerImpl.java | 297 ---- .../bgp/controller/impl/BgpPipelineFactory.java | 74 - .../bgp/controller/impl/BgpSelectionAlgo.java | 242 --- .../bgp/controller/impl/BgpSessionInfoImpl.java | 93 -- .../bgp/controller/impl/Controller.java | 254 --- .../bgp/controller/impl/VpnAdjRibIn.java | 209 --- .../bgp/controller/impl/package-info.java | 20 - .../org/onosproject/bgp/BgpControllerImplTest.java | 300 ---- .../onosproject/bgp/BgpPeerChannelHandlerTest.java | 107 -- .../onosproject/bgp/BgpPeerFrameDecoderTest.java | 168 -- .../controller/impl/BgpSelectionAlgoTest.java | 595 ------- framework/src/onos/bgp/pom.xml | 60 - .../org/onosproject/cli/net/GroupsListCommand.java | 2 +- .../onosproject/cli/net/InterfaceAddCommand.java | 12 +- .../cli/net/InterfaceRemoveCommand.java | 17 +- .../onosproject/cli/net/InterfacesListCommand.java | 38 +- .../resources/OSGI-INF/blueprint/shell-config.xml | 11 +- .../java/org/onosproject/net/AnnotationKeys.java | 18 +- .../net/DefaultOchSignalComparator.java | 37 + .../java/org/onosproject/net/NshContextHeader.java | 83 + .../java/org/onosproject/net/NshServiceIndex.java | 83 + .../java/org/onosproject/net/NshServicePathId.java | 83 + .../src/main/java/org/onosproject/net/OchPort.java | 4 +- .../main/java/org/onosproject/net/OchSignal.java | 8 +- .../main/java/org/onosproject/net/OduCltPort.java | 2 +- .../src/main/java/org/onosproject/net/OmsPort.java | 2 +- .../net/behaviour/ExtensionSelectorResolver.java | 40 + .../net/behaviour/ExtensionTreatmentResolver.java | 4 +- .../org/onosproject/net/behaviour/LambdaQuery.java | 40 + .../net/config/basics/BasicHostConfig.java | 72 +- .../net/config/basics/BasicLinkConfig.java | 33 +- .../onosproject/net/flow/AbstractExtension.java | 74 + .../net/flow/DefaultTrafficSelector.java | 27 +- .../net/flow/DefaultTrafficTreatment.java | 15 + .../java/org/onosproject/net/flow/Extension.java | 71 + .../org/onosproject/net/flow/TrafficSelector.java | 15 +- .../org/onosproject/net/flow/TrafficTreatment.java | 24 + .../onosproject/net/flow/criteria/Criteria.java | 28 + .../onosproject/net/flow/criteria/Criterion.java | 3 + .../net/flow/criteria/ExtensionCriterion.java | 92 + .../net/flow/criteria/ExtensionSelector.java | 32 + .../net/flow/criteria/ExtensionSelectorType.java | 98 ++ .../net/flow/criteria/OduSignalIdCriterion.java | 2 +- .../net/flow/criteria/OduSignalTypeCriterion.java | 2 +- .../net/flow/criteria/PbbIsidCriterion.java | 75 + .../instructions/AbstractExtensionTreatment.java | 71 - .../net/flow/instructions/ExtensionTreatment.java | 53 +- .../flow/instructions/ExtensionTreatmentType.java | 17 +- .../net/flow/instructions/Instructions.java | 36 + .../instructions/L3ModificationInstruction.java | 162 +- .../flowobjective/DefaultFilteringObjective.java | 2 +- .../net/flowobjective/DefaultNextObjective.java | 2 +- .../net/flowobjective/FilteringObjective.java | 2 +- .../net/flowobjective/NextObjective.java | 2 +- .../org/onosproject/net/intent/IntentUtils.java | 84 + .../net/mcast/MulticastRouteService.java | 4 +- .../onosproject/net/newresource/ResourcePath.java | 74 +- .../net/topology/GeoDistanceLinkWeight.java | 72 + .../net/topology/HopCountLinkWeight.java | 36 + .../onosproject/net/topology/MetricLinkWeight.java | 36 + .../onosproject/net/topology/PathAdminService.java | 44 + .../org/onosproject/net/topology/PathService.java | 36 +- .../java/org/onosproject/ui/topo/TopoJson.java | 4 + .../net/flow/criteria/CriteriaTest.java | 79 + .../net/newresource/ResourceAllocationTest.java | 12 +- .../net/newresource/ResourcePathTest.java | 34 +- .../persistence/PersistenceServiceAdapter.java | 36 + .../store/persistence/TestPersistenceService.java | 57 + .../codec/impl/EncodeCriterionCodecHelper.java | 1 + .../org/onosproject/common/DefaultTopology.java | 84 +- .../net/edgeservice/impl/EdgeManager.java | 55 +- .../onosproject/net/flow/impl/FlowRuleManager.java | 2 +- .../flowobjective/impl/FlowObjectiveManager.java | 9 +- .../net/intent/impl/ObjectiveTracker.java | 7 +- .../impl/compiler/MplsPathIntentCompiler.java | 31 +- .../OpticalConnectivityIntentCompiler.java | 12 +- .../net/link/impl/BasicLinkOperator.java | 4 + .../newresource/impl/ResourceDeviceListener.java | 103 +- .../net/newresource/impl/ResourceLinkListener.java | 153 -- .../net/newresource/impl/ResourceRegistrar.java | 11 +- .../net/edgeservice/impl/EdgeManagerTest.java | 155 +- .../net/intent/impl/ObjectiveTrackerTest.java | 5 +- .../consistent/impl/DefaultAsyncConsistentMap.java | 49 +- .../store/consistent/impl/MappingSet.java | 131 ++ .../store/group/impl/DistributedGroupStore.java | 2 +- .../store/host/impl/DistributedHostStore.java | 265 +++ .../onosproject/store/host/impl/ECHostStore.java | 272 --- .../proxyarp/impl/DistributedProxyArpStore.java | 7 +- .../topology/impl/DistributedTopologyStore.java | 91 +- .../impl/DefaultAsyncConsistentMapTest.java | 369 ++++ .../ecmap/EventuallyConsistentMapImplTest.java | 8 +- .../store/host/impl/DistributedHostStoreTest.java | 83 + .../store/host/impl/ECHostStoreTest.java | 95 -- .../persistence/impl/PersistenceManager.java | 1 - .../store/serializers/KryoSerializerTest.java | 4 +- framework/src/onos/docs/external-excludes | 2 + framework/src/onos/docs/external.xml | 3 +- framework/src/onos/docs/internal-excludes | 2 + framework/src/onos/docs/internal.xml | 3 +- .../extensions/DefaultMoveExtensionTreatment.java | 146 ++ .../driver/extensions/MoveExtensionTreatment.java | 59 + .../NiciraExtensionSelectorInterpreter.java | 102 ++ .../NiciraExtensionTreatmentInterpreter.java | 88 +- .../extensions/NiciraMatchNshContextHeader.java | 95 ++ .../driver/extensions/NiciraMatchNshSi.java | 91 + .../driver/extensions/NiciraMatchNshSpi.java | 91 + .../extensions/NiciraMoveTreatmentFactory.java | 100 ++ .../driver/extensions/NiciraResubmit.java | 5 +- .../driver/extensions/NiciraResubmitTable.java | 114 ++ .../extensions/NiciraSetNshContextHeader.java | 108 ++ .../driver/extensions/NiciraSetNshSi.java | 101 ++ .../driver/extensions/NiciraSetNshSpi.java | 17 +- .../driver/extensions/NiciraSetTunnelDst.java | 6 +- .../handshaker/CalientFiberSwitchHandshaker.java | 42 +- .../handshaker/OfOpticalSwitchImplLinc13.java | 43 +- .../driver/pipeline/CpqdOFDPA2Pipeline.java | 116 +- .../driver/pipeline/OFDPA2Pipeline.java | 769 ++++----- .../driver/pipeline/OpenstackPipeline.java | 286 ++++ .../onosproject/driver/pipeline/SpringOpenTTP.java | 53 +- .../drivers/src/main/resources/onos-drivers.xml | 8 + .../extensions/NiciraSetNshContextHeaderTest.java | 68 + .../driver/extensions/NiciraSetNshSiTest.java | 52 + .../driver/extensions/NiciraSetNshSpiTest.java | 52 + .../net/config/basics/InterfaceConfig.java | 20 +- .../incubator/net/faultmanagement/alarm/Alarm.java | 211 +++ .../net/faultmanagement/alarm/AlarmEntityId.java | 75 + .../net/faultmanagement/alarm/AlarmEvent.java | 65 + .../net/faultmanagement/alarm/AlarmId.java | 84 + .../net/faultmanagement/alarm/AlarmListener.java | 25 + .../net/faultmanagement/alarm/AlarmProvider.java | 37 + .../alarm/AlarmProviderRegistry.java | 25 + .../alarm/AlarmProviderService.java | 37 + .../net/faultmanagement/alarm/AlarmService.java | 121 ++ .../net/faultmanagement/alarm/DefaultAlarm.java | 309 ++++ .../net/faultmanagement/alarm/package-info.java | 20 + .../onosproject/incubator/net/intf/Interface.java | 39 +- .../incubator/net/intf/InterfaceAdminService.java | 6 +- .../faultmanagement/alarm/AlarmEntityIdTest.java | 74 + .../net/faultmanagement/alarm/AlarmIdTest.java | 98 ++ .../faultmanagement/alarm/DefaultAlarmTest.java | 47 + .../incubator/net/intf/impl/InterfaceManager.java | 85 +- framework/src/onos/incubator/rpc-grpc/pom.xml | 15 +- framework/src/onos/pom.xml | 28 +- framework/src/onos/protocols/bgp/api/pom.xml | 90 + .../org/onosproject/bgp/controller/BgpCfg.java | 297 ++++ .../onosproject/bgp/controller/BgpConnectPeer.java | 28 + .../onosproject/bgp/controller/BgpController.java | 131 ++ .../org/onosproject/bgp/controller/BgpDpid.java | 130 ++ .../java/org/onosproject/bgp/controller/BgpId.java | 121 ++ .../bgp/controller/BgpLinkListener.java | 35 + .../onosproject/bgp/controller/BgpLocalRib.java | 60 + .../bgp/controller/BgpNodeListener.java | 35 + .../onosproject/bgp/controller/BgpPacketStats.java | 52 + .../org/onosproject/bgp/controller/BgpPeer.java | 113 ++ .../org/onosproject/bgp/controller/BgpPeerCfg.java | 180 ++ .../onosproject/bgp/controller/BgpPeerManager.java | 54 + .../onosproject/bgp/controller/BgpSessionInfo.java | 70 + .../onosproject/bgp/controller/package-info.java | 20 + framework/src/onos/protocols/bgp/bgpio/pom.xml | 76 + .../bgpio/exceptions/BgpParseException.java | 106 ++ .../onosproject/bgpio/exceptions/package-info.java | 20 + .../onosproject/bgpio/protocol/BgpFactories.java | 82 + .../org/onosproject/bgpio/protocol/BgpFactory.java | 60 + .../bgpio/protocol/BgpKeepaliveMsg.java | 48 + .../org/onosproject/bgpio/protocol/BgpLSNlri.java | 54 + .../onosproject/bgpio/protocol/BgpLinkLsNlri.java | 47 + .../org/onosproject/bgpio/protocol/BgpMessage.java | 71 + .../bgpio/protocol/BgpMessageReader.java | 36 + .../bgpio/protocol/BgpMessageWriter.java | 36 + .../onosproject/bgpio/protocol/BgpNodeLSNlri.java | 30 + .../bgpio/protocol/BgpNotificationMsg.java | 77 + .../org/onosproject/bgpio/protocol/BgpOpenMsg.java | 127 ++ .../bgpio/protocol/BgpPrefixLSNlri.java | 40 + .../org/onosproject/bgpio/protocol/BgpType.java | 45 + .../onosproject/bgpio/protocol/BgpUpdateMsg.java | 48 + .../org/onosproject/bgpio/protocol/BgpVersion.java | 45 + .../onosproject/bgpio/protocol/IGPRouterID.java | 23 + .../org/onosproject/bgpio/protocol/NlriType.java | 45 + .../org/onosproject/bgpio/protocol/Writeable.java | 35 + .../protocol/linkstate/BgpLinkLSIdentifier.java | 297 ++++ .../protocol/linkstate/BgpLinkLsNlriVer4.java | 210 +++ .../protocol/linkstate/BgpNodeLSIdentifier.java | 122 ++ .../protocol/linkstate/BgpNodeLSNlriVer4.java | 212 +++ .../linkstate/BgpPrefixIPv4LSNlriVer4.java | 205 +++ .../protocol/linkstate/BgpPrefixLSIdentifier.java | 272 +++ .../bgpio/protocol/linkstate/NodeDescriptors.java | 264 +++ .../protocol/linkstate/PathAttrNlriDetails.java | 135 ++ .../linkstate/PathAttrNlriDetailsLocalRib.java | 122 ++ .../bgpio/protocol/linkstate/package-info.java | 20 + .../onosproject/bgpio/protocol/package-info.java | 20 + .../bgpio/protocol/ver4/BgpFactoryVer4.java | 58 + .../bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java | 157 ++ .../bgpio/protocol/ver4/BgpMessageVer4.java | 111 ++ .../protocol/ver4/BgpNotificationMsgVer4.java | 265 +++ .../bgpio/protocol/ver4/BgpOpenMsgVer4.java | 518 ++++++ .../bgpio/protocol/ver4/BgpPathAttributes.java | 200 +++ .../bgpio/protocol/ver4/BgpUpdateMsgVer4.java | 285 ++++ .../bgpio/protocol/ver4/package-info.java | 20 + .../org/onosproject/bgpio/types/AreaIDTlv.java | 130 ++ .../java/org/onosproject/bgpio/types/As4Path.java | 175 ++ .../java/org/onosproject/bgpio/types/AsPath.java | 214 +++ .../bgpio/types/AutonomousSystemTlv.java | 130 ++ .../org/onosproject/bgpio/types/BgpErrorType.java | 74 + .../org/onosproject/bgpio/types/BgpHeader.java | 161 ++ .../bgpio/types/BgpLSIdentifierTlv.java | 131 ++ .../org/onosproject/bgpio/types/BgpValueType.java | 47 + .../bgpio/types/FourOctetAsNumCapabilityTlv.java | 120 ++ .../bgpio/types/IPReachabilityInformationTlv.java | 165 ++ .../onosproject/bgpio/types/IPv4AddressTlv.java | 133 ++ .../onosproject/bgpio/types/IPv6AddressTlv.java | 133 ++ .../onosproject/bgpio/types/IsIsNonPseudonode.java | 124 ++ .../onosproject/bgpio/types/IsIsPseudonode.java | 146 ++ .../bgpio/types/LinkLocalRemoteIdentifiersTlv.java | 142 ++ .../bgpio/types/LinkStateAttributes.java | 314 ++++ .../org/onosproject/bgpio/types/LocalPref.java | 121 ++ .../main/java/org/onosproject/bgpio/types/Med.java | 121 ++ .../org/onosproject/bgpio/types/MpReachNlri.java | 225 +++ .../org/onosproject/bgpio/types/MpUnReachNlri.java | 210 +++ .../types/MultiProtocolExtnCapabilityTlv.java | 166 ++ .../java/org/onosproject/bgpio/types/NextHop.java | 139 ++ .../onosproject/bgpio/types/OSPFNonPseudonode.java | 121 ++ .../onosproject/bgpio/types/OSPFPseudonode.java | 132 ++ .../onosproject/bgpio/types/OSPFRouteTypeTlv.java | 168 ++ .../java/org/onosproject/bgpio/types/Origin.java | 168 ++ .../bgpio/types/RouteDistinguisher.java | 79 + .../bgpio/types/attr/BgpAttrNodeFlagBitTlv.java | 199 +++ .../bgpio/types/attr/BgpAttrNodeIsIsAreaId.java | 136 ++ .../types/attr/BgpAttrNodeMultiTopologyId.java | 164 ++ .../bgpio/types/attr/BgpAttrNodeName.java | 135 ++ .../bgpio/types/attr/BgpAttrOpaqueNode.java | 138 ++ .../bgpio/types/attr/BgpAttrRouterIdV4.java | 140 ++ .../bgpio/types/attr/BgpAttrRouterIdV6.java | 143 ++ .../bgpio/types/attr/BgpLinkAttrIgpMetric.java | 178 ++ .../types/attr/BgpLinkAttrIsIsAdminstGrp.java | 136 ++ .../types/attr/BgpLinkAttrMaxLinkBandwidth.java | 156 ++ .../types/attr/BgpLinkAttrMplsProtocolMask.java | 158 ++ .../bgpio/types/attr/BgpLinkAttrName.java | 134 ++ .../bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java | 139 ++ .../types/attr/BgpLinkAttrProtectionType.java | 246 +++ .../bgpio/types/attr/BgpLinkAttrSrlg.java | 136 ++ .../types/attr/BgpLinkAttrTeDefaultMetric.java | 138 ++ .../attr/BgpLinkAttrUnRsrvdLinkBandwidth.java | 163 ++ .../bgpio/types/attr/BgpPrefixAttrExtRouteTag.java | 145 ++ .../bgpio/types/attr/BgpPrefixAttrIgpFlags.java | 204 +++ .../bgpio/types/attr/BgpPrefixAttrMetric.java | 137 ++ .../bgpio/types/attr/BgpPrefixAttrOpaqueData.java | 139 ++ .../bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java | 193 +++ .../bgpio/types/attr/BgpPrefixAttrRouteTag.java | 142 ++ .../onosproject/bgpio/types/attr/package-info.java | 20 + .../org/onosproject/bgpio/types/package-info.java | 20 + .../java/org/onosproject/bgpio/util/Constants.java | 37 + .../bgpio/util/UnSupportedAttribute.java | 51 + .../org/onosproject/bgpio/util/Validation.java | 223 +++ .../org/onosproject/bgpio/util/package-info.java | 20 + .../bgp/BgpLinkAttrMaxLinkBandwidthTest.java | 44 + .../bgp/BgpLinkAttrTeDefaultMetricTest.java | 42 + .../bgp/BgpPrefixAttrOpaqueDataTest.java | 42 + .../bgpio/protocol/BgpKeepaliveMsgTest.java | 66 + .../bgpio/protocol/BgpNotificationMsgTest.java | 224 +++ .../onosproject/bgpio/protocol/BgpOpenMsgTest.java | 314 ++++ .../bgpio/protocol/BgpUpdateMsgTest.java | 1496 +++++++++++++++++ .../org/onosproject/bgpio/types/AreaIdTest.java | 39 + .../org/onosproject/bgpio/types/As4PathTest.java | 55 + .../org/onosproject/bgpio/types/AsPathTest.java | 55 + .../bgpio/types/AutonomousSystemTest.java | 39 + .../bgpio/types/BgpLSIdentifierTest.java | 39 + .../bgpio/types/IPReachabilityInformationTest.java | 40 + .../onosproject/bgpio/types/IPv4AddressTest.java | 40 + .../onosproject/bgpio/types/IPv6AddressTest.java | 40 + .../bgpio/types/IsIsNonPseudonodeTest.java | 39 + .../bgpio/types/IsIsPseudonodeTest.java | 39 + .../types/LinkLocalRemoteIdentifiersTest.java | 39 + .../org/onosproject/bgpio/types/LocalPrefTest.java | 36 + .../java/org/onosproject/bgpio/types/MedTest.java | 36 + .../org/onosproject/bgpio/types/NextHopTest.java | 40 + .../org/onosproject/bgpio/types/OriginTest.java | 39 + .../bgpio/types/OspfPseudonodeTest.java | 42 + .../onosproject/bgpio/types/OspfRouteTypeTest.java | 39 + .../types/attr/BgpAttrNodeFlagBitTlvTest.java | 50 + .../bgpio/types/attr/BgpAttrRouterIdV6Test.java | 49 + .../bgpio/types/attr/BgpLinkAttrIgpMetricTest.java | 43 + .../attr/BgpLinkAttrMaxLinkBandwidthTest.java | 43 + .../attr/BgpLinkAttrMplsProtocolMaskTest.java | 42 + .../bgpio/types/attr/BgpLinkAttrNameTest.java | 38 + .../types/attr/BgpLinkAttrOpaqLnkAttribTest.java | 41 + .../types/attr/BgpLinkAttrProtectionTypeTest.java | 56 + .../types/attr/BgpLinkAttrTeDefaultMetricTest.java | 40 + .../attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java | 56 + .../types/attr/BgpPrefixAttrIgpFlagsTest.java | 53 + .../bgpio/types/attr/BgpPrefixAttrMetricTest.java | 39 + .../types/attr/BgpPrefixAttrOpaqueDataTest.java | 41 + .../types/attr/BgpPrefixAttrOspfFwdAddrTest.java | 51 + .../types/attr/BgpPrefixAttrRouteTagTest.java | 54 + framework/src/onos/protocols/bgp/ctl/pom.xml | 61 + .../onosproject/bgp/controller/impl/AdjRibIn.java | 132 ++ .../bgp/controller/impl/BgpChannelHandler.java | 896 ++++++++++ .../onosproject/bgp/controller/impl/BgpConfig.java | 364 ++++ .../bgp/controller/impl/BgpConnectPeerImpl.java | 133 ++ .../bgp/controller/impl/BgpControllerImpl.java | 266 +++ .../bgp/controller/impl/BgpKeepAliveTimer.java | 72 + .../bgp/controller/impl/BgpLocalRibImpl.java | 603 +++++++ .../bgp/controller/impl/BgpMessageDecoder.java | 60 + .../bgp/controller/impl/BgpMessageEncoder.java | 60 + .../bgp/controller/impl/BgpPacketStatsImpl.java | 124 ++ .../bgp/controller/impl/BgpPeerConfig.java | 121 ++ .../bgp/controller/impl/BgpPeerImpl.java | 346 ++++ .../bgp/controller/impl/BgpPipelineFactory.java | 74 + .../bgp/controller/impl/BgpSelectionAlgo.java | 242 +++ .../bgp/controller/impl/BgpSessionInfoImpl.java | 93 ++ .../bgp/controller/impl/Controller.java | 254 +++ .../bgp/controller/impl/VpnAdjRibIn.java | 209 +++ .../bgp/controller/impl/package-info.java | 20 + .../org/onosproject/bgp/BgpControllerImplTest.java | 322 ++++ .../onosproject/bgp/BgpPeerChannelHandlerTest.java | 107 ++ .../onosproject/bgp/BgpPeerFrameDecoderTest.java | 168 ++ .../controller/impl/BgpSelectionAlgoTest.java | 595 +++++++ framework/src/onos/protocols/bgp/pom.xml | 40 + framework/src/onos/protocols/netconf/api/pom.xml | 9 +- framework/src/onos/protocols/netconf/ctl/pom.xml | 6 + framework/src/onos/protocols/netconf/pom.xml | 30 +- framework/src/onos/protocols/netconf/rfc/pom.xml | 1 + .../controller/ExtensionSelectorInterpreter.java | 57 + .../controller/ExtensionTreatmentInterpreter.java | 16 +- .../controller/driver/AbstractOpenFlowSwitch.java | 1 + .../controller/impl/OpenFlowControllerImpl.java | 16 +- .../impl/OpenFlowControllerImplTest.java | 5 + framework/src/onos/protocols/openflow/pom.xml | 23 - .../controller/driver/DefaultOvsdbClient.java | 21 +- framework/src/onos/protocols/ovsdb/pom.xml | 39 +- .../pcepio/types/ISISAreaIdentifierTlv.java | 5 +- .../org/onosproject/pcepio/types/LinkNameTlv.java | 7 +- framework/src/onos/protocols/pcep/pom.xml | 20 - framework/src/onos/protocols/pom.xml | 17 +- .../bgp/topology/impl/BgpTopologyProviderTest.java | 12 + .../provider/lldp/impl/LldpLinkProvider.java | 2 +- framework/src/onos/providers/netcfghost/pom.xml | 65 + .../netcfghost/NetworkConfigHostProvider.java | 196 +++ .../provider/netcfghost/package-info.java | 20 + .../netcfghost/NetworkConfigHostProviderTest.java | 132 ++ framework/src/onos/providers/netconf/app/pom.xml | 7 +- framework/src/onos/providers/netconf/flow/pom.xml | 259 --- .../netconf/flow/impl/NetconfFlowRuleProvider.java | 403 ----- .../netconf/flow/impl/NetconfOperation.java | 141 -- .../provider/netconf/flow/impl/XmlBuilder.java | 223 --- .../provider/netconf/flow/impl/package-info.java | 21 - framework/src/onos/providers/netconf/pom.xml | 1 - .../onosproject/provider/nil/NullProviders.java | 4 +- .../of/device/impl/OpenFlowDeviceProvider.java | 21 +- .../provider/of/flow/impl/FlowEntryBuilder.java | 67 + .../provider/of/flow/impl/FlowModBuilder.java | 76 +- .../provider/of/flow/impl/FlowModBuilderVer10.java | 1 + .../provider/of/flow/impl/FlowModBuilderVer13.java | 65 +- .../flow/impl/NewAdaptiveFlowStatsCollector.java | 1764 ++++++++++---------- .../provider/of/flow/impl/OpenFlowValueMapper.java | 38 + .../of/group/impl/OpenFlowGroupProvider.java | 3 +- .../of/meter/impl/OpenFlowMeterProvider.java | 2 + framework/src/onos/providers/pom.xml | 2 + framework/src/onos/providers/snmp/alarm/pom.xml | 34 + .../snmp/alarm/impl/SNMPAlarmProvider.java | 57 + .../provider/snmp/alarm/impl/package-info.java | 20 + framework/src/onos/providers/snmp/pom.xml | 38 + framework/src/onos/tools/build/conf/pom.xml | 2 +- .../conf/src/main/resources/onos/checkstyle.xml | 4 - framework/src/onos/tools/build/onos-change-version | 5 +- framework/src/onos/tools/build/onos-package | 34 +- framework/src/onos/tools/build/pom.xml | 1 - framework/src/onos/tools/dev/bash_profile | 9 +- .../tools/dev/bin/onos-build-selective.exclude | 3 +- .../tools/package/config/samples/network-cfg.json | 109 +- ...sproject.faultmanagement.impl.AlarmsManager.cfg | 6 + .../tools/package/karaf-assembly/onos-assembly.py | 80 + .../src/onos/tools/package/karaf-assembly/pom.xml | 84 + .../src/onos/tools/package/maven-plugin/pom.xml | 3 +- .../org/onosproject/maven/OnosSwaggerMojo.java | 3 +- framework/src/onos/tools/package/yangtools/pom.xml | 76 + .../java/org/onoproject/yangtool/YangLoader.java | 167 ++ .../org/onoproject/yangtool/YangLoaderMain.java | 16 + .../yangtools/src/main/resources/pom-template.xml | 95 ++ framework/src/onos/tools/test/bin/ogroup-opts | 2 +- framework/src/onos/tools/test/cells/andrea | 2 +- framework/src/onos/tools/test/cells/tomx | 2 +- .../test/configs/network-cfg-2x2-leaf-spine.json | 108 ++ .../test/configs/network-cfg-4x4-leaf-spine.json | 208 +++ framework/src/onos/tools/test/topos/attmplsfast.py | 15 +- framework/src/onos/tools/test/topos/metro.py | 2 +- .../src/main/java/org/onlab/util/GeoLocation.java | 85 + .../src/main/java/org/onlab/util/Spectrum.java | 8 +- .../test/java/org/onlab/util/GeoLocationTest.java | 38 + .../rest/resources/ApplicationsWebResource.java | 4 +- .../rest/resources/ClusterWebResource.java | 6 +- .../rest/resources/DevicesWebResource.java | 6 +- .../rest/resources/FlowsWebResource.java | 8 +- .../rest/resources/HostsWebResource.java | 8 +- .../rest/resources/IntentsWebResource.java | 6 +- .../rest/resources/LinksWebResource.java | 2 +- .../rest/resources/NetworkConfigWebResource.java | 2 - .../rest/resources/PathsWebResource.java | 4 +- .../rest/resources/StatisticsWebResource.java | 10 +- .../rest/resources/TopologyWebResource.java | 14 +- .../main/resources/definitions/Application.json | 4 +- .../resources/definitions/ApplicationPost.json | 4 +- .../main/resources/definitions/Applications.json | 4 +- .../resources/NetworkConfigWebResourceTest.java | 352 ++++ .../ui/impl/TopologyViewMessageHandlerBase.java | 7 +- .../main/webapp/_sdh/topojson/countrycodes.html | 376 +++++ .../web/gui/src/main/webapp/app/fw/svg/icon.js | 4 + .../web/gui/src/main/webapp/app/view/topo/topo.css | 10 +- .../web/gui/src/main/webapp/app/view/topo/topo.js | 6 + .../gui/src/main/webapp/app/view/topo/topoD3.js | 70 +- .../src/main/webapp/app/view/topo/topoOverlay.js | 5 +- .../gui/src/main/webapp/app/view/topo/topoPanel.js | 2 +- .../src/main/webapp/app/view/topo/topoToolbar.js | 2 +- .../src/main/webapp/data/map/countries.topojson | 10 +- .../test/_karma/ev/badges/ev_10_addHost_02.json | 21 + .../ev/badges/ev_10_showHighlights_stuff.json | 63 - .../test/_karma/ev/badges/ev_11_addHost_03.json | 21 + .../ev/badges/ev_11_showHighlights_clear.json | 8 - .../ev/badges/ev_12_showHighlights_clear.json | 8 + .../ev/badges/ev_13_showHighlights_devices.json | 63 + .../ev/badges/ev_14_showHighlights_hosts.json | 32 + .../ev/badges/ev_15_showHighlights_clear.json | 8 + .../src/test/_karma/ev/badges/ev_9_addHost_01.json | 21 + .../ev/badges/ev_9_showHighlights_clear.json | 8 - .../gui/src/test/_karma/ev/badges/scenario.json | 6 +- 779 files changed, 46246 insertions(+), 25276 deletions(-) create mode 100644 framework/src/onos/apps/cpman/pom.xml create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMessageType.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMetricType.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneLoad.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneManager.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneMetric.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneStatsService.java create mode 100644 framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/package-info.java create mode 100644 framework/src/onos/apps/faultmanagement/app/app.xml create mode 100644 framework/src/onos/apps/faultmanagement/app/features.xml create mode 100644 framework/src/onos/apps/faultmanagement/app/pom.xml create mode 100644 framework/src/onos/apps/faultmanagement/fmmgr/pom.xml create mode 100644 framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/AlarmsManager.java create mode 100644 framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/package-info.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/pom.xml create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/main/webapp/WEB-INF/web.xml create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecContext.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecTest.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmJsonMatcher.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-full.json create mode 100644 framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-minimal.json create mode 100644 framework/src/onos/apps/faultmanagement/pom.xml create mode 100644 framework/src/onos/apps/iptopology-api/pom.xml create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AreaId.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AsNumber.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Color.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDeviceIntf.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDevicePrefix.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpDevice.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpLink.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceInterface.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceIntf.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DevicePrefix.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceTed.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DomainId.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ExtendedRouteTag.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IgpFlags.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/InterfaceIdentifier.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDevice.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDeviceIdentifier.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLink.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLinkIdentifier.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpReachability.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsIsPseudonode.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsoNodeId.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/LinkTed.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Metric.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/OspfPseudonode.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Position.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixIdentifier.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixTed.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ProtectionType.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteDistinguisher.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteIdentifier.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteInstance.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteTag.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteType.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouterId.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Signalling.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Srlg.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TerminationPoint.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TopologyId.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultInterfaceDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultIpDeviceDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultPrefixDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/InterfaceDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceEvent.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceListener.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProvider.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderRegistry.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderService.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceService.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStore.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStoreDelegate.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/PrefixDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/package-info.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/DefaultIpLinkDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkDescription.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkEvent.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkListener.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProvider.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderRegistry.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderService.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkService.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStore.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStoreDelegate.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/package-info.java create mode 100644 framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/package-info.java create mode 100644 framework/src/onos/apps/pathpainter/pom.xml create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html create mode 100644 framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html delete mode 100644 framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java create mode 100644 framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PortNextObjectiveStoreKey.java create mode 100644 framework/src/onos/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingConfigTest.java delete mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/NshSpiIdGenerators.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/manager/impl/SfcManagerTest.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowClassifierManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowObjectiveServiceTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortChainManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairGroupManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VirtualPortManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VtnRscManagerTestImpl.java create mode 100644 framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ArpServiceImpl.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/ClassifierService.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/ClassifierManager.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/package-info.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/package-info.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierEvent.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierListener.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainEvent.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainListener.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairEvent.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairListener.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupEvent.java create mode 100644 framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupListener.java create mode 100644 framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java create mode 100644 framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java create mode 100644 framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java create mode 100644 framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortChain.json create mode 100644 framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPairGroup.json delete mode 100755 framework/src/onos/bgp/api/pom.xml delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java delete mode 100644 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java delete mode 100755 framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java delete mode 100755 framework/src/onos/bgp/bgpio/pom.xml delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java delete mode 100644 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java delete mode 100755 framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java delete mode 100755 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java delete mode 100755 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java delete mode 100755 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java delete mode 100755 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java delete mode 100755 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java delete mode 100644 framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java delete mode 100755 framework/src/onos/bgp/ctl/pom.xml delete mode 100644 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java delete mode 100644 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java delete mode 100644 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java delete mode 100644 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java delete mode 100755 framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java delete mode 100755 framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java delete mode 100755 framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java delete mode 100755 framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java delete mode 100644 framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java delete mode 100755 framework/src/onos/bgp/pom.xml create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/NshContextHeader.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServiceIndex.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServicePathId.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/LambdaQuery.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Extension.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PbbIsidCriterion.java delete mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentUtils.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java create mode 100644 framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java create mode 100644 framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/PersistenceServiceAdapter.java create mode 100644 framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/TestPersistenceService.java delete mode 100644 framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java create mode 100644 framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java create mode 100644 framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java delete mode 100644 framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java create mode 100644 framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java create mode 100644 framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java delete mode 100644 framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/ECHostStoreTest.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java create mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java create mode 100644 framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java create mode 100644 framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java create mode 100644 framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/Alarm.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityId.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEvent.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmId.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmListener.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProvider.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderRegistry.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderService.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmService.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java create mode 100644 framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/package-info.java create mode 100644 framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityIdTest.java create mode 100644 framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmIdTest.java create mode 100644 framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarmTest.java create mode 100755 framework/src/onos/protocols/bgp/api/pom.xml create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java create mode 100644 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java create mode 100755 framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/pom.xml create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpUpdateMsgTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java create mode 100755 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java create mode 100644 framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java create mode 100755 framework/src/onos/protocols/bgp/ctl/pom.xml create mode 100644 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java create mode 100644 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java create mode 100644 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java create mode 100644 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java create mode 100755 framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java create mode 100644 framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java create mode 100755 framework/src/onos/protocols/bgp/pom.xml create mode 100644 framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java create mode 100644 framework/src/onos/providers/netcfghost/pom.xml create mode 100644 framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java create mode 100644 framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/package-info.java create mode 100644 framework/src/onos/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java delete mode 100644 framework/src/onos/providers/netconf/flow/pom.xml delete mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java delete mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java delete mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java delete mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java create mode 100644 framework/src/onos/providers/snmp/alarm/pom.xml create mode 100644 framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/SNMPAlarmProvider.java create mode 100644 framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/package-info.java create mode 100644 framework/src/onos/providers/snmp/pom.xml create mode 100644 framework/src/onos/tools/package/etc/samples/org.onosproject.faultmanagement.impl.AlarmsManager.cfg create mode 100755 framework/src/onos/tools/package/karaf-assembly/onos-assembly.py create mode 100644 framework/src/onos/tools/package/karaf-assembly/pom.xml create mode 100644 framework/src/onos/tools/package/yangtools/pom.xml create mode 100644 framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoader.java create mode 100644 framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoaderMain.java create mode 100644 framework/src/onos/tools/package/yangtools/src/main/resources/pom-template.xml create mode 100644 framework/src/onos/tools/test/configs/network-cfg-2x2-leaf-spine.json create mode 100644 framework/src/onos/tools/test/configs/network-cfg-4x4-leaf-spine.json create mode 100644 framework/src/onos/utils/misc/src/main/java/org/onlab/util/GeoLocation.java create mode 100644 framework/src/onos/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java create mode 100644 framework/src/onos/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java create mode 100644 framework/src/onos/web/gui/src/main/webapp/_sdh/topojson/countrycodes.html create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json delete mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json delete mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json create mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json delete mode 100644 framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json diff --git a/build.sh b/build.sh index 5b398433..f6dd0b16 100755 --- a/build.sh +++ b/build.sh @@ -18,9 +18,9 @@ # limitations under the License. ##### Settings ##### -VERSION=1.0.7 +VERSION=1.0.8 AUTHOR="Ashlee Young" -MODIFIED="December 5, 2015" +MODIFIED="December 6, 2015" GERRITURL="git clone ssh://im2bz2pee@gerrit.opnfv.org:29418/onosfw" ONOSURL="https://github.com/opennetworkinglab/onos" SURICATAURL="https://github.com/inliniac/suricata" @@ -155,32 +155,48 @@ updateONOS() ##### Check Java ##### checkJRE() { - INSTALLED_JAVA=`java -version 2>&1 | head -n 1 | cut -d\" -f 2` # | awk -F "." '{print $1"."$2}'` - JAVA_NUM=`echo $INSTALLED_JAVA | awk -F "." '{print $1"."$2}'` - if [ "$JAVA_NUM" '<' "$JAVA_VERSION" ]; then - echo -e "Java version $INSTALLED_JAVA is lower than the required version of $JAVA_VERSION. \n" - if [ "$OS" = "centos" ]; then - printf "It is recommended that you run \"sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel\".\n" - if ask "May we perform this task for you?"; then - sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel + if [ -d "$JRE_HOME" ]; then + INSTALLED_JAVA=`$JRE_HOME/java -version 2>&1 | head -n 1 | cut -d\" -f 2` + JAVA_NUM=`echo $INSTALLED_JAVA | awk -F "." '{print $1"."$2}'` + if [ "$JAVA_NUM" '<' "$JAVA_VERSION" ]; then + echo -e "Java version $INSTALLED_JAVA is lower than the required version of $JAVA_VERSION. \n" + if [ "$OS" = "centos" ]; then + printf "It is recommended that you run \"sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel\".\n" + if ask "May we perform this task for you?"; then + sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel + fi + elif [[ "$OS" = "ubuntu" ]]; then + printf "It is recommended that you run \"sudo apt-get -y install openjdk-8-jdk\".\n" + if ask "May we perform this task for you?"; then + sudo add-apt-repository -y ppa:openjdk-r/ppa + sudo apt-get -y update + sudo apt-get -y install openjdk-8-jdk + fi + + elif [[ "$OS" = "suse" ]]; then + printf "It is recommended that you run \"sudo zypper --non-interactive install java-1_8_0-openjdk-devel\".\n" + if ask "May we perform this task for you?"; then + sudo zypper --non-interactive install java-1_8_0-openjdk-devel + fi fi - elif [[ "$OS" = "ubuntu" ]]; then - printf "It is recommended that you run \"sudo apt-get -y install openjdk-8-jdk\".\n" - if ask "May we perform this task for you?"; then + else + printf "Installed Java version meets the requirements. \n\n" + fi + else + printf "We are looking for Java in a specific location and not finding it. This won't change \n" + printf "any other Java settings you might have. \n\n" + if ask "May we install it where we need it?"; then + if [ "$OS" = "centos" ]; then + sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel + elif [[ "$OS" = "ubuntu" ]]; then sudo add-apt-repository -y ppa:openjdk-r/ppa sudo apt-get -y update sudo apt-get -y install openjdk-8-jdk - fi - - elif [[ "$OS" = "suse" ]]; then - printf "It is recommended that you run \"sudo zypper --non-interactive install java-1_8_0-openjdk-devel\".\n" - if ask "May we perform this task for you?"; then + elif [[ "$OS" = "suse" ]]; then sudo zypper --non-interactive install java-1_8_0-openjdk-devel fi fi - else - printf "Installed Java version meets the requirements. \n\n" - fi + fi } checkJDK() diff --git a/framework/src/onos/apps/cpman/pom.xml b/framework/src/onos/apps/cpman/pom.xml new file mode 100644 index 00000000..c01af6d8 --- /dev/null +++ b/framework/src/onos/apps/cpman/pom.xml @@ -0,0 +1,39 @@ + + + + 4.0.0 + + org.onosproject + onos-apps + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-app-cpman + bundle + + Control Plane Management Application + + + + org.onosproject + onos-api + 1.4.0-SNAPSHOT + + + diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMessageType.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMessageType.java new file mode 100644 index 00000000..82e414d9 --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMessageType.java @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +/** + * Abstracted Control Message Type. + */ +public enum ControlMessageType { + + /** Mapped to PACKET-IN message of OpenFlow. */ + INBOUND_PACKET, + + /** Mapped to PACKET-OUT message of OpenFlow. */ + OUTBOUND_PACKET, + + /** Mapped to FLOW-MOD message of OpenFlow. */ + FLOW_MOD_PACKET, + + /** Mapped to FLOW-REMOVED message of OpenFlow. */ + FLOW_REMOVED_PACKET, + + /** Mapped to STATS-REQUEST message of OpenFlow. */ + REQUEST_PACKET, + + /** Mapped to STATS-REPLY message of OpenFlow. */ + REPLY_PACKET, + + /** All message types. */ + ALL +} diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMetricType.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMetricType.java new file mode 100644 index 00000000..b5e82811 --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlMetricType.java @@ -0,0 +1,34 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +/** + * A set of metric type used in control plane. + */ +public enum ControlMetricType { + + /** Racket Rate of Control Message. */ + PacketRate, + + /** Byte Rate of Control Message. */ + ByteRate, + + /** Cpu Utilization. */ + CpuInfo, + + /** Memory Utilization. */ + MemoryInfo +} diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneLoad.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneLoad.java new file mode 100644 index 00000000..f55945fd --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneLoad.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +import org.onosproject.net.statistic.Load; + +import java.util.concurrent.TimeUnit; + +/** + * Data repository for control plane load information. + */ +public interface ControlPlaneLoad extends Load { + + /** + * Obtain the average of the specified time duration. + * + * @param duration time duration + * @param unit time unit + * @return average control plane metric value + */ + long average(int duration, TimeUnit unit); + + /** + * Obtain the average of all time duration. + * + * @return average control plane metric value + */ + long average(); +} diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneManager.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneManager.java new file mode 100644 index 00000000..5f3dee73 --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneManager.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +import com.sun.jndi.toolkit.ctx.ComponentContext; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Control plane management application. + */ +public class ControlPlaneManager { + + private final Logger log = getLogger(getClass()); + + @Activate + public void activate(ComponentContext context) { + + } + + @Deactivate + public void deactivate() { + + } + + @Modified + public void modified(ComponentContext context) { + + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneMetric.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneMetric.java new file mode 100644 index 00000000..19f4153a --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneMetric.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +/** + * Include various control plane metrics. + */ +public class ControlPlaneMetric { + + private ControlMetricType metricType; + private long metricValue; + + ControlMetricType metricType() { + return metricType; + } + + void setMetricType(ControlMetricType metricType) { + this.metricType = metricType; + } + + long metricValue() { + return metricValue; + } + + void setMetricValue(long metricValue) { + this.metricValue = metricValue; + } +} diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneStatsService.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneStatsService.java new file mode 100644 index 00000000..9fc2d7a9 --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/ControlPlaneStatsService.java @@ -0,0 +1,59 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cpman; + +import org.onosproject.cluster.NodeId; +import org.onosproject.net.DeviceId; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +/** + * Control Plane Statistics Service Interface. + */ +public interface ControlPlaneStatsService { + + /** + * Add a new control plane metric value with a certain update interval. + * + * @param cpm control plane metric (e.g., control message rate, cpu, memory, etc.) + * @param updateInterval value update interval (time unit will be in minute) + */ + void updateMetric(ControlPlaneMetric cpm, int updateInterval); + + /** + * Obtain the control plane load of a specific device. + * + * @param nodeId node id {@link org.onosproject.cluster.NodeId} + * @param type control metric type + * @param deviceId device id {@link org.onosproject.net.DeviceId} + * @return control plane load + */ + ControlPlaneLoad getLoad(NodeId nodeId, ControlMetricType type, Optional deviceId); + + /** + * Obtain the control plane load of a specific device with a specific time duration. + * + * @param nodeId node id {@link org.onosproject.cluster.NodeId} + * @param type control metric type + * @param duration time duration + * @param unit time unit + * @param deviceId device id {@link org.onosproject.net.Device} + * @return control plane load + */ + ControlPlaneLoad getLoad(NodeId nodeId, ControlMetricType type, Optional deviceId, + int duration, TimeUnit unit); +} \ No newline at end of file diff --git a/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/package-info.java b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/package-info.java new file mode 100644 index 00000000..e2c1dc85 --- /dev/null +++ b/framework/src/onos/apps/cpman/src/main/java/org/onosproject/cpman/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Application for control plane management. + */ +package org.onosproject.cpman; \ No newline at end of file diff --git a/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java index cd8149ea..6265fee0 100644 --- a/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java +++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java @@ -51,7 +51,7 @@ public class DhcpWebResource extends AbstractWebResource { * Shows lease, renewal and rebinding times in seconds. * * @return 200 OK - * @rsModel DhcpConfigGet + * @onos.rsModel DhcpConfigGet */ @GET @Path("config") @@ -68,7 +68,7 @@ public class DhcpWebResource extends AbstractWebResource { * Get all MAC/IP mappings. * Shows all MAC/IP mappings held by the DHCP server. * - * @rsModel DhcpConfigGetMappings + * @onos.rsModel DhcpConfigGetMappings * @return 200 OK */ @GET @@ -90,7 +90,7 @@ public class DhcpWebResource extends AbstractWebResource { * Get all available IPs. * Shows all the IPs in the free pool of the DHCP Server. * - * @rsModel DhcpConfigGetAvailable + * @onos.rsModel DhcpConfigGetAvailable * @return 200 OK */ @GET @@ -108,7 +108,7 @@ public class DhcpWebResource extends AbstractWebResource { * Post a new static MAC/IP binding. * Registers a static binding to the DHCP server, and displays the current set of bindings. * - * @rsModel DhcpConfigPut + * @onos.rsModel DhcpConfigPut * @param stream JSON stream * @return 200 OK */ diff --git a/framework/src/onos/apps/faultmanagement/app/app.xml b/framework/src/onos/apps/faultmanagement/app/app.xml new file mode 100644 index 00000000..288ccc49 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/app/app.xml @@ -0,0 +1,24 @@ + + + + ${project.description} + + mvn:${project.groupId}/onos-app-fm-mgr/${project.version} + mvn:${project.groupId}/onos-app-fm-web/${project.version} + diff --git a/framework/src/onos/apps/faultmanagement/app/features.xml b/framework/src/onos/apps/faultmanagement/app/features.xml new file mode 100644 index 00000000..86aab911 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/app/features.xml @@ -0,0 +1,25 @@ + + + + + onos-api + onos-drivers + mvn:${project.groupId}/onos-app-fm-mgr/${project.version} + mvn:${project.groupId}/onos-app-fm-web/${project.version} + + diff --git a/framework/src/onos/apps/faultmanagement/app/pom.xml b/framework/src/onos/apps/faultmanagement/app/pom.xml new file mode 100644 index 00000000..ef41cdde --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/app/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + + org.onosproject + onos-app-fm + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-app-fm-onosfw + pom + + ONOS framework applications + + + + org.onosproject + onos-app-fm-web + ${project.version} + + + org.onosproject + onos-app-fm-mgr + ${project.version} + + + + diff --git a/framework/src/onos/apps/faultmanagement/fmmgr/pom.xml b/framework/src/onos/apps/faultmanagement/fmmgr/pom.xml new file mode 100644 index 00000000..86b7cb67 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmmgr/pom.xml @@ -0,0 +1,54 @@ + + + + 4.0.0 + + org.onosproject + onos-app-fm + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-app-fm-mgr + bundle + + + + javax.ws.rs + jsr311-api + 1.1.1 + + + org.onosproject + onos-incubator-api + + + org.onosproject + onos-core-serializers + ${project.version} + + + org.osgi + org.osgi.compendium + 5.0.0 + jar + + + diff --git a/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/AlarmsManager.java b/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/AlarmsManager.java new file mode 100644 index 00000000..74fe7072 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/AlarmsManager.java @@ -0,0 +1,222 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.impl; + +import static com.google.common.base.Strings.isNullOrEmpty; +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.apache.felix.scr.annotations.Property; +import static org.onlab.util.Tools.nullIsNotFound; + +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEvent; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmListener; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.slf4j.Logger; +import static org.slf4j.LoggerFactory.getLogger; +import org.apache.felix.scr.annotations.Service; +import static org.onlab.util.Tools.get; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.IdGenerator; +import org.onosproject.core.CoreService; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.util.ItemNotFoundException; +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; +import org.osgi.service.component.ComponentContext; + +/** + * Implementation of the Alarm service. + */ +@Component(immediate = true) +@Service +public class AlarmsManager implements AlarmService { + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + private final Logger log = getLogger(getClass()); + private ApplicationId appId; + private IdGenerator idGenerator; + + + @Property(name = "fmDevices", value = "127.0.0.1", label = "Instance-specific configurations") + private String devConfigs; + + private final Map alarms = new ConcurrentHashMap<>(); + + + private final AtomicLong alarmIdGenerator = new AtomicLong(0); + + @Override + public Alarm update(final Alarm replacement) { + + final Alarm found = alarms.get(replacement.id()); + if (found == null) { + throw new ItemNotFoundException("Alarm with id " + replacement.id() + " found"); + } + final Alarm updated = new DefaultAlarm.Builder(found). + withAcknowledged(replacement.acknowledged()). + withAssignedUser(replacement.assignedUser()).build(); + alarms.put(replacement.id(), updated); + return updated; + } + + @Override + public int getActiveAlarmCount(final DeviceId deviceId) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + private static final String NOT_SUPPORTED_YET = "Not supported yet."; + + @Override + public Alarm getAlarm(final AlarmId alarmId) { + return nullIsNotFound( + alarms.get(alarmId), + "Alarm is not found"); + } + + @Override + public Set getAlarms() { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + @Override + public Set getActiveAlarms() { + // Enpty set if no values + return alarms.isEmpty() ? new HashSet<>() : new HashSet<>(alarms.values()); + + } + + private static DefaultAlarm generateFake(final DeviceId deviceId, final AlarmId alarmId) { + + return new DefaultAlarm.Builder( + alarmId, deviceId, "NE is not reachable", Alarm.SeverityLevel.MAJOR, System.currentTimeMillis()). + withTimeUpdated(System.currentTimeMillis()). + withServiceAffecting(true) + .withAcknowledged(true). + withManuallyClearable(true) + .withAssignedUser("user1").build(); + } + + @Override + public Set getAlarms(final Alarm.SeverityLevel severity) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + @Override + public Set getAlarms(final DeviceId deviceId) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + @Override + public Set getAlarms(final DeviceId deviceId, final AlarmEntityId source) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + @Override + public Set getAlarmsForLink(final ConnectPoint src, final ConnectPoint dst) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + @Override + public Set getAlarmsForFlow(final DeviceId deviceId, final long flowId) { + //TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + + private void discoverAlarmsForDevice(final DeviceId deviceId) { + final AlarmId alarmId = new AlarmId(alarmIdGenerator.incrementAndGet()); + + // TODO In a new thread invoke SNMP Provider with DeviceId and device type and when done update our of alarms + // + alarms.put(alarmId, generateFake(deviceId, alarmId)); + + } + + private class InternalAlarmListener implements AlarmListener { + + @Override + public void event(final AlarmEvent event) { + // TODO + throw new UnsupportedOperationException(NOT_SUPPORTED_YET); + } + } + + @Activate + public void activate(final ComponentContext context) { + log.info("Activate ..."); + appId = coreService.registerApplication("org.onos.faultmanagement.alarms"); + idGenerator = coreService.getIdGenerator("alarm-ids"); + log.info("Started with appId={} idGenerator={}", appId, idGenerator); + + final boolean result = modified(context); + log.info("modified result = {}", result); + + } + + @Deactivate + public void deactivate(final ComponentContext context) { + log.info("Deactivate ..."); + // cfgService.unregisterProperties(getClass(), false); + + log.info("Stopped"); + } + + @Modified + public boolean modified(final ComponentContext context) { + log.info("context={}", context); + if (context == null) { + log.info("No configuration file"); + return false; + } + final Dictionary properties = context.getProperties(); + final String ipaddresses = get(properties, "fmDevices"); + log.info("Settings: devConfigs={}", ipaddresses); + if (!isNullOrEmpty(ipaddresses)) { + discover(ipaddresses); + + } + return true; + } + + private void discover(final String ipaddresses) { + for (String deviceEntry : ipaddresses.split(",")) { + final DeviceId deviceId = DeviceId.deviceId(deviceEntry); + if (deviceId != null) { + log.info("Device {} needs to have its alarms refreshed!", deviceId); + discoverAlarmsForDevice(deviceId); + } + } + } + +} diff --git a/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/package-info.java b/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/package-info.java new file mode 100644 index 00000000..a3f56459 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmmgr/src/main/java/org/onosproject/faultmanagement/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Fault Management application implementation. + */ +package org.onosproject.faultmanagement.impl; diff --git a/framework/src/onos/apps/faultmanagement/fmweb/pom.xml b/framework/src/onos/apps/faultmanagement/fmweb/pom.xml new file mode 100644 index 00000000..8d759710 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/pom.xml @@ -0,0 +1,141 @@ + + + + 4.0.0 + + org.onosproject + onos-app-fm + 1.4.0-SNAPSHOT + ../pom.xml + + + + onos-app-fm-web + bundle + + /onos/v1/fm + 1.0.0 + ONOS Fault Management Application REST API + + APIs for interacting with the Fault Management application. + + org.onos.faultmanagement.web + + + + + javax.ws.rs + jsr311-api + 1.1.1 + + + org.onosproject + onos-incubator-api + ${project.version} + jar + + + org.onosproject + onlab-osgi + ${project.version} + tests + test + + + com.sun.jersey + jersey-client + 1.19 + test + jar + + + org.onosproject + onos-core-common + ${project.version} + test + jar + + + org.onosproject + onos-rest + ${project.version} + test + jar + + + + org.onosproject + onos-rest + ${project.version} + tests + test + + + + com.sun.jersey.jersey-test-framework + jersey-test-framework-core + 1.19 + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + <_wab>src/main/webapp/ + + WEB-INF/classes/apidoc/swagger.json=target/swagger.json, + {maven-resources} + + + ${project.groupId}.${project.artifactId} + + + org.slf4j, + org.osgi.framework, + javax.ws.rs, + javax.ws.rs.core, + com.sun.jersey.api.core, + com.sun.jersey.spi.container.servlet, + com.sun.jersey.server.impl.container.servlet, + com.fasterxml.jackson.databind, + com.fasterxml.jackson.databind.node, + com.fasterxml.jackson.core, + org.apache.karaf.shell.commands, + org.apache.commons.lang.math.*, + com.google.common.*, + org.onlab.packet.*, + org.onlab.rest.*, + org.onosproject.*, + org.onlab.util.*, + org.jboss.netty.util.* + + ${web.context} + + + + + + + diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java new file mode 100644 index 00000000..a764c908 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmCodec.java @@ -0,0 +1,101 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import com.fasterxml.jackson.databind.JsonNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; +import org.onosproject.net.DeviceId; +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; +import org.slf4j.Logger; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of encoder for Alarm codec. + */ +public final class AlarmCodec extends JsonCodec { + + private final Logger log = getLogger(getClass()); + + @Override + public ObjectNode encode(final Alarm alarm, final CodecContext context) { + checkNotNull(alarm, "Alarm cannot be null"); + + return context.mapper().createObjectNode() + .put("id", alarm.id().fingerprint()) + .put("deviceId", alarm.deviceId().toString()) + .put("description", alarm.description()) + .put("source", + alarm.source() == null ? null + : alarm.source().toString()) + .put("timeRaised", alarm.timeRaised()) + .put("timeUpdated", alarm.timeUpdated()) + .put("timeCleared", alarm.timeCleared()) + .put("severity", alarm.severity().toString()) + .put("serviceAffecting", alarm.serviceAffecting()) + .put("acknowledged", alarm.acknowledged()) + .put("manuallyClearable", alarm.manuallyClearable()) + .put("assignedUser", alarm.assignedUser()); + + } + + @Override + public Alarm decode(final ObjectNode json, final CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + log.debug("id={}, full json={} ", json.get("id"), json); + final Long id = json.get("id").asLong(); + + final DeviceId deviceId = DeviceId.deviceId(json.get("deviceId").asText()); + final String description = json.get("description").asText(); + final Long timeRaised = json.get("timeRaised").asLong(); + final Long timeUpdated = json.get("timeUpdated").asLong(); + + final JsonNode jsonTimeCleared = json.get("timeCleared"); + final Long timeCleared = jsonTimeCleared == null || jsonTimeCleared.isNull() ? null : jsonTimeCleared.asLong(); + + final Alarm.SeverityLevel severity + = Alarm.SeverityLevel.valueOf(json.get("severity").asText().toUpperCase()); + + final Boolean serviceAffecting = json.get("serviceAffecting").asBoolean(); + final Boolean acknowledged = json.get("acknowledged").asBoolean(); + final Boolean manuallyClearable = json.get("manuallyClearable").asBoolean(); + + final JsonNode jsonAssignedUser = json.get("assignedUser"); + final String assignedUser + = jsonAssignedUser == null || jsonAssignedUser.isNull() ? null : jsonAssignedUser.asText(); + + return new DefaultAlarm.Builder( + AlarmId.valueOf(id), deviceId, description, severity, timeRaised).forSource(AlarmEntityId.NONE). + withTimeUpdated(timeUpdated). + withTimeCleared(timeCleared). + withServiceAffecting(serviceAffecting). + withAcknowledged(acknowledged). + withManuallyClearable(manuallyClearable). + withAssignedUser(assignedUser). + build(); + + } +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java new file mode 100644 index 00000000..56c891cd --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/AlarmsWebResource.java @@ -0,0 +1,148 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.io.InputStream; +import org.onosproject.rest.AbstractWebResource; + +import javax.ws.rs.core.Response; +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService; +import org.slf4j.Logger; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Alarms on devices or ONOS. + */ +@Path("alarms") +public class AlarmsWebResource extends AbstractWebResource { + + public static final String ALARM_NOT_FOUND = "Alarm is not found"; + + private final Logger log = getLogger(getClass()); + + public AlarmsWebResource() { + get(CodecService.class).registerCodec(Alarm.class, new AlarmCodec()); + } + + /** + * Get all alarms. Returns a list of all alarms across all devices. + * + * @param includeCleared include recently cleared alarms in response + * @return JSON encoded set of alarms + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getAlarms(@DefaultValue("false") @QueryParam("includeCleared") final boolean includeCleared + ) { + + log.info("Requesting all alarms, includeCleared={}", includeCleared); + final AlarmService service = get(AlarmService.class); + + final Iterable alarms = includeCleared + ? service.getAlarms() + : service.getActiveAlarms(); + + final ObjectNode result = new ObjectMapper().createObjectNode(); + result.set("alarms", + codec(Alarm.class). + encode(alarms, this)); + return ok(result.toString()).build(); + + } + + /** + * Get specified alarm. Returns details of the specified alarm. + * + * @param id ONOS allocated identifier + * @return JSON encoded alarm + */ + @GET + @Path("{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response getAlarm(@PathParam("id") final String id) { + log.info("HTTP GET alarm for id={}", id); + + final AlarmId alarmId = toAlarmId(id); + final Alarm alarm = get(AlarmService.class).getAlarm(alarmId); + + final ObjectNode result = mapper().createObjectNode(); + result.set("alarm", codec(Alarm.class).encode(alarm, this)); + return ok(result.toString()).build(); + } + + /** + * Update book-keeping fields on the alarm. Returns an up-to-date version of the alarm. Some of its fields may have + * been updated since the REST client last retrieved the alarm being updated. + * + * @param alarmIdPath + * @param stream input JSON + * @return updated JSON encoded alarm + */ + @PUT + @Path("{alarm_id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response update(@PathParam("alarm_id") final String alarmIdPath, final InputStream stream) { + log.info("PUT NEW ALARM at /{}", alarmIdPath); + + try { + final ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); + log.info("jsonTree={}", jsonTree); + + final Alarm alarm = codec(Alarm.class).decode(jsonTree, this); + + final AlarmService service = get(AlarmService.class); + + if (Long.parseLong(alarmIdPath) != alarm.id().fingerprint()) { + throw new IllegalArgumentException("id in path is " + Long.parseLong(alarmIdPath) + + " but payload uses id=" + alarm.id().fingerprint()); + + } + final Alarm updated = service.update(alarm); + final ObjectNode encoded = new AlarmCodec().encode(updated, this); + return ok(encoded.toString()).build(); + + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + } + + private static AlarmId toAlarmId(final String id) { + try { + return AlarmId.valueOf(Long.parseLong(id)); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Alarm id should be numeric", ex); + } + + } + +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java new file mode 100644 index 00000000..9c291231 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/main/java/org/onosproject/faultmanagement/web/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Fault management web support. + */ +package org.onosproject.faultmanagement.web; diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/faultmanagement/fmweb/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..18671f01 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,42 @@ + + + + FM2 REST API v1.0 + + + JAX-RS Service + com.sun.jersey.spi.container.servlet.ServletContainer + + com.sun.jersey.config.property.resourceConfigClass + com.sun.jersey.api.core.ClassNamesResourceConfig + + + com.sun.jersey.config.property.classnames + + org.onosproject.faultmanagement.web.AlarmsWebResource + + 10 + + + + JAX-RS Service + /* + + diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecContext.java b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecContext.java new file mode 100644 index 00000000..89886e8a --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecContext.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; + +/** + * Mock codec context for use in codec unit tests. + */ +public class AlarmCodecContext implements CodecContext { + + private final ObjectMapper mapper = new ObjectMapper(); + private final Map, JsonCodec> codecs = new ConcurrentHashMap<>(); + + /** + * Constructs a new mock codec context. + */ + public AlarmCodecContext() { + codecs.clear(); + registerCodec(Alarm.class, new AlarmCodec()); + + } + + @Override + public ObjectMapper mapper() { + return mapper; + } + + @SuppressWarnings("unchecked") + @Override + public T getService(Class serviceClass) { + // TODO + return null; + } + + /** + * Registers the specified JSON codec for the given entity class. + * + * @param entityClass entity class + * @param codec JSON codec + * @param entity type + */ + public void registerCodec(Class entityClass, JsonCodec codec) { + codecs.putIfAbsent(entityClass, codec); + } + + @SuppressWarnings("unchecked") + @Override + public JsonCodec codec(Class entityClass) { + return codecs.get(entityClass); + } +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecTest.java b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecTest.java new file mode 100644 index 00000000..3009b99a --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmCodecTest.java @@ -0,0 +1,140 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.io.InputStream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +import org.junit.Test; +import org.onosproject.codec.JsonCodec; +import static org.onosproject.faultmanagement.web.AlarmJsonMatcher.matchesAlarm; +import org.onosproject.net.DeviceId; +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId; +import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; + +public class AlarmCodecTest { + + private final AlarmCodecContext context = new AlarmCodecContext(); + + // Use this to check handling for miminal Alarm + private final Alarm alarmMinimumFields = new DefaultAlarm.Builder( + new AlarmId(44), + DeviceId.deviceId("of:2222000000000000"), + "NE unreachable", + Alarm.SeverityLevel.CLEARED, + 1). + build(); + + // Use this to check handling for fully populated Alarm + private final Alarm alarmWithSource = new DefaultAlarm.Builder( + new AlarmId(44), + DeviceId.deviceId("of:2222000000000000"), + "NE unreachable", + Alarm.SeverityLevel.CLEARED, 1). + forSource(AlarmEntityId.alarmEntityId("port:1/2/3/4")). + withTimeUpdated(2). + withTimeCleared(3L). + withServiceAffecting(true). + withAcknowledged(true). + withManuallyClearable(true). + withAssignedUser("the assigned user").build(); + + @Test + public void alarmCodecTestWithOptionalFieldMissing() { + //context.registerService(AlarmService.class, new AlarmServiceAdapter()); + final JsonCodec codec = context.codec(Alarm.class); + assertThat(codec, is(notNullValue())); + + final ObjectNode alarmJson = codec.encode(alarmMinimumFields, context); + assertThat(alarmJson, notNullValue()); + assertThat(alarmJson, matchesAlarm(alarmMinimumFields)); + + } + + @Test + public void alarmCodecTestWithOptionalField() { + final JsonCodec codec = context.codec(Alarm.class); + assertThat(codec, is(notNullValue())); + + final ObjectNode alarmJson = codec.encode(alarmWithSource, context); + assertThat(alarmJson, notNullValue()); + assertThat(alarmJson, matchesAlarm(alarmWithSource)); + + } + + @Test + public void verifyMinimalAlarmIsEncoded() throws Exception { + final JsonCodec alarmCodec = context.codec(Alarm.class); + + final Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-minimal.json"); + assertCommon(alarm); + + assertThat(alarm.timeCleared(), nullValue()); + assertThat(alarm.assignedUser(), nullValue()); + + } + + @Test + public void verifyFullyLoadedAlarmIsEncoded() throws Exception { + final JsonCodec alarmCodec = context.codec(Alarm.class); + + final Alarm alarm = getDecodedAlarm(alarmCodec, "alarm-full.json"); + assertCommon(alarm); + + assertThat(alarm.timeCleared(), is(2222L)); + assertThat(alarm.assignedUser(), is("foo")); + + } + + private void assertCommon(final Alarm alarm) { + assertThat(alarm.id(), is(new AlarmId(10L))); + assertThat(alarm.description(), is("NE is not reachable")); + assertThat(alarm.source(), is(AlarmEntityId.NONE)); + assertThat(alarm.timeRaised(), is(999L)); + assertThat(alarm.timeUpdated(), is(1111L)); + assertThat(alarm.severity(), is(Alarm.SeverityLevel.MAJOR)); + assertThat(alarm.serviceAffecting(), is(true)); + assertThat(alarm.acknowledged(), is(false)); + assertThat(alarm.manuallyClearable(), is(true)); + } + + /** + * Reads in a rule from the given resource and decodes it. + * + * @param resourceName resource to use to read the JSON for the rule + * @return decoded flow rule + * @throws IOException if processing the resource failsdecode + */ + private Alarm getDecodedAlarm(final JsonCodec codec, final String resourceName) throws IOException { + final InputStream jsonStream = AlarmCodecTest.class + .getResourceAsStream(resourceName); + final JsonNode json = context.mapper().readTree(jsonStream); + assertThat(json, notNullValue()); + final Alarm result = codec.decode((ObjectNode) json, context); + assertThat(result, notNullValue()); + return result; + } + + +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmJsonMatcher.java b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmJsonMatcher.java new file mode 100644 index 00000000..14bb45f3 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmJsonMatcher.java @@ -0,0 +1,135 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; + +import com.fasterxml.jackson.databind.JsonNode; + +/** + * Hamcrest matcher for alarms. + */ +public final class AlarmJsonMatcher extends TypeSafeDiagnosingMatcher { + + private final Alarm alarm; + + private AlarmJsonMatcher(final Alarm alarm) { + this.alarm = alarm; + } + + @Override + public boolean matchesSafely(final JsonNode jsonAlarm, final Description description) { + final String jsonAlarmId = jsonAlarm.get("id").asText(); + final String alarmId = Long.toString(alarm.id().fingerprint()); + if (!jsonAlarmId.equals(alarmId)) { + description.appendText("alarm id was " + jsonAlarmId); + return false; + } + + final String jsonDeviceId = jsonAlarm.get("deviceId").asText(); + final String alarmDeviceId = alarm.deviceId().toString(); + if (!jsonDeviceId.equals(alarmDeviceId)) { + description.appendText("DeviceId was " + jsonDeviceId); + return false; + } + + + final String jsonDescription = jsonAlarm.get("description").asText(); + final String alarmDesc = alarm.description(); + if (!jsonDescription.equals(alarmDesc)) { + description.appendText("description was " + jsonDescription); + return false; + } + + final long jsonTimeRaised = jsonAlarm.get("timeRaised").asLong(); + final long timeRaised = alarm.timeRaised(); + if (timeRaised != jsonTimeRaised) { + description.appendText("timeRaised was " + jsonTimeRaised); + return false; + } + + + final long jsonTimeUpdated = jsonAlarm.get("timeUpdated").asLong(); + final long timeUpdated = alarm.timeUpdated(); + if (timeUpdated != jsonTimeUpdated) { + description.appendText("timeUpdated was " + jsonTimeUpdated); + return false; + } + + final JsonNode jsonTimeClearedNode = jsonAlarm.get("timeCleared"); + + if (alarm.timeCleared() != null) { + final Long jsonTimeCleared = jsonTimeClearedNode.longValue(); + final Long timeCleared = alarm.timeCleared(); + + if (!timeCleared.equals(jsonTimeCleared)) { + description.appendText("Time Cleared was " + jsonTimeCleared); + return false; + } + } else { + // No clear time not specified, JSON representation must be empty + if (!jsonTimeClearedNode.isNull()) { + description.appendText("Time Cleared should be null"); + return false; + } + } + + final String jsonSeverity = jsonAlarm.get("severity").asText(); + final String severity = alarm.severity().toString(); + if (!severity.equals(jsonSeverity)) { + description.appendText("severity was " + jsonSeverity); + return false; + } + + final JsonNode jsonAlarmNode = jsonAlarm.get("source"); + + if (alarm.source() != null) { + final String jsonSource = jsonAlarmNode.textValue(); + final String source = alarm.source().toString(); + + if (!source.equals(jsonSource)) { + description.appendText("source was " + jsonSource); + return false; + } + } else { + // source not specified, JSON representation must be empty + if (!jsonAlarmNode.isNull()) { + description.appendText("source should be null"); + return false; + } + } + + // In progress + return true; + } + + @Override + public void describeTo(final Description description) { + description.appendText(alarm.toString()); + } + + /** + * Factory to allocate a alarm matcher. + * + * @param alarm alarm object we are looking for + * @return matcher + */ + public static AlarmJsonMatcher matchesAlarm(final Alarm alarm) { + return new AlarmJsonMatcher(alarm); + } +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java new file mode 100644 index 00000000..0b7d9811 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.faultmanagement.web; + +import com.sun.jersey.api.client.WebResource; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import org.junit.Ignore; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.codec.CodecService; +import org.onosproject.codec.impl.CodecManager; +import org.onosproject.rest.ResourceTest; + +/** + * Test of the Fault Management Web REST API for Alarms. + */ +public class AlarmsWebResourceTest extends ResourceTest { + + @Before + public void setUp() { + + final CodecManager codecService = new CodecManager(); + codecService.activate(); + + final ServiceDirectory testDirectory + = new TestServiceDirectory() + // Currently no alarms-service implemented + // .add(AlarmsService.class, alarmsService) + .add(CodecService.class, codecService); + BaseResource.setServiceDirectory(testDirectory); + } + + @Test + @Ignore + public void getAllAlarms() { + final WebResource rs = resource(); + final String response = rs.path("/alarms").get(String.class); + // Ensure hard-coded alarms returned okay + assertThat(response, containsString("\"NE is not reachable\",")); + assertThat(response, containsString("\"Equipment Missing\",")); + } + + @Test + @Ignore + public void getAlarm() { + final WebResource rs = resource(); + final String response = rs.path("/alarms/1").get(String.class); + // Ensure hard-coded alarms returned okay + assertThat(response, containsString("\"NE is not reachable\",")); + assertThat(response, not(containsString("\"Equipment Missing\","))); + } + +} diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-full.json b/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-full.json new file mode 100644 index 00000000..215fc938 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-full.json @@ -0,0 +1,15 @@ +{ + "id": 10, + "deviceId": "of:123", + "description": "NE is not reachable", + "source": "none:none", + "timeRaised": 999, + "timeUpdated": 1111, + "timeUpdated": 1111, + "timeCleared": 2222, + "severity": "MAJOR", + "serviceAffecting": true, + "acknowledged": false, + "manuallyClearable": true, + "assignedUser": "foo" +} \ No newline at end of file diff --git a/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-minimal.json b/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-minimal.json new file mode 100644 index 00000000..4a24db09 --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/fmweb/src/test/resources/org/onosproject/faultmanagement/web/alarm-minimal.json @@ -0,0 +1,12 @@ +{ + "id": 10, + "deviceId": "of:123", + "description": "NE is not reachable", + "source": "none:none", + "timeRaised": 999, + "timeUpdated": 1111, + "severity": "MAJOR", + "serviceAffecting": true, + "acknowledged": false, + "manuallyClearable": true +} \ No newline at end of file diff --git a/framework/src/onos/apps/faultmanagement/pom.xml b/framework/src/onos/apps/faultmanagement/pom.xml new file mode 100644 index 00000000..e7bb6a1b --- /dev/null +++ b/framework/src/onos/apps/faultmanagement/pom.xml @@ -0,0 +1,56 @@ + + + + 4.0.0 + + + org.onosproject + onos-apps + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-app-fm + pom + + ONOS framework applications + + + fmmgr + fmweb + app + + + + org.onosproject + onlab-junit + test + + + com.google.guava + guava-testlib + test + + + org.easymock + easymock + test + + + diff --git a/framework/src/onos/apps/iptopology-api/pom.xml b/framework/src/onos/apps/iptopology-api/pom.xml new file mode 100644 index 00000000..50cb4adc --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + org.onosproject + onos-apps + 1.4.0-SNAPSHOT + + onos-app-iptopology-api + bundle + + IP Layer Topology API + diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AreaId.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AreaId.java new file mode 100644 index 00000000..79a326da --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AreaId.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Area identifier class (32 Bit Area-ID). + */ +public class AreaId { + private final int areaId; + + /** + * Constructor to set area identifier. + * + * @param areaId area id + */ + public AreaId(int areaId) { + this.areaId = areaId; + } + + /** + * obtain area identifier. + * + * @return area identifier + */ + public int areaId() { + return areaId; + } + + @Override + public int hashCode() { + return Objects.hash(areaId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AreaId) { + AreaId other = (AreaId) obj; + return Objects.equals(areaId, other.areaId); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("areaId", areaId) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AsNumber.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AsNumber.java new file mode 100644 index 00000000..3159b20a --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/AsNumber.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Autonomous system Number class (32 Bit ASNumber). + */ +public class AsNumber { + private final int asNum; + + /** + * Constructor to set As number. + * + * @param asNum As number + */ + public AsNumber(int asNum) { + this.asNum = asNum; + } + + /** + * Obtain autonomous system number. + * + * @return autonomous system number + */ + public int asNum() { + return asNum; + } + + @Override + public int hashCode() { + return Objects.hash(asNum); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AsNumber) { + AsNumber other = (AsNumber) obj; + return Objects.equals(asNum, other.asNum); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("asNum", asNum) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Color.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Color.java new file mode 100644 index 00000000..cb38fa67 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Color.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents administrative group color. + * bit mask - least significant bit is referred to as 'group 0', + * and the most significant bit is referred to as 'group 31' + */ +public class Color { + private final int color; + + /** + * Constructor to initialize its parameter. + * + * @param color assigned by the network administrator + */ + public Color(int color) { + this.color = color; + } + + /** + * Obtains administrative group. + * + * @return administrative group + */ + public int color() { + return color; + } + + @Override + public int hashCode() { + return Objects.hash(color); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof Color) { + Color other = (Color) obj; + return Objects.equals(color, other.color); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("color", color) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDeviceIntf.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDeviceIntf.java new file mode 100644 index 00000000..e40cbfc0 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDeviceIntf.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onosproject.net.Element; + +/** + * Default Device interface implementation. + */ +public class DefaultDeviceIntf implements DeviceIntf { + + private final Element element; + private final DeviceInterface deviceInterface; + + /** + * Constructor to initialize device interface parameters. + * + * @param element parent network element + * @param deviceInterface device interface + */ + public DefaultDeviceIntf(Element element, DeviceInterface deviceInterface) { + this.element = element; + this.deviceInterface = deviceInterface; + } + + @Override + public Element element() { + return element; + } + + @Override + public DeviceInterface deviceInterface() { + return deviceInterface; + } + + @Override + public int hashCode() { + return Objects.hash(element, deviceInterface); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DefaultDeviceIntf) { + final DefaultDeviceIntf other = (DefaultDeviceIntf) obj; + return Objects.equals(this.element.id(), other.element.id()) + && Objects.equals(this.deviceInterface, other.deviceInterface); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("element", element.id()) + .add("deviceInterface", deviceInterface) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDevicePrefix.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDevicePrefix.java new file mode 100644 index 00000000..2b1dde6f --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultDevicePrefix.java @@ -0,0 +1,95 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.AbstractAnnotated; +import org.onosproject.net.Annotations; +import org.onosproject.net.Element; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Default Device prefix implementation. + */ +public class DefaultDevicePrefix extends AbstractAnnotated implements DevicePrefix { + + private final Element element; + private final PrefixIdentifier prefixIdentifier; + private final PrefixTed prefixTed; + + /** + * Creates a network device prefix attributed to the specified element. + * + * @param element parent network element + * @param prefixIdentifier prefix identifier + * @param prefixTed prefid traffic engineering parameters + * @param annotations optional key/value annotations + */ + public DefaultDevicePrefix(Element element, PrefixIdentifier prefixIdentifier, + PrefixTed prefixTed, Annotations... annotations) { + super(annotations); + this.element = element; + this.prefixIdentifier = prefixIdentifier; + this.prefixTed = prefixTed; + } + + @Override + public Element element() { + return element; + } + + @Override + public PrefixIdentifier prefixIdentifier() { + return prefixIdentifier; + } + + @Override + public PrefixTed prefixTed() { + return prefixTed; + } + + @Override + public int hashCode() { + return Objects.hash(element, prefixIdentifier, prefixTed); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof DefaultDevicePrefix) { + final DefaultDevicePrefix other = (DefaultDevicePrefix) obj; + return Objects.equals(this.element.id(), other.element.id()) && + Objects.equals(this.prefixIdentifier, other.prefixIdentifier) && + Objects.equals(this.prefixTed, other.prefixTed) && + Objects.equals(this.annotations(), other.annotations()); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("element", element.id()) + .add("prefixIdentifier", prefixIdentifier) + .add("prefixTed", prefixTed) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpDevice.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpDevice.java new file mode 100644 index 00000000..a2d0165c --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpDevice.java @@ -0,0 +1,113 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.AbstractElement; +import org.onosproject.net.Annotations; +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderId; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Default ip device model implementation. + */ +public class DefaultIpDevice extends AbstractElement implements IpDevice { + + private final Type type; + private final IpDeviceIdentifier deviceIdentifier; + private final DeviceTed deviceTed; + + + /** + * For Serialization. + */ + private DefaultIpDevice() { + this.type = null; + this.deviceIdentifier = null; + this.deviceTed = null; + } + + /** + * Creates a network element attributed to the specified provider. + * + * @param providerId identity of the provider + * @param id device identifier + * @param type device type + * @param deviceIdentifier provides device identifier details + * @param deviceTed device traffic engineering parameters + * @param annotations optional key/value annotations + */ + public DefaultIpDevice(ProviderId providerId, DeviceId id, Type type, + IpDeviceIdentifier deviceIdentifier, DeviceTed deviceTed, + Annotations... annotations) { + super(providerId, id, annotations); + this.type = type; + this.deviceIdentifier = deviceIdentifier; + this.deviceTed = deviceTed; + } + + @Override + public DeviceId id() { + return (DeviceId) id; + } + + @Override + public Type type() { + return type; + } + + @Override + public IpDeviceIdentifier deviceIdentifier() { + return deviceIdentifier; + } + + @Override + public DeviceTed deviceTed() { + return deviceTed; } + + @Override + public int hashCode() { + return Objects.hash(type, deviceIdentifier, deviceTed); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DefaultIpDevice) { + final DefaultIpDevice other = (DefaultIpDevice) obj; + return Objects.equals(this.id, other.id) && + Objects.equals(this.type, other.type) && + Objects.equals(this.deviceIdentifier, other.deviceIdentifier) && + Objects.equals(this.deviceTed, other.deviceTed); + } + return false; + } + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("id", id) + .add("deviceIdentifier", deviceIdentifier) + .add("deviceTed", deviceTed) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpLink.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpLink.java new file mode 100644 index 00000000..41f06047 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DefaultIpLink.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.AbstractModel; +import org.onosproject.net.Annotations; +import org.onosproject.net.provider.ProviderId; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * This class provides Link identifier and link ted details. + */ +public class DefaultIpLink extends AbstractModel implements IpLink { + + private final TerminationPoint src; + private final TerminationPoint dst; + private final IpLinkIdentifier linkIdentifier; + private final LinkTed linkTed; + + /** + * Constructor to initialize its parameters. + * + * @param src link source termination point + * @param dst link destination termination point + * @param linkIdentifier provides link identifier details + * @param linkTed provides link traffic engineering details + * @param annotations optional key/value annotations + */ + public DefaultIpLink(ProviderId providerId, TerminationPoint src, TerminationPoint dst, + IpLinkIdentifier linkIdentifier, LinkTed linkTed, + Annotations... annotations) { + super(providerId, annotations); + this.src = src; + this.dst = dst; + this.linkIdentifier = linkIdentifier; + this.linkTed = linkTed; + } + + @Override + public TerminationPoint src() { + return src; + } + + @Override + public TerminationPoint dst() { + return dst; + } + + @Override + public IpLinkIdentifier linkIdentifier() { + return linkIdentifier; + } + + @Override + public LinkTed linkTed() { + return linkTed; + } + + @Override + public int hashCode() { + return Objects.hash(src, dst, linkIdentifier, linkTed); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof DefaultIpLink) { + final DefaultIpLink other = (DefaultIpLink) obj; + return Objects.equals(this.src, other.src) && + Objects.equals(this.dst, other.dst) && + Objects.equals(this.linkIdentifier, other.linkIdentifier) && + Objects.equals(this.linkTed, other.linkTed); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("src", src) + .add("dst", dst) + .add("linkIdentifier", linkIdentifier) + .add("linkTed", linkTed) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceInterface.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceInterface.java new file mode 100644 index 00000000..131aa623 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceInterface.java @@ -0,0 +1,100 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import java.util.Objects; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; + +import com.google.common.base.MoreObjects; + +/** + * Representation of device interface. + */ +public class DeviceInterface { + private final Ip4Address ip4Address; + private final Ip6Address ip6Address; + private final InterfaceIdentifier interfaceId; + + /** + * Constructor to initialize its parameter. + * + * @param ip4Address ipv4 interface address + * @param ip6Address ipv6 interface address + * @param interfaceId interface Identifier + */ + public DeviceInterface(Ip4Address ip4Address, Ip6Address ip6Address, InterfaceIdentifier interfaceId) { + this.ip4Address = ip4Address; + this.ip6Address = ip6Address; + this.interfaceId = interfaceId; + } + + /** + * obtains ipv4 address of an interface. + * + * @return ipv4 interface address + */ + public Ip4Address ip4Address() { + return ip4Address; + } + + /** + * obtains ipv6 interface address. + * + * @return ipv6 interface address + */ + public Ip6Address ip6Address() { + return ip6Address; + } + + /** + * obtains interface identifier. + * + * @return interface identifier + */ + public InterfaceIdentifier interfaceId() { + return interfaceId; + } + + @Override + public int hashCode() { + return Objects.hash(ip4Address, ip6Address, interfaceId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof DeviceInterface) { + final DeviceInterface other = (DeviceInterface) obj; + return Objects.equals(this.ip4Address, other.ip4Address) + && Objects.equals(this.ip6Address, other.ip6Address) + && Objects.equals(this.interfaceId, other.interfaceId); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("ip4Address", ip4Address) + .add("ip6Address", ip6Address) + .add("interfaceId", interfaceId) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceIntf.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceIntf.java new file mode 100644 index 00000000..ff18d3ac --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceIntf.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.Element; + +/** + * Abstraction of Device interface. + */ +public interface DeviceIntf { + /** + * Returns the parent network element to which this interface belongs. + * + * @return parent network element + */ + Element element(); + + /** + * Returns device interface details. + * + * @return device interface details + */ + DeviceInterface deviceInterface(); +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DevicePrefix.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DevicePrefix.java new file mode 100644 index 00000000..89efccd4 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DevicePrefix.java @@ -0,0 +1,46 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.Annotated; +import org.onosproject.net.Element; + +/** + * Abstraction of Device Prefix. + */ +public interface DevicePrefix extends Annotated { + + /** + * Returns the parent network element to which this port belongs. + * + * @return parent network element + */ + Element element(); + + /** + * Returns prefix identifier details. + * + * @return prefix identifier details + */ + PrefixIdentifier prefixIdentifier(); + + /** + * Returns prefix Traffic engineering parameters. + * + * @return prefix Traffic engineering parameters + */ + PrefixTed prefixTed(); +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceTed.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceTed.java new file mode 100644 index 00000000..4d9da55d --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DeviceTed.java @@ -0,0 +1,173 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; + +/** + * Represents Device Traffic Engineering parameters. + */ +public class DeviceTed { + private final List ipv4RouterIds; + private final List ipv6RouterIds; + private final List topologyIds; + private final Position position; + + /** + * Constructor to initialize the parameter fields. + * + * @param ipv4RouterIds Router ids of Ipv4 + * @param ipv6RouterIds Router ids of Ipv6 + * @param topologyIds list of multi-topology IDs of the node + * @param position of router whether it is ABR or ASBR + */ + public DeviceTed(List ipv4RouterIds, List ipv6RouterIds, + List topologyIds, Position position) { + this.ipv4RouterIds = ipv4RouterIds; + this.ipv6RouterIds = ipv6RouterIds; + this.topologyIds = topologyIds; + this.position = position; + } + + /** + * Obtain list of Ipv4 Router id. + * + * @return Ipv4 Router ids + */ + public List ipv4RouterIds() { + return ipv4RouterIds; + } + + /** + * Obtain list of Ipv6 Router id. + * + * @return Ipv6 Router ids + */ + public List ipv6RouterIds() { + return ipv6RouterIds; + } + + /** + * Obtain the list of topology ID's. + * + * @return list of topology id's + */ + public List topologyIds() { + return topologyIds; + } + + + /** + * Obtain position of device in the network. + * + * @return position of device in the network + */ + public Position position() { + return position; + } + + @Override + public int hashCode() { + return Objects.hash(ipv4RouterIds, ipv6RouterIds, topologyIds, position); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DeviceTed) { + int countObjSubTlv = 0; + int countOtherSubTlv = 0; + int countObjTopologyId = 0; + int countOtherTopologyId = 0; + boolean isCommonSubTlv = true; + boolean isCommonSubTlv6 = true; + boolean isCommonTopology = true; + DeviceTed other = (DeviceTed) obj; + Iterator objListIterator = other.ipv4RouterIds.iterator(); + countOtherSubTlv = other.ipv4RouterIds.size(); + countObjSubTlv = ipv4RouterIds.size(); + + Iterator objListIteratorIpv6 = other.ipv6RouterIds.iterator(); + int countOtherSubTlv6 = other.ipv6RouterIds.size(); + int countObjSubTlv6 = ipv6RouterIds.size(); + + Iterator topologyId = other.topologyIds.iterator(); + countOtherTopologyId = other.topologyIds.size(); + countObjTopologyId = topologyIds.size(); + + if (countObjSubTlv != countOtherSubTlv || countOtherSubTlv6 != countObjSubTlv6 + || countObjTopologyId != countOtherTopologyId) { + return false; + } else { + while (objListIterator.hasNext() && isCommonSubTlv) { + Ip4Address subTlv = objListIterator.next(); + //find index of that element and then get that from the list and then compare + if (ipv4RouterIds.contains(subTlv) && other.ipv4RouterIds.contains(subTlv)) { + isCommonSubTlv = Objects.equals(ipv4RouterIds.get(ipv4RouterIds.indexOf(subTlv)), + other.ipv4RouterIds.get(other.ipv4RouterIds.indexOf(subTlv))); + } else { + isCommonSubTlv = false; + } + } + while (objListIteratorIpv6.hasNext() && isCommonSubTlv6) { + Ip6Address subTlv = objListIteratorIpv6.next(); + //find index of that element and then get that from the list and then compare + if (ipv6RouterIds.contains(subTlv) && other.ipv6RouterIds.contains(subTlv)) { + isCommonSubTlv6 = Objects.equals(ipv6RouterIds.get(ipv6RouterIds.indexOf(subTlv)), + other.ipv6RouterIds.get(other.ipv6RouterIds.indexOf(subTlv))); + } else { + isCommonSubTlv6 = false; + } + } + while (topologyId.hasNext() && isCommonTopology) { + TopologyId subTlv = topologyId.next(); + //find index of that element and then get that from the list and then compare + if (topologyIds.contains(subTlv) && other.topologyIds.contains(subTlv)) { + isCommonTopology = Objects.equals(topologyIds.get(topologyIds.indexOf(subTlv)), + other.topologyIds.get(other.topologyIds.indexOf(subTlv))); + } else { + isCommonTopology = false; + } + } + return isCommonSubTlv && isCommonSubTlv6 && isCommonTopology + && Objects.equals(position, other.position); + } + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("ipv6RouterIds", ipv6RouterIds) + .add("ipv4RouterIds", ipv4RouterIds) + .add("topologyIds", topologyIds) + .add("position", position) + .toString(); + } + +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DomainId.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DomainId.java new file mode 100644 index 00000000..4fb10701 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/DomainId.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Domain Identifier(32 Bit). + */ +public class DomainId { + private final int domainIdentifier; + + /** + * Constructor to initialize domain identifier. + * + * @param domainIdentifier domain identifier + */ + public DomainId(int domainIdentifier) { + this.domainIdentifier = domainIdentifier; + } + + /** + * Obtain domain identifier. + * + * @return domain identifier + */ + public int domainIdentifier() { + return domainIdentifier; + } + + @Override + public int hashCode() { + return Objects.hash(domainIdentifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DomainId) { + DomainId other = (DomainId) obj; + return Objects.equals(domainIdentifier, other.domainIdentifier); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("domainIdentifier", domainIdentifier) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ExtendedRouteTag.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ExtendedRouteTag.java new file mode 100644 index 00000000..9bd87c1b --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ExtendedRouteTag.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents the extended igp administrative tags of the prefix. + */ +public class ExtendedRouteTag { + private final long extRouteTag; + + /** + * Constructor to initialize its parameter. + * + * @param extRouteTag extended ISIS route tag + */ + public ExtendedRouteTag(long extRouteTag) { + this.extRouteTag = extRouteTag; + } + + /** + * Obtains extended igp administrative tags. + * + * @return extended igp administrative tags + */ + public long extRouteTag() { + return extRouteTag; + } + + @Override + public int hashCode() { + return Objects.hash(extRouteTag); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof ExtendedRouteTag) { + ExtendedRouteTag other = (ExtendedRouteTag) obj; + return Objects.equals(extRouteTag, other.extRouteTag); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("extRouteTag", extRouteTag) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IgpFlags.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IgpFlags.java new file mode 100644 index 00000000..59084c04 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IgpFlags.java @@ -0,0 +1,114 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * This class provides implementation IS-IS and OSPF flags assigned to the prefix. + */ +public class IgpFlags { + private final boolean isisUpDown; + private final boolean ospfNoUnicast; + private final boolean ospfLclAddr; + private final boolean ospfNssa; + + /** + * Constructor to initialize its parameters. + * + * @param isisUpDown IS-IS Up/Down + * @param ospfNoUnicast OSPF no unicast + * @param ospfLclAddr OSPF local address + * @param ospfNssa OSPF propagate NSSA + */ + public IgpFlags(boolean isisUpDown, boolean ospfNoUnicast, boolean ospfLclAddr, + boolean ospfNssa) { + this.isisUpDown = isisUpDown; + this.ospfNoUnicast = ospfNoUnicast; + this.ospfLclAddr = ospfLclAddr; + this.ospfNssa = ospfNssa; + } + + /** + * Provides information whether IS-IS is Up/Down. + * + * @return IS-IS Up/Down bit enabled or not + */ + public boolean isisUpDown() { + return isisUpDown; + } + + /** + * Provides information whether OSPF is unicast or not. + * + * @return OSPF no unicast Bit set or not + */ + public boolean ospfNoUnicast() { + return ospfNoUnicast; + } + + /** + * Provides information on OSPF local address. + * + * @return OSPF local address Bit set or not + */ + public boolean ospfLclAddr() { + return ospfLclAddr; + } + + /** + * Provides information on OSPF propagate NSSA. + * + * @return OSPF propagate NSSA Bit set or not + */ + public boolean ospfNssa() { + return ospfNssa; + } + + @Override + public int hashCode() { + return Objects.hash(isisUpDown, ospfNoUnicast, ospfLclAddr, + ospfNssa); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IgpFlags) { + IgpFlags other = (IgpFlags) obj; + return Objects.equals(isisUpDown, other.isisUpDown) + && Objects.equals(ospfNoUnicast, other.ospfNoUnicast) + && Objects.equals(ospfLclAddr, other.ospfLclAddr) + && Objects.equals(ospfNssa, other.ospfNssa); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("isisUpDown", isisUpDown) + .add("ospfNoUnicast", ospfNoUnicast) + .add("ospfLclAddr", ospfLclAddr) + .add("ospfNssa", ospfNssa) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/InterfaceIdentifier.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/InterfaceIdentifier.java new file mode 100644 index 00000000..405e1417 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/InterfaceIdentifier.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * This class provides information on Local Interface Identifier and Remote + * Interface Identifier of the link. + */ +public class InterfaceIdentifier { + private final Integer identifier; + + /** + * Constructor to initialize identifier. + * + * @param identifier local/remote interface identifier + */ + public InterfaceIdentifier(Integer identifier) { + this.identifier = identifier; + } + + /** + * Provides the local/remote interface identifier of the link. + * + * @return interface identifier + */ + public Integer identifier() { + return identifier; + } + + @Override + public int hashCode() { + return Objects.hash(identifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof InterfaceIdentifier) { + InterfaceIdentifier other = (InterfaceIdentifier) obj; + return Objects.equals(identifier, other.identifier); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("identifier", identifier) + .toString(); + } +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDevice.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDevice.java new file mode 100644 index 00000000..131b7eae --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDevice.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.Element; + +/** + * Abstraction of Ip Device. + */ +public interface IpDevice extends Element { + /** + ** Enum type to store Device Type. + */ + enum Type { + /** + * Signifies that the device is pseudo device. + */ + PSEUDO, + + /** + * Signifies that the device is non-pseudo device. + */ + NONPSEUDO; + } + + /** + * Obtains device id. + * + * @return device id + */ + @Override + DeviceId id(); + + /** + * Obtains device type. + * + * @return device type + */ + Type type(); + + /** + * Obtains Device identifier details. + * + * @return identifier of the device + */ + IpDeviceIdentifier deviceIdentifier(); + + /** + * Obtains the traffic engineering parameters of the device. + * + * @return traffic engineering parameters of the device + */ + DeviceTed deviceTed(); +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDeviceIdentifier.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDeviceIdentifier.java new file mode 100644 index 00000000..472fe008 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpDeviceIdentifier.java @@ -0,0 +1,141 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents IP Device Identifiers. + */ +public class IpDeviceIdentifier { + + private final RouteDistinguisher routeDish; + private final RouteInstance routeInstance; + private final AsNumber asNum; + private final DomainId domainIdentifier; + private final AreaId areaId; + private final RouteIdentifier routerIdentifier; + + /** + * Constructor to initialize parameters. + * + * @param routeInstance routing protocol instance + * @param asNum AS number + * @param domainIdentifier BGP-LS domain + * @param areaId Area ID + * @param routerIdentifier IGP router ID + */ + public IpDeviceIdentifier(RouteDistinguisher routeDish, RouteInstance routeInstance, AsNumber asNum, + DomainId domainIdentifier, AreaId areaId, RouteIdentifier routerIdentifier) { + this.routeDish = routeDish; + this.areaId = areaId; + this.asNum = asNum; + this.domainIdentifier = domainIdentifier; + this.routeInstance = routeInstance; + this.routerIdentifier = routerIdentifier; + } + + /** + * Obtains Route Distinguisher of Ip Device. + * + * @return Area ID + */ + public RouteDistinguisher routeDish() { + return routeDish; + } + + /** + * Obtains Area ID if Ip Device. + * + * @return Area ID + */ + public AreaId areaId() { + return areaId; + } + + /** + * Obtains AS number of Ip Device. + * + * @return AS number + */ + public AsNumber asNum() { + return asNum; + } + + /** + * Obtains domain identifier of Ip Device. + * + * @return domain identifier + */ + public DomainId domainIdentifier() { + return domainIdentifier; + } + + /** + * Obtains Router id of Ip Device. + * + * @return Router id + */ + public RouteIdentifier routerIdentifier() { + return routerIdentifier; + } + + /** + * Obtains routing protocol instance. + * + * @return routing protocol instance + */ + public RouteInstance routeInstance() { + return routeInstance; + } + + @Override + public int hashCode() { + return Objects.hash(routeDish, areaId, asNum, domainIdentifier, routerIdentifier, routeInstance); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IpDeviceIdentifier) { + IpDeviceIdentifier other = (IpDeviceIdentifier) obj; + return Objects.equals(areaId, other.areaId) && Objects.equals(asNum, other.asNum) + && Objects.equals(domainIdentifier, other.domainIdentifier) + && Objects.equals(routerIdentifier, other.routerIdentifier) + && Objects.equals(routeInstance, other.routeInstance) + && Objects.equals(routeDish, other.routeDish); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("areaId", areaId) + .add("asNum", asNum) + .add("domainIdentifier", domainIdentifier) + .add("routerIdentifier", routerIdentifier) + .add("routeInstance", routeInstance) + .add("routeDish", routeDish) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLink.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLink.java new file mode 100644 index 00000000..d632d2db --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLink.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import org.onosproject.net.Annotated; +import org.onosproject.net.NetworkResource; +import org.onosproject.net.Provided; + +/** + * Abstraction of a network ip link. + */ +public interface IpLink extends Annotated, Provided, NetworkResource { + + /** + * Returns source termination point of link. + * + * @return source termination point of link + */ + TerminationPoint src(); + + /** + * Returns destination termination point of link. + * + * @return destination termination point of link + */ + TerminationPoint dst(); + + /** + * Returns link identifier details. + * + * @return link identifier details + */ + IpLinkIdentifier linkIdentifier(); + + /** + * Returns the link traffic engineering parameters. + * + * @return links traffic engineering parameters + */ + LinkTed linkTed(); +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLinkIdentifier.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLinkIdentifier.java new file mode 100644 index 00000000..8522f945 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpLinkIdentifier.java @@ -0,0 +1,161 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; + +/** + * Represents Ip Link Identifier. + */ +public class IpLinkIdentifier { + private final InterfaceIdentifier localIndentifier; + private final InterfaceIdentifier remoteIndentifier; + private final Ip4Address localIpv4Addr; + private final Ip4Address remoteIpv4Addr; + private final Ip6Address localIpv6Addr; + private final Ip6Address remoteIpv6Addr; + private final TopologyId topologyId; + + /** + * Constructor to initialize its parameters. + * + * @param localIndentifier local interface identifier of the link + * @param remoteIndentifier remote interface identifier of the link + * @param localIpv4Addr local IPv4 address of the link + * @param remoteIpv4Addr remote IPv4 address of the link + * @param localIpv6Addr local IPv6 address of the link + * @param remoteIpv6Addr remote IPv6 address of the link + * @param topologyId link topology identifier + */ + public IpLinkIdentifier(InterfaceIdentifier localIndentifier, InterfaceIdentifier remoteIndentifier, + Ip4Address localIpv4Addr, Ip4Address remoteIpv4Addr, Ip6Address localIpv6Addr, + Ip6Address remoteIpv6Addr, TopologyId topologyId) { + this.localIndentifier = localIndentifier; + this.remoteIndentifier = remoteIndentifier; + this.localIpv4Addr = localIpv4Addr; + this.remoteIpv4Addr = remoteIpv4Addr; + this.localIpv6Addr = localIpv6Addr; + this.remoteIpv6Addr = remoteIpv6Addr; + this.topologyId = topologyId; + } + + /** + * Obtains link local identifier. + * + * @return link local identifier + */ + public InterfaceIdentifier localIndentifier() { + return localIndentifier; + } + + /** + * Obtains link local identifier. + * + * @return link local identifier + */ + public InterfaceIdentifier remoteIndentifier() { + return remoteIndentifier; + } + + /** + * Obtains local IPv4 address of the link. + * + * @return local IPv4 address of the link + */ + public Ip4Address localIpv4Addr() { + return localIpv4Addr; + } + + /** + * Obtains remote IPv4 address of the link. + * + * @return remote IPv4 address of the link + */ + public Ip4Address remoteIpv4Addr() { + return remoteIpv4Addr; + } + + /** + * Obtains local IPv6 address of the link. + * + * @return local IPv6 address of the link + */ + public Ip6Address localIpv6Addr() { + return localIpv6Addr; + } + + /** + * Obtains remote IPv6 address of the link. + * + * @return remote IPv6 address of the link + */ + public Ip6Address remoteIpv6Addr() { + return remoteIpv6Addr; + } + + /** + * Obtains Topology ID of the link. + * + * @return Topology ID of the link + */ + public TopologyId topologyId() { + return topologyId; + } + + @Override + public int hashCode() { + return Objects.hash(localIndentifier, remoteIndentifier, localIpv4Addr, remoteIpv4Addr, + localIpv6Addr, remoteIpv6Addr, topologyId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IpLinkIdentifier) { + IpLinkIdentifier other = (IpLinkIdentifier) obj; + return Objects.equals(topologyId, other.topologyId) + && Objects.equals(localIndentifier, other.localIndentifier) + && Objects.equals(remoteIndentifier, other.remoteIndentifier) + && Objects.equals(localIpv4Addr, other.localIpv4Addr) + && Objects.equals(remoteIpv4Addr, other.remoteIpv4Addr) + && Objects.equals(localIpv6Addr, other.localIpv6Addr) + && Objects.equals(remoteIpv6Addr, other.remoteIpv6Addr); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("localIndentifier", localIndentifier) + .add("remoteIndentifier", remoteIndentifier) + .add("localIpv4Addr", localIpv4Addr) + .add("remoteIpv4Addr", remoteIpv4Addr) + .add("localIpv6Addr", localIpv6Addr) + .add("remoteIpv6Addr", remoteIpv6Addr) + .add("topologyId", topologyId) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpReachability.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpReachability.java new file mode 100644 index 00000000..8fdd4d31 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IpReachability.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.packet.IpPrefix; + +/** + * Provides information of IP address prefix in the IGP topology and a router advertises + * this to each of its BGP nexthop. + */ +public class IpReachability { + private final IpPrefix ipPrefix; + + /** + * Constructor to initialize IP prefix. + * + * @param ipPrefix IP address prefix + */ + public IpReachability(IpPrefix ipPrefix) { + this.ipPrefix = ipPrefix; + } + + /** + * Provides IP Address prefix reachability. + * + * @return IP Address prefix + */ + public IpPrefix ipPrefix() { + return ipPrefix; + } + + @Override + public int hashCode() { + return Objects.hash(ipPrefix); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IpReachability) { + IpReachability other = (IpReachability) obj; + return Objects.equals(ipPrefix, other.ipPrefix); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("ipPrefix", ipPrefix) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsIsPseudonode.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsIsPseudonode.java new file mode 100644 index 00000000..064d830b --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsIsPseudonode.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents the Pseudonode information of device in ISIS domain. + */ +public class IsIsPseudonode implements RouteIdentifier { + private final IsoNodeId isoNodeId; + private final byte psnIdentifier; + private final ProtocolType type; + + /** + * Constructor to initialize the values. + * + * @param isoNodeId ISO system-ID + * @param psnIdentifier Pseudonode identifier + * @param type Protocol ID + */ + public IsIsPseudonode(IsoNodeId isoNodeId, byte psnIdentifier, ProtocolType type) { + this.isoNodeId = isoNodeId; + this.psnIdentifier = psnIdentifier; + this.type = type; + } + + /** + * Obtains iso system id of Pseudonode of device in ISIS domain. + * + * @return ISO system Id + */ + public IsoNodeId isoNodeId() { + return isoNodeId; + } + + /** + * Obtains Pseudonode identifier. + * + * @return Pseudonode identifier + */ + public byte psnIdentifier() { + return psnIdentifier; + } + + @Override + public ProtocolType type() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(isoNodeId, psnIdentifier, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IsIsPseudonode) { + IsIsPseudonode other = (IsIsPseudonode) obj; + return Objects.equals(isoNodeId, other.isoNodeId) && Objects.equals(psnIdentifier, other.psnIdentifier) + && Objects.equals(type, other.type); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("isoNodeId", isoNodeId) + .add("psnIdentifier", psnIdentifier) + .add("type", type) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsoNodeId.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsoNodeId.java new file mode 100644 index 00000000..8bb3d8b9 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/IsoNodeId.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents ISO system id of the device. + */ +public class IsoNodeId implements RouteIdentifier { + private final byte[] isoNodeId; + private final ProtocolType type; + + /** + * Constructor to initialize the values. + * + * @param isoNodeId ISO system-ID + * @param type Protocol type + */ + public IsoNodeId(byte[] isoNodeId, ProtocolType type) { + this.isoNodeId = isoNodeId; + this.type = type; + } + + /** + * Obtains ISO system id of the device. + * + * @return ISO system id + */ + public byte[] isoNodeId() { + return isoNodeId; + } + + @Override + public ProtocolType type() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(isoNodeId, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IsoNodeId) { + IsoNodeId other = (IsoNodeId) obj; + return Objects.equals(isoNodeId, other.isoNodeId) && Objects.equals(type, other.type); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("isoNodeId", isoNodeId) + .add("type", type) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/LinkTed.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/LinkTed.java new file mode 100644 index 00000000..3a686034 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/LinkTed.java @@ -0,0 +1,349 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onlab.util.Bandwidth; + +/** + * Represents Link Traffic engineering parameters. + */ +public class LinkTed { + private final Bandwidth maximumLink; + private final Bandwidth maxReserved; + private final List maxUnResBandwidth; + private final Metric teMetric; + private final Metric igpMetric; + private final List ipv4LocRouterId; + private final List ipv6LocRouterId; + private final List ipv4RemRouterId; + private final List ipv6RemRouterId; + private final Color color; + private final Signalling signalType; + private final List srlgGroup; + private final ProtectionType protectType; + + /** + * Constructor to initialize its parameter. + * + * @param maximumLink maximum bandwidth can be used + * @param maxReserved max bandwidth that can be reserved + * @param maxUnResBandwidth amount of bandwidth reservable + * @param teMetric Traffic engineering metric + * @param igpMetric IGP metric + * @param color information on administrative group assigned to the interface + * @param signalType MPLS signaling protocols + * @param srlgGroup Shared Risk Link Group information + * @param protectType protection capabilities of the link + * @param ipv4LocRouterId IPv4 router-Id of local node + * @param ipv6LocRouterId IPv6 router-Id of local node + * @param ipv4RemRouterId IPv4 router-Id of remote node + * @param ipv6RemRouterId IPv6 router-Id of remote node + */ + public LinkTed(Bandwidth maximumLink, Bandwidth maxReserved, List maxUnResBandwidth, + Metric teMetric, Metric igpMetric, Color color, Signalling signalType, List srlgGroup, + ProtectionType protectType, List ipv4LocRouterId, List ipv6LocRouterId, + List ipv4RemRouterId, List ipv6RemRouterId) { + this.maximumLink = maximumLink; + this.maxReserved = maxReserved; + this.maxUnResBandwidth = maxUnResBandwidth; + this.teMetric = teMetric; + this.igpMetric = igpMetric; + this.color = color; + this.signalType = signalType; + this.srlgGroup = srlgGroup; + this.protectType = protectType; + this.ipv4LocRouterId = ipv4LocRouterId; + this.ipv6LocRouterId = ipv6LocRouterId; + this.ipv4RemRouterId = ipv4RemRouterId; + this.ipv6RemRouterId = ipv6RemRouterId; + } + + /** + * Provides maximum bandwidth can be used on the link. + * + * @return maximum bandwidth + */ + public Bandwidth maximumLink() { + return maximumLink; + } + + /** + * Amount of bandwidth reservable on the link. + * + * @return unreserved bandwidth + */ + public List maxUnResBandwidth() { + return maxUnResBandwidth; + } + + /** + * Provides max bandwidth that can be reserved on the link. + * + * @return max bandwidth reserved + */ + public Bandwidth maxReserved() { + return maxReserved; + } + + /** + * Provides Traffic engineering metric for the link. + * + * @return Traffic engineering metric + */ + public Metric teMetric() { + return teMetric; + } + + /** + * Provides IGP metric for the link. + * + * @return IGP metric + */ + public Metric igpMetric() { + return igpMetric; + } + + /** + * Provides protection capabilities of the link. + * + * @return link protection type + */ + public ProtectionType protectType() { + return protectType; + } + + /** + * Provides Shared Risk Link Group information. + * + * @return Shared Risk Link Group value + */ + public List srlgGroup() { + return srlgGroup; + } + + /** + * Provides which MPLS signaling protocols are enabled. + * + * @return signal type + */ + public Signalling signalType() { + return signalType; + } + + /** + * Provides information on administrative group assigned to the interface. + * + * @return 4-octect bit mask assigned by network administrator + */ + public Color color() { + return color; + } + + /** + * Provides IPv4 router-Id of local node. + * + * @return IPv4 router-Id of local node + */ + public List ipv4LocRouterId() { + return ipv4LocRouterId; + } + + /** + * Provides IPv6 router-Id of local node. + * + * @return IPv6 router-Id of local node + */ + public List ipv6LocRouterId() { + return ipv6LocRouterId; + } + + /** + * Provides IPv4 router-Id of remote node. + * + * @return IPv4 router-Id of remote node + */ + public List ipv4RemRouterId() { + return ipv4RemRouterId; + } + + /** + * Provides IPv6 router-Id of remote node. + * + * @return IPv6 router-Id of remote node + */ + public List ipv6RemRouterId() { + return ipv6RemRouterId; + } + + @Override + public int hashCode() { + return Objects.hash(maximumLink, maxReserved, maxUnResBandwidth, teMetric, igpMetric, + ipv4LocRouterId, ipv6LocRouterId, ipv4RemRouterId, ipv6RemRouterId, + color, signalType, srlgGroup, protectType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof LinkTed) { + int countCommonBandwidth = 0; + int countOtherCommonBandwidth = 0; + int countOther4LocRouterId = 0; + int countCommon4LocRouterId = 0; + int countOther6RemRouterId = 0; + int countCommon6RemRouterId = 0; + int countOther4RemRouterId = 0; + int countCommon4RemRouterId = 0; + int countCommon6LocRouterId = 0; + int countOther6LocRouterId = 0; + int countCommonSrlg = 0; + int countOtherSrlg = 0; + boolean isCommonBandwidth = true; + boolean isCommonIp4Loc = true; + boolean isCommonIp4Rem = true; + boolean isCommonIp6Loc = true; + boolean isCommonIp6Rem = true; + boolean isCommonSrlg = true; + LinkTed other = (LinkTed) obj; + Iterator objListIterator = other.maxUnResBandwidth.iterator(); + countOtherCommonBandwidth = other.maxUnResBandwidth.size(); + countCommonBandwidth = maxUnResBandwidth.size(); + + Iterator ipv4local = other.ipv4LocRouterId.iterator(); + countOther4LocRouterId = other.ipv4LocRouterId.size(); + countCommon4LocRouterId = ipv4LocRouterId.size(); + + Iterator ipv4remote = other.ipv4RemRouterId.iterator(); + countOther4RemRouterId = other.ipv4RemRouterId.size(); + countCommon4RemRouterId = ipv4RemRouterId.size(); + + Iterator ipv6local = other.ipv6LocRouterId.iterator(); + countOther6LocRouterId = other.ipv6LocRouterId.size(); + countCommon6LocRouterId = ipv6LocRouterId.size(); + + Iterator ipv6remote = other.ipv6RemRouterId.iterator(); + countOther6RemRouterId = other.ipv6RemRouterId.size(); + countCommon6RemRouterId = ipv6RemRouterId.size(); + + Iterator srlg = other.srlgGroup.iterator(); + countOtherSrlg = other.srlgGroup.size(); + countCommonSrlg = srlgGroup.size(); + + if (countOtherCommonBandwidth != countCommonBandwidth + || countOther4LocRouterId != countCommon4LocRouterId + || countOther4RemRouterId != countCommon4RemRouterId + || countOther6LocRouterId != countCommon6LocRouterId + || countOther6RemRouterId != countCommon6RemRouterId + || countOtherSrlg != countCommonSrlg) { + return false; + } else { + while (objListIterator.hasNext() && isCommonBandwidth) { + Bandwidth subTlv = objListIterator.next(); + if (maxUnResBandwidth.contains(subTlv) && other.maxUnResBandwidth.contains(subTlv)) { + isCommonBandwidth = Objects.equals(maxUnResBandwidth.get(maxUnResBandwidth.indexOf(subTlv)), + other.maxUnResBandwidth.get(other.maxUnResBandwidth.indexOf(subTlv))); + } else { + isCommonBandwidth = false; + } + } + while (ipv4local.hasNext() && isCommonIp4Loc) { + Ip4Address subTlv = ipv4local.next(); + if (ipv4LocRouterId.contains(subTlv) && other.ipv4LocRouterId.contains(subTlv)) { + isCommonIp4Loc = Objects.equals(ipv4LocRouterId.get(ipv4LocRouterId.indexOf(subTlv)), + other.ipv4LocRouterId.get(other.ipv4LocRouterId.indexOf(subTlv))); + } else { + isCommonIp4Loc = false; + } + } + while (ipv4remote.hasNext() && isCommonIp4Rem) { + Ip4Address subTlv = ipv4remote.next(); + if (ipv4RemRouterId.contains(subTlv) && other.ipv4RemRouterId.contains(subTlv)) { + isCommonIp4Rem = Objects.equals(ipv4RemRouterId.get(ipv4RemRouterId.indexOf(subTlv)), + other.ipv4RemRouterId.get(other.ipv4RemRouterId.indexOf(subTlv))); + } else { + isCommonIp4Rem = false; + } + } + while (ipv6remote.hasNext() && isCommonIp6Rem) { + Ip6Address subTlv = ipv6remote.next(); + if (ipv6RemRouterId.contains(subTlv) && other.ipv6RemRouterId.contains(subTlv)) { + isCommonIp6Rem = Objects.equals(ipv6RemRouterId.get(ipv6RemRouterId.indexOf(subTlv)), + other.ipv6RemRouterId.get(other.ipv6RemRouterId.indexOf(subTlv))); + } else { + isCommonIp6Rem = false; + } + } + while (ipv6local.hasNext() && isCommonIp6Loc) { + Ip6Address subTlv = ipv6local.next(); + if (ipv6LocRouterId.contains(subTlv) && other.ipv6LocRouterId.contains(subTlv)) { + isCommonIp6Loc = Objects.equals(ipv6LocRouterId.get(ipv6LocRouterId.indexOf(subTlv)), + other.ipv6LocRouterId.get(other.ipv6LocRouterId.indexOf(subTlv))); + } else { + isCommonIp6Loc = false; + } + } + while (srlg.hasNext() && isCommonIp6Loc) { + Srlg subTlv = srlg.next(); + if (srlgGroup.contains(subTlv) && other.srlgGroup.contains(subTlv)) { + isCommonSrlg = Objects.equals(srlgGroup.get(srlgGroup.indexOf(subTlv)), + other.srlgGroup.get(other.srlgGroup.indexOf(subTlv))); + } else { + isCommonSrlg = false; + } + } + return isCommonBandwidth && isCommonIp4Loc && isCommonIp4Rem && isCommonIp6Rem && isCommonIp6Loc + && isCommonSrlg + && Objects.equals(igpMetric, other.igpMetric) + && Objects.equals(teMetric, other.teMetric) + && Objects.equals(maximumLink, other.maximumLink) + && Objects.equals(protectType, other.protectType) + && Objects.equals(color, other.color) + && Objects.equals(signalType, other.signalType); + } + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("igpMetric", igpMetric) + .add("teMetric", teMetric) + .add("maximumLink", maximumLink) + .add("maxReserved", maxReserved) + .add("maxUnResBandwidth", maxUnResBandwidth) + .add("ipv4LocRouterId", ipv4LocRouterId) + .add("ipv4RemRouterId", ipv4RemRouterId) + .add("ipv6LocRouterId", ipv6LocRouterId) + .add("ipv6RemRouterId", ipv6RemRouterId) + .add("protectType", protectType) + .add("color", color) + .add("srlgGroup", srlgGroup) + .add("signalType", signalType) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Metric.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Metric.java new file mode 100644 index 00000000..0af95b01 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Metric.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Traffic engineering metrics. + */ +public class Metric { + private final Integer metric; + + /** + * Constructor to initialize its metric. + * + * @param metric can be TE metric or IGP metric or Prefix metric + */ + public Metric(Integer metric) { + this.metric = metric; + } + + /** + * Obtains traffic engineering metric. + * + * @return traffic engineering metric + */ + public Integer metric() { + return metric; + } + + @Override + public int hashCode() { + return Objects.hash(metric); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof Metric) { + Metric other = (Metric) obj; + return Objects.equals(metric, other.metric); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("metric", metric) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/OspfPseudonode.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/OspfPseudonode.java new file mode 100644 index 00000000..86d96acb --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/OspfPseudonode.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.packet.Ip4Address; + +/** + * Represents Pseudonode information of OSFP device. + */ +public class OspfPseudonode implements RouteIdentifier { + private final RouterId designatedRouter; + private final Ip4Address drInterface; + private final ProtocolType type; + + /** + * Constructor to initialize the values. + * + * @param designatedRouter Router Id of designated router + * @param drInterface IP address of Designated Router interface + * @param type Protocol ID + */ + public OspfPseudonode(RouterId designatedRouter, Ip4Address drInterface, ProtocolType type) { + this.designatedRouter = designatedRouter; + this.drInterface = drInterface; + this.type = type; + } + + /** + * Obtains designated Router Id. + * + * @return designated Router Id + */ + public RouterId designatedRouter() { + return designatedRouter; + } + + /** + * Obtains IP address of Designated Router interface. + * + * @return IP address of Designated Router interface + */ + public Ip4Address drInterface() { + return drInterface; + } + + @Override + public ProtocolType type() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(designatedRouter, drInterface, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof OspfPseudonode) { + OspfPseudonode other = (OspfPseudonode) obj; + return Objects.equals(designatedRouter, other.designatedRouter) + && Objects.equals(drInterface, other.drInterface) + && Objects.equals(type, other.type); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("designatedRouter", designatedRouter) + .add("drInterface", drInterface) + .add("type", type) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Position.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Position.java new file mode 100644 index 00000000..f81f9fd3 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Position.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Position of device in the network. + */ +public class Position { + private final Boolean asbr; + private final Boolean abr; + + /** + * Constructor to set position of device. + * + * @param asbr autonomous system boundary router + * @param abr area boundary router + */ + public Position(Boolean asbr, Boolean abr) { + this.asbr = asbr; + this.abr = abr; + } + + /** + * obtain whether the device is autonomous system boundary router or not. + * + * @return autonomous system boundary router or not + */ + Boolean asbr() { + return asbr; + } + + /** + * obtain whether the device is area boundary router or not. + * + * @return area boundary router or not + */ + Boolean abr() { + return abr; + } + + @Override + public int hashCode() { + return Objects.hash(abr, asbr); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof Position) { + Position other = (Position) obj; + return Objects.equals(abr, other.abr) && Objects.equals(asbr, other.asbr); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("abrBit", abr) + .add("asbrBit", asbr) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixIdentifier.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixIdentifier.java new file mode 100644 index 00000000..b41b5d71 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixIdentifier.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * This class provides Prefix Identifier details. + */ +public class PrefixIdentifier { + private final TopologyId topologyId; + private final RouteType routeType; + private final IpReachability ipReach; + + /** + * Constructor to initialize its parameters. + * + * @param topologyId topology ID of prefix + * @param routeType OSPF Route type of the prefix + * @param ipReach IP address prefix reachability information + */ + public PrefixIdentifier(TopologyId topologyId, RouteType routeType, IpReachability ipReach) { + this.topologyId = topologyId; + this.routeType = routeType; + this.ipReach = ipReach; + } + + /** + * Provides topology ID of prefix. + * + * @return topology id + */ + public TopologyId topologyId() { + return this.topologyId; + } + + /** + * Provides IP address prefix reachability information. + * + * @return IP address prefix + */ + public IpReachability ipReach() { + return this.ipReach; + } + + /** + * Provides OSPF Route type of the prefix. + * + * @return Route type + */ + public RouteType routeType() { + return this.routeType; + } + + @Override + public int hashCode() { + return Objects.hash(topologyId, routeType, ipReach); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof PrefixIdentifier) { + PrefixIdentifier other = (PrefixIdentifier) obj; + return Objects.equals(topologyId, other.topologyId) && Objects.equals(routeType, other.routeType) + && Objects.equals(ipReach, other.ipReach); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("routeType", routeType) + .add("ipReach", ipReach) + .add("topologyId", topologyId) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixTed.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixTed.java new file mode 100644 index 00000000..9f1c40ad --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/PrefixTed.java @@ -0,0 +1,138 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.packet.IpAddress; + +/** + * This class provides implementation of prefix traffic engineering data. + */ +public class PrefixTed { + private final IgpFlags igpFlags; + private final RouteTag routeTag; + private final ExtendedRouteTag extendedRouteTag; + private final Metric metric; + private final IpAddress fwdingAddress; + + /** + * Constructor to initialize its parameters. + * + * @param igpFlags igp flags + * @param routeTag ospf route tag + * @param extendedRouteTag isis route tag + * @param metric prefix metric + * @param fwdingAddress forwarding address + */ + /** + * Constructor to initialize its parameters. + * + * @param igpFlags IS-IS and OSPF flags assigned to the prefix + * @param routeTag IGP (ISIS or OSPF) tags of the prefix + * @param extendedRouteTag extended ISIS route tags of the prefix + * @param metric metric of the prefix + * @param fwdingAddress OSPF forwarding address + */ + public PrefixTed(IgpFlags igpFlags, RouteTag routeTag, ExtendedRouteTag extendedRouteTag, + Metric metric, IpAddress fwdingAddress) { + this.igpFlags = igpFlags; + this.routeTag = routeTag; + this.extendedRouteTag = extendedRouteTag; + this.metric = metric; + this.fwdingAddress = fwdingAddress; + } + + /** + * Provides IS-IS and OSPF flags assigned to the prefix. + * + * @return IGP flags + */ + public IgpFlags igpFlags() { + return igpFlags; + } + + /** + * Provides IGP (ISIS or OSPF) tags of the prefix. + * + * @return IGP route tag. + */ + public RouteTag routeTag() { + return routeTag; + } + + /** + * Provides extended ISIS route tags of the prefix. + * + * @return extended IS-IS route tag + */ + public ExtendedRouteTag extendedRouteTag() { + return extendedRouteTag; + } + + /** + * Provides metric of the prefix. + * + * @return prefix metric + */ + public Metric metric() { + return metric; + } + + /** + * Provides OSPF forwarding address. + * + * @return forwarding address + */ + public IpAddress fwdingAddress() { + return fwdingAddress; + } + + + @Override + public int hashCode() { + return Objects.hash(igpFlags, routeTag, extendedRouteTag, metric, fwdingAddress); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof PrefixTed) { + PrefixTed other = (PrefixTed) obj; + return Objects.equals(igpFlags, other.igpFlags) && Objects.equals(extendedRouteTag, other.extendedRouteTag) + && Objects.equals(routeTag, other.routeTag) && Objects.equals(metric, other.metric) + && Objects.equals(fwdingAddress, other.fwdingAddress); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .omitNullValues() + .add("igpFlags", igpFlags) + .add("extendedRouteTag", extendedRouteTag) + .add("routeTag", routeTag) + .add("metric", metric) + .add("fwdingAddress", fwdingAddress) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ProtectionType.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ProtectionType.java new file mode 100644 index 00000000..be7fb5a9 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/ProtectionType.java @@ -0,0 +1,97 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents protection capabilities of the link. + */ +public class ProtectionType { + private final LinkProtectionType protectionType; + + /** + * Enum to provide Link Protection type. + */ + public enum LinkProtectionType { + Extra_Traffic(1), Unprotected(2), Shared(4), Enhanced(0x20), Dedicated_OneIsToOne(8), + Dedicated_OnePlusOne(0x10), Reserved(0x40); + int value; + + /** + * Constructor to assign value. + * + * @param val link protection type + */ + LinkProtectionType(int val) { + value = val; + } + + /** + * Provides Link protection type. + * + * @return protection type + */ + public byte type() { + return (byte) value; + } + } + + /** + * Constructor to initialize protection type. + * + * @param protectionType link protection type + */ + public ProtectionType(LinkProtectionType protectionType) { + this.protectionType = protectionType; + } + + /** + * Provides protection capabilities of the link. + * + * @return link protection type. + */ + public LinkProtectionType protectionType() { + return protectionType; + } + + @Override + public int hashCode() { + return Objects.hash(protectionType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof ProtectionType) { + ProtectionType other = (ProtectionType) obj; + return Objects.equals(protectionType, other.protectionType); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("protectionType", protectionType) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteDistinguisher.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteDistinguisher.java new file mode 100644 index 00000000..b6b83368 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteDistinguisher.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of RouteDistinguisher. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Route Distinguisher of device in the network. + */ +public class RouteDistinguisher { + private final Long routeDistinguisher; + + /** + * Constructor to initialize parameters. + * + * @param routeDistinguisher route distinguisher + */ + public RouteDistinguisher(Long routeDistinguisher) { + this.routeDistinguisher = routeDistinguisher; + } + + /** + * Obtain route distinguisher. + * + * @return route distinguisher + */ + public Long routeDistinguisher() { + return routeDistinguisher; + } + + @Override + public int hashCode() { + return Objects.hash(routeDistinguisher); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RouteDistinguisher) { + RouteDistinguisher other = (RouteDistinguisher) obj; + return Objects.equals(routeDistinguisher, other.routeDistinguisher); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("routeDistinguisher", routeDistinguisher) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteIdentifier.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteIdentifier.java new file mode 100644 index 00000000..73cda7a6 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteIdentifier.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +/** + * Abstraction of Router ID to identify the router with a distinct IP address. + */ +public interface RouteIdentifier { + /** + * Enum to provide Protocol type. + */ + public enum ProtocolType { + ISIS_LevelOne(1), ISIS_LevelTwo(2), OSPFv2(3), Direct(4), Static_Configuration(5), OSPFv3(6); + int value; + + /** + * Sets protocol ID. + * + * @param val protocol ID + */ + ProtocolType(int val) { + value = val; + } + + /** + * Provides Protocol ID. + * + * @return Protocol ID + */ + public byte getType() { + return (byte) value; + } + } + + /** + * Provides Protocol ID to identify which protocol routing instance is used. + * + * @return Protocol type + */ + ProtocolType type(); +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteInstance.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteInstance.java new file mode 100644 index 00000000..fbca820c --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteInstance.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents routing universe where the network element belongs. + */ +public class RouteInstance { + private final long routeInstance; + + /** + * Constructor to initialize routeInstance. + * + * @param routeInstance routing protocol instance + */ + public RouteInstance(long routeInstance) { + this.routeInstance = routeInstance; + } + + /** + * Obtain route instance. + * + * @return route instance + */ + public long routeInstance() { + return routeInstance; + } + + @Override + public int hashCode() { + return Objects.hash(routeInstance); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RouteInstance) { + RouteInstance other = (RouteInstance) obj; + return Objects.equals(routeInstance, other.routeInstance); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("routeInstance", routeInstance) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteTag.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteTag.java new file mode 100644 index 00000000..f77cc5e6 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteTag.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents the igp administrative tags of the prefix. + */ +public class RouteTag { + private final int routeTag; + + /** + * Constructor to initialize its parameter. + * + * @param routeTag IGP route tag + */ + public RouteTag(int routeTag) { + this.routeTag = routeTag; + } + + /** + * Obtains igp administrative tags of the prefix. + * + * @return igp administrative tags of the prefix + */ + public int routeTag() { + return routeTag; + } + + @Override + public int hashCode() { + return Objects.hash(routeTag); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RouteTag) { + RouteTag other = (RouteTag) obj; + return Objects.equals(routeTag, other.routeTag); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("routeTag", routeTag) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteType.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteType.java new file mode 100644 index 00000000..11268f6f --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouteType.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Route type of the prefix in the OSPF domain. + */ +public class RouteType { + private final Type routeType; + + /** + * Enum to provide Route type. + */ + public enum Type { + Intra_Area(1), Inter_Area(2), External_1(3), External_2(4), NSSA_1(5), NSSA_2(6); + int value; + + /** + * Constructor to assign value. + * + * @param val route type + */ + Type(int val) { + value = val; + } + + /** + * Provides route type. + * + * @return route type + */ + public byte type() { + return (byte) value; + } + } + + /** + * Constructor to initialize routeType. + * + * @param routeType Route type + */ + public RouteType(Type routeType) { + this.routeType = routeType; + } + + /** + * Provides Route type of the prefix. + * + * @return Route type + */ + public Type routeType() { + return routeType; + } + + @Override + public int hashCode() { + return Objects.hash(routeType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RouteType) { + RouteType other = (RouteType) obj; + return Objects.equals(routeType, other.routeType); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("routeType", routeType) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouterId.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouterId.java new file mode 100644 index 00000000..85714cb1 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/RouterId.java @@ -0,0 +1,78 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Router ID of the device. + */ +public class RouterId implements RouteIdentifier { + private final int routerId; + private final ProtocolType type; + + /** + * Constructor to initialize its parameters. + * + * @param routerId Router ID of designated router + */ + public RouterId(int routerId, ProtocolType type) { + this.routerId = routerId; + this.type = type; + } + + /** + * Obtains Router Id of the device. + * + * @return Router Id of the device + */ + public int routerId() { + return routerId; + } + + @Override + public ProtocolType type() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(routerId, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RouterId) { + RouterId other = (RouterId) obj; + return Objects.equals(routerId, other.routerId) && Objects.equals(type, other.type); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("routerId", routerId) + .add("type", type) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Signalling.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Signalling.java new file mode 100644 index 00000000..41593977 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Signalling.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents signaling protocols that are enabled. + */ +public class Signalling { + private final Boolean ldp; + private final Boolean rsvpte; + + /** + * Constructor to initialize the values. + * + * @param ldp Label Distribution Protocol whether enabled or not + * @param rsvpte RSVP TE whether enabled or not + */ + public Signalling(Boolean ldp, Boolean rsvpte) { + this.ldp = ldp; + this.rsvpte = rsvpte; + } + + /** + * Obtains whether LDP signalling protocol is enabled or not. + * + * @return LDP signalling protocol is enabled or not + */ + public Boolean ldp() { + return ldp; + } + + /** + * Obtains whether rsvp-te signalling protocol is enabled or not. + * + * @return rsvp-te signalling protocol is enabled or not + */ + public Boolean rsvpte() { + return rsvpte; + } + + @Override + public int hashCode() { + return Objects.hash(ldp, rsvpte); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof Signalling) { + Signalling other = (Signalling) obj; + return Objects.equals(ldp, other.ldp) && Objects.equals(rsvpte, other.rsvpte); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("ldp", ldp) + .add("rsvpte", rsvpte) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Srlg.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Srlg.java new file mode 100644 index 00000000..1f39bad2 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/Srlg.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +/** + * Represents Shared Risk Link Group information. + */ +public class Srlg { + private final int srlgGroup; + + /** + * Constructor to initialize its parameter. + * + * @param srlgGroup list of Shared Risk Link Group value + */ + public Srlg(int srlgGroup) { + this.srlgGroup = srlgGroup; + } + + /** + * Provides Shared Risk link group. + * + * @return Shared Risk link group value + */ + public int srlgGroup() { + return srlgGroup; + } + + @Override + public int hashCode() { + return Objects.hash(srlgGroup); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof Srlg) { + Srlg other = (Srlg) obj; + return Objects.equals(srlgGroup, other.srlgGroup); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("srlgGroup", srlgGroup) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TerminationPoint.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TerminationPoint.java new file mode 100644 index 00000000..9c21cb46 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TerminationPoint.java @@ -0,0 +1,104 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import java.util.Objects; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.ElementId; + +import com.google.common.base.MoreObjects; + +/** + * Abstraction of a network termination point expressed as a pair of the network element identifier and device + * interface. + */ +public class TerminationPoint { + private final ElementId elementId; + private final DeviceInterface deviceInterface; + + /** + * Constructor to initialize its parameters. + * + * @param elementId network element identifier + * @param deviceInterface device interface + */ + public TerminationPoint(ElementId elementId, DeviceInterface deviceInterface) { + this.elementId = elementId; + this.deviceInterface = deviceInterface; + } + + /** + * Returns the network element identifier. + * + * @return element identifier + */ + public ElementId elementId() { + return elementId; + } + + /** + * Returns the identifier of the infrastructure device if the termination + * point belongs to a network element which is indeed an ip + * device. + * + * @return network element identifier as a device identifier + * @throws java.lang.IllegalStateException if termination point is not + * associated with a device + */ + public DeviceId deviceId() { + if (elementId instanceof DeviceId) { + return (DeviceId) elementId; + } + throw new IllegalStateException("Termination point not associated " + + "with an ip device"); + } + + /** + * Returns Device interface details. + * + * @return device interface details + */ + public DeviceInterface deviceInterface() { + return deviceInterface; + } + + @Override + public int hashCode() { + return Objects.hash(elementId, deviceInterface); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof TerminationPoint) { + final TerminationPoint other = (TerminationPoint) obj; + return Objects.equals(this.elementId, other.elementId) + && Objects.equals(this.deviceInterface, other.deviceInterface); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("elementId", elementId) + .add("deviceInterface", deviceInterface) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TopologyId.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TopologyId.java new file mode 100644 index 00000000..9d414e35 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/TopologyId.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api; + +import java.util.Objects; + +import com.google.common.base.MoreObjects; + +/** + * Represents Multi-Topology IDs for a network link, node or prefix. + */ +public class TopologyId { + private final short topologyId; + + /** + * Constructor to initialize its parameter. + * + * @param topologyId topology id for node/link/prefix + */ + public TopologyId(short topologyId) { + this.topologyId = topologyId; + } + + /** + * Obtains the topology ID. + * + * @return topology ID + */ + public short topologyId() { + return topologyId; + } + + @Override + public int hashCode() { + return Objects.hash(topologyId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof TopologyId) { + TopologyId other = (TopologyId) obj; + return Objects.equals(topologyId, other.topologyId); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("topologyId", topologyId) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultInterfaceDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultInterfaceDescription.java new file mode 100644 index 00000000..c7e413d7 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultInterfaceDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import com.google.common.base.MoreObjects; +import org.onlab.packet.Ip6Address; +import org.onlab.packet.Ip4Address; +import org.onosproject.iptopology.api.InterfaceIdentifier; +import org.onosproject.net.AbstractDescription; +import org.onosproject.net.SparseAnnotations; + +/** + * Default implementation of immutable Interface description. + */ +public class DefaultInterfaceDescription extends AbstractDescription + implements InterfaceDescription { + + private final InterfaceIdentifier intfId; + private final Ip4Address ipv4Address; + private final Ip6Address ipv6Address; + + + + /** + * Creates an interface description using the supplied information. + * + * @param intfId interface identifier + * @param ipv4Address ipv4 address of an interface + * @param ipv6Address ipv6 address of an interface + * @param annotations optional key/value annotations map + */ + public DefaultInterfaceDescription(InterfaceIdentifier intfId, Ip4Address ipv4Address, + Ip6Address ipv6Address, SparseAnnotations...annotations) { + super(annotations); + this.intfId = intfId; + this.ipv4Address = ipv4Address; + this.ipv6Address = ipv6Address; + } + + /** + * Default constructor for serialization. + */ + private DefaultInterfaceDescription() { + this.intfId = null; + this.ipv4Address = null; + this.ipv6Address = null; + } + + /** + * Creates an interface description using the supplied information. + * + * @param base InterfaceDescription to get basic information from + * @param annotations optional key/value annotations map + */ + public DefaultInterfaceDescription(InterfaceDescription base, + SparseAnnotations annotations) { + this(base.intfId(), base.ipv4Address(), base.ipv6Address(), annotations); + } + + @Override + public InterfaceIdentifier intfId() { + return intfId; + } + + @Override + public Ip4Address ipv4Address() { + return ipv4Address; + } + + @Override + public Ip6Address ipv6Address() { + return ipv6Address; } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("intfId", intfId) + .add("ipv4Address", ipv4Address) + .add("ipv6Address", ipv6Address) + .add("annotations", annotations()) + .toString(); + } + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultIpDeviceDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultIpDeviceDescription.java new file mode 100644 index 00000000..889e48a7 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultIpDeviceDescription.java @@ -0,0 +1,117 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.iptopology.api.DeviceTed; +import org.onosproject.iptopology.api.IpDeviceIdentifier; +import org.onosproject.net.AbstractDescription; +import org.onosproject.net.SparseAnnotations; + +import java.net.URI; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onosproject.iptopology.api.IpDevice.Type; + +/** + * Default implementation of immutable device description entity. + */ +public class DefaultIpDeviceDescription extends AbstractDescription + implements IpDeviceDescription { + private final URI uri; + private final Type type; + private final IpDeviceIdentifier deviceIdentifier; + private final DeviceTed deviceTed; + + /** + * Creates an ip device description using the supplied information. + * + * @param uri device URI + * @param type device type + * @param deviceIdentifier device manufacturer + * @param deviceTed device Traffic Engineering parameters + * @param annotations optional key/value annotations map + */ + public DefaultIpDeviceDescription(URI uri, Type type, IpDeviceIdentifier deviceIdentifier, + DeviceTed deviceTed, SparseAnnotations... annotations) { + super(annotations); + this.uri = checkNotNull(uri, "Device URI cannot be null"); + this.type = checkNotNull(type, "Device type cannot be null"); + this.deviceIdentifier = deviceIdentifier; + this.deviceTed = deviceTed; + } + + /** + * Creates an ip device description using the supplied information. + * @param base IpDeviceDescription to basic information + * @param annotations Annotations to use. + */ + public DefaultIpDeviceDescription(IpDeviceDescription base, SparseAnnotations... annotations) { + this(base.deviceURI(), base.type(), base.deviceIdentifier(), + base.deviceTed(), annotations); + } + + /** + * Creates an ip device description using the supplied information. + * @param base IpDeviceDescription to basic information (except for type) + * @param type device type + * @param annotations Annotations to use. + */ + public DefaultIpDeviceDescription(IpDeviceDescription base, Type type, SparseAnnotations... annotations) { + this(base.deviceURI(), type, base.deviceIdentifier(), + base.deviceTed(), annotations); + } + + @Override + public URI deviceURI() { + return uri; + } + + @Override + public Type type() { + return type; + } + + @Override + public IpDeviceIdentifier deviceIdentifier() { + return deviceIdentifier; + } + + @Override + public DeviceTed deviceTed() { + return deviceTed; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("uri", uri) + .add("type", type) + .add("devid", deviceIdentifier) + .add("devTed", deviceTed) + .toString(); + } + + /** + * Default constructor for serialization. + */ + private DefaultIpDeviceDescription() { + this.uri = null; + this.type = null; + this.deviceIdentifier = null; + this.deviceTed = null; + } +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultPrefixDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultPrefixDescription.java new file mode 100644 index 00000000..36cc14a6 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/DefaultPrefixDescription.java @@ -0,0 +1,86 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import com.google.common.base.MoreObjects; +import org.onosproject.iptopology.api.PrefixIdentifier; +import org.onosproject.iptopology.api.PrefixTed; +import org.onosproject.net.AbstractDescription; +import org.onosproject.net.SparseAnnotations; + +/** + * Default implementation of immutable Prefix description. + */ +public class DefaultPrefixDescription extends AbstractDescription + implements PrefixDescription { + + private final PrefixIdentifier prefixIdentifier; + private final PrefixTed prefixTed; + + + /** + * Creates prefix description using the supplied information. + * + * @param prefixIdentifier prefix identifier + * @param prefixTed prefix traffic engineering parameters + * @param annotations optional key/value annotations map + */ + public DefaultPrefixDescription(PrefixIdentifier prefixIdentifier, PrefixTed prefixTed, + SparseAnnotations...annotations) { + super(annotations); + this.prefixIdentifier = prefixIdentifier; + this.prefixTed = prefixTed; + } + + /** + * Default constructor for serialization. + */ + private DefaultPrefixDescription() { + this.prefixIdentifier = null; + this.prefixTed = null; + } + + /** + * Creates prefix description using the supplied information. + * + * @param base PrefixDescription to get basic information from + * @param annotations optional key/value annotations map + */ + public DefaultPrefixDescription(PrefixDescription base, + SparseAnnotations annotations) { + this(base.prefixIdentifier(), base.prefixTed(), annotations); + } + + @Override + public PrefixIdentifier prefixIdentifier() { + return prefixIdentifier; + } + + @Override + public PrefixTed prefixTed() { + return prefixTed; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("prefixIdentifier", prefixIdentifier) + .add("prefixTed", prefixTed) + .add("annotations", annotations()) + .toString(); + } + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/InterfaceDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/InterfaceDescription.java new file mode 100644 index 00000000..6e7804d9 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/InterfaceDescription.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onosproject.iptopology.api.InterfaceIdentifier; +import org.onosproject.net.Description; + + +/** + * Information about an interface. + */ +public interface InterfaceDescription extends Description { + + /** + * Returns the IPv4 Address of an interface. + * + * @return ipv4 address + */ + Ip4Address ipv4Address(); + + /** + * Returns the IPv6 Address of an interface. + * + * @return ipv6 address + */ + Ip6Address ipv6Address(); + + + /** + * Returns the interface id of the interface. + * + * @return interface identifier + */ + InterfaceIdentifier intfId(); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceDescription.java new file mode 100644 index 00000000..c0a4391d --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.iptopology.api.DeviceTed; +import org.onosproject.iptopology.api.IpDevice; +import org.onosproject.iptopology.api.IpDeviceIdentifier; +import org.onosproject.net.Description; + + +import java.net.URI; + +/** + * Carrier of immutable information about an ip device. + */ +public interface IpDeviceDescription extends Description { + + /** + * Protocol/provider specific URI that can be used to encode the identity + * information required to communicate with the ip device externally, e.g. + * datapath ID. + * + * @return provider specific URI for the ip device + */ + URI deviceURI(); + + /** + * Returns the type of the ip device. For ex: Psuedo or actual + * + * @return type of the device + */ + IpDevice.Type type(); + + /** + * Returns the device identifier details. + * + * @return identifier of the device + */ + IpDeviceIdentifier deviceIdentifier(); + + /** + * Returns the traffic engineering parameters of the device. + * + * @return traffic engineering parameters of the device + */ + DeviceTed deviceTed(); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceEvent.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceEvent.java new file mode 100644 index 00000000..07f263e4 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceEvent.java @@ -0,0 +1,183 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.joda.time.LocalDateTime; +import org.onosproject.event.AbstractEvent; +import org.onosproject.iptopology.api.DeviceIntf; +import org.onosproject.iptopology.api.DevicePrefix; +import org.onosproject.iptopology.api.IpDevice; + + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Describes ip device event. + */ +public class IpDeviceEvent extends AbstractEvent { + + private final DeviceIntf devInterface; + private final DevicePrefix devicePrefix; + + /** + * Type of device events. + */ + public enum Type { + /** + * Signifies that a new device has been detected. + */ + DEVICE_ADDED, + + /** + * Signifies that some device attributes have changed; excludes + * availability changes. + */ + DEVICE_UPDATED, + + /** + * Signifies that a device has been removed. + */ + DEVICE_REMOVED, + + /** + * Signifies that an interface has been added. + */ + INTERFACE_ADDED, + + /** + * Signifies that an interface has been updated. + */ + INTERFACE_UPDATED, + + /** + * Signifies that an interface has been removed. + */ + INTERFACE_REMOVED, + + /** + * Signifies that a prefix has been added. + */ + PREFIX_ADDED, + + /** + * Signifies that a prefix has been updated. + */ + PREFIX_UPDATED, + + /** + * Signifies that a prefix has been removed. + */ + PREFIX_REMOVED, + + } + + /** + * Creates an event of a given type and for the specified ip device. + * + * @param type device event type + * @param device event device subject + */ + public IpDeviceEvent(Type type, IpDevice device) { + this(type, device, null, null); + } + + /** + * Creates an event of a given type and for the specified device and interface. + * + * @param type device event type + * @param device event device subject + * @param devInterface optional interface subject + */ + public IpDeviceEvent(Type type, IpDevice device, DeviceIntf devInterface) { + this(type, device, devInterface, null); + } + + /** + * Creates an event of a given type and for the specified device and interface. + * + * @param type device event type + * @param device event device subject + * @param devicePrefix optional prefix subject + */ + public IpDeviceEvent(Type type, IpDevice device, DevicePrefix devicePrefix) { + this(type, device, null, devicePrefix); + } + + + /** + * Creates an event of a given type and for the specified device, interface and prefix. + * + * @param type device event type + * @param device event device subject + * @param devInterface optional interface subject + * @param devicePrefix optional prefix subject + */ + public IpDeviceEvent(Type type, IpDevice device, DeviceIntf devInterface, DevicePrefix devicePrefix) { + super(type, device); + this.devInterface = devInterface; + this.devicePrefix = devicePrefix; + } + + + /** + * Creates an event of a given type and for the specified device, interface and time. + * + * @param type device event type + * @param device event device subject + * @param devInterface optional interface subject + * @param devicePrefix optional prefix subject + * @param time occurrence time + */ + + public IpDeviceEvent(Type type, IpDevice device, DeviceIntf devInterface, DevicePrefix devicePrefix, long time) { + super(type, device, time); + this.devInterface = devInterface; + this.devicePrefix = devicePrefix; + } + + + /** + * Returns the interface subject. + * + * @return interface subject or null if the event is not interface specific. + */ + public DeviceIntf deviceInterface() { + return devInterface; + } + + /** + * Returns the prefix subject. + * + * @return prefix subject or null if the event is not prefix specific. + */ + public DevicePrefix prefix() { + return devicePrefix; + } + + @Override + public String toString() { + if (devInterface == null || devicePrefix == null) { + return super.toString(); + } + return toStringHelper(this) + .add("time", new LocalDateTime(time())) + .add("type", type()) + .add("subject", subject()) + .add("interface", devInterface) + .add("prefix", devicePrefix) + .toString(); + } +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceListener.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceListener.java new file mode 100644 index 00000000..cd40c405 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceListener.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of receiving ip device related events. + */ +public interface IpDeviceListener extends EventListener { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProvider.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProvider.java new file mode 100644 index 00000000..67502eb6 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.net.provider.Provider; + +/** + * Abstraction of a ip device information provider. + */ +public interface IpDeviceProvider extends Provider { + // Currently there is none to set some information into the network +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderRegistry.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderRegistry.java new file mode 100644 index 00000000..74b27415 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderRegistry.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.net.provider.ProviderRegistry; + +/** + * Abstraction of a ip device provider registry. + */ +public interface IpDeviceProviderRegistry + extends ProviderRegistry { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderService.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderService.java new file mode 100644 index 00000000..f84b8b74 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceProviderService.java @@ -0,0 +1,78 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderService; + +import java.util.List; + +/** + * Service through which ip device providers can inject ip device information into + * the core. + */ +public interface IpDeviceProviderService extends ProviderService { + + /** + * Signals the core that an ip device is added or updated with IP topology information. + * + * @param deviceId device identifier + * @param deviceDescription information about network ip device + */ + void addOrUpdateIpDevice(DeviceId deviceId, IpDeviceDescription deviceDescription); + + /** + * Signals the core that an ip device is removed. + * + * @param deviceId identity of the ip device to be removed + */ + void removeIpDevice(DeviceId deviceId); + + /** + * Sends information about all interfaces of a device. It is up to the core to + * determine what has changed. + * + * @param deviceId identity of the ip device + * @param interfaceDescriptions list of device interfaces + */ + void updateInterfaces(DeviceId deviceId, List interfaceDescriptions); + + /** + * signals interfaces of a device is deleted. + * + * @param deviceId identity of the ip device + * @param interfaceDescriptions list of device interfaces + */ + void removeInterfaces(DeviceId deviceId, List interfaceDescriptions); + + /** + * Sends information about all ip prefix of a device. It is up to the core to + * determine what has changed. + * + * @param deviceId identity of the ip device + * @param prefixDescriptions list of device ip prefixes + */ + void updatePrefixes(DeviceId deviceId, List prefixDescriptions); + + /** + * signals ip prefix of a device is deleted. + * + * @param deviceId identity of the ip device + * @param prefixDescriptions list of device ip prefixes + */ + void removePrefixes(DeviceId deviceId, List prefixDescriptions); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceService.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceService.java new file mode 100644 index 00000000..4b126eb3 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceService.java @@ -0,0 +1,111 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.event.ListenerService; +import org.onosproject.iptopology.api.DeviceIntf; +import org.onosproject.iptopology.api.DevicePrefix; +import org.onosproject.iptopology.api.InterfaceIdentifier; +import org.onosproject.iptopology.api.IpDevice; +import org.onosproject.net.DeviceId; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; + +import java.util.List; + +/** + * Service for interacting with the inventory of ip devices. + */ +public interface IpDeviceService + extends ListenerService { + + /** + * Returns the number of ip devices known to the system. + * + * @return number of infrastructure devices + */ + int getIpDeviceCount(); + + /** + * Returns a collection of the currently known ip + * devices. + * + * @return collection of devices + */ + Iterable getIpDevices(); + + /** + * Returns a collection of the currently known ip + * devices by device type. + * + * @param type device type + * @return collection of devices + */ + Iterable getIpDevices(IpDevice.Type type); + + + /** + * Returns the ip device with the specified identifier. + * + * @param deviceId device identifier + * @return device or null if one with the given identifier is not known + */ + IpDevice getIpDevice(DeviceId deviceId); + + /** + * Returns the list of interfaces associated with the device. + * + * @param deviceId device identifier + * @return list of device interfaces + */ + List getInterfaces(DeviceId deviceId); + + /** + * Returns the interface with the specified ipv4 address and hosted by the given device. + * + * @param deviceId device identifier + * @param ipv4Address ipv4 address + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, Ip4Address ipv4Address); + + /** + * Returns the interface with the specified ipv6 address and hosted by the given device. + * + * @param deviceId device identifier + * @param ipv6Address ipv6 address + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, Ip6Address ipv6Address); + + /** + * Returns the interface with the specified interface id and hosted by the given device. + * + * @param deviceId device identifier + * @param intfId interface id + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, InterfaceIdentifier intfId); + + /** + * Returns the list of ip prefix associated with the device. + * + * @param deviceId device identifier + * @return list of device prefixes + */ + List getPrefixes(DeviceId deviceId); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStore.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStore.java new file mode 100644 index 00000000..db1dd429 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStore.java @@ -0,0 +1,164 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onosproject.iptopology.api.DevicePrefix; +import org.onosproject.iptopology.api.InterfaceIdentifier; +import org.onosproject.iptopology.api.IpDevice; +import org.onosproject.iptopology.api.DeviceIntf; +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.Store; + +import java.util.List; + +/** + * Manages inventory of ip devices; not intended for direct use. + */ +public interface IpDeviceStore extends Store { + + /** + * Returns the number of ip devices known to the system. + * + * @return number of ip devices + */ + int getIpDeviceCount(); + + /** + * Returns an iterable collection of all ip devices known to the system. + * + * @return ip device collection + */ + Iterable getIpDevices(); + + + /** + * Returns an ip device with the specified identifier. + * + * @param deviceId device identifier + * @return ip device + */ + IpDevice getIpDevice(DeviceId deviceId); + + /** + * Creates a new infrastructure ip device, or updates an existing one using + * the supplied device description. + * + * @param providerId provider identifier + * @param deviceId device identifier + * @param deviceDescription device description + * @return ready to send event describing what occurred; null if no change + */ + IpDeviceEvent createOrUpdateIpDevice(ProviderId providerId, DeviceId deviceId, + IpDeviceDescription deviceDescription); + + /** + * Administratively removes the specified ip device from the store. + * + * @param deviceId device to be removed + * @return null if no such ip device + */ + IpDeviceEvent removeIpDevice(DeviceId deviceId); + + /** + * Updates the interface of the specified ip device using the given + * list of interface descriptions. The list is assumed to be comprehensive. + * + * @param providerId provider identifier + * @param deviceId ip device identifier + * @param interfaceDescriptions list of interface descriptions + * @return ready to send events describing what occurred; empty list if no change + */ + List updateInterfaces(ProviderId providerId, DeviceId deviceId, + List interfaceDescriptions); + + /** + * Administratively removes the specified interface from the store. + * + * @param deviceId device of the interfaces to be removed + * @param interfaceDescriptions list of interface descriptions + * @return ready to send events describing what occurred. + */ + List removeInterfaces(DeviceId deviceId, List interfaceDescriptions); + + /** + * Returns the list of interfaces that belong to the specified device. + * + * @param deviceId device identifier + * @return list of device interfaces + */ + List getInterfaces(DeviceId deviceId); + + /** + * Returns the specified device interface. + * + * @param deviceId device identifier + * @param ipv4Address ipv4 address of the interface + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, Ip4Address ipv4Address); + + /** + * Returns the specified device interface. + * + * @param deviceId device identifier + * @param ipv6Address ipv6 address of the interface + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, Ip6Address ipv6Address); + + /** + * Returns the specified device interface. + * + * @param deviceId device identifier + * @param intfId interface identifier of the interface + * @return device interface + */ + DeviceIntf getInterface(DeviceId deviceId, InterfaceIdentifier intfId); + + /** + * Updates the prefix information of the specified ip device using the given + * list of prefix descriptions. The list is assumed to be comprehensive. + * + * @param providerId provider identifier + * @param deviceId ip device identifier + * @param prefixDescriptions list of prefix descriptions + * @return ready to send events describing what occurred; empty list if no change + */ + List updatePrefixes(ProviderId providerId, DeviceId deviceId, + List prefixDescriptions); + + /** + * Administratively removes the specified prefix from the store. + * + * @param deviceId device of the prefix to be removed + * @param prefixDescriptions list of prefix descriptions + * @return ready to send events describing what occurred. + */ + List removePrefixes(DeviceId deviceId, List prefixDescriptions); + + /** + * Returns the list of prefixes that belong to the specified device. + * + * @param deviceId device identifier + * @return list of device prefixes + */ + List getPrefixes(DeviceId deviceId); + +} + diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStoreDelegate.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStoreDelegate.java new file mode 100644 index 00000000..14efe064 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/IpDeviceStoreDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.store.StoreDelegate; + +/** + * Infrastructure ip topology store delegate abstraction. + */ +public interface IpDeviceStoreDelegate extends StoreDelegate { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/PrefixDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/PrefixDescription.java new file mode 100644 index 00000000..eb1ece33 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/PrefixDescription.java @@ -0,0 +1,41 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.device; + +import org.onosproject.iptopology.api.PrefixIdentifier; +import org.onosproject.iptopology.api.PrefixTed; +import org.onosproject.net.Description; + +/** + * Information about a prefix. + */ +public interface PrefixDescription extends Description { + + /** + * Returns the prefix identifier. + * + * @return prefix identifier + */ + PrefixIdentifier prefixIdentifier(); + + /** + * Returns the prefix Traffic Engineering parameters. + * + * @return prefix Traffic Engineering parameters + */ + PrefixTed prefixTed(); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/package-info.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/package-info.java new file mode 100644 index 00000000..5e4e29b1 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/device/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Ip device model & related services API definitions. + */ +package org.onosproject.iptopology.api.device; diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/DefaultIpLinkDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/DefaultIpLinkDescription.java new file mode 100644 index 00000000..4a3b46d2 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/DefaultIpLinkDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import com.google.common.base.MoreObjects; +import org.onosproject.iptopology.api.IpLinkIdentifier; +import org.onosproject.iptopology.api.LinkTed; +import org.onosproject.iptopology.api.TerminationPoint; +import org.onosproject.net.AbstractDescription; +import org.onosproject.net.SparseAnnotations; + +/** + * Default implementation of immutable ip link description entity. + */ +public class DefaultIpLinkDescription extends AbstractDescription + implements IpLinkDescription { + + private final TerminationPoint src; + private final TerminationPoint dst; + private final IpLinkIdentifier linkIdentifier; + private final LinkTed linkTed; + + /** + * Creates an ip link description using the supplied information. + * + * @param src link source + * @param dst link destination + * @param linkIdentifier link identifier + * @param linkTed link traffic engineering parameters + * @param annotations optional key/value annotations + */ + public DefaultIpLinkDescription(TerminationPoint src, TerminationPoint dst, + IpLinkIdentifier linkIdentifier, LinkTed linkTed, + SparseAnnotations... annotations) { + super(annotations); + this.src = src; + this.dst = dst; + this.linkIdentifier = linkIdentifier; + this.linkTed = linkTed; + } + + /** + * Creates an ip link description using the supplied information. + * + * @param base IpLinkDescription to basic information + * @param annotations optional key/value annotations + */ + public DefaultIpLinkDescription(IpLinkDescription base, SparseAnnotations... annotations) { + this(base.src(), base.dst(), base.linkIdentifier(), + base.linkTed(), annotations); + } + + @Override + public TerminationPoint src() { + return src; + } + + @Override + public TerminationPoint dst() { + return dst; + } + + @Override + public IpLinkIdentifier linkIdentifier() { + return linkIdentifier; + } + + @Override + public LinkTed linkTed() { + return linkTed; } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("src", src()) + .add("dst", dst()) + .add("linkIdentifier", linkIdentifier()) + .add("linkTed", linkTed()) + .toString(); + } + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkDescription.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkDescription.java new file mode 100644 index 00000000..258e7444 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.iptopology.api.IpLinkIdentifier; +import org.onosproject.iptopology.api.LinkTed; +import org.onosproject.iptopology.api.TerminationPoint; +import org.onosproject.net.Description; + +/** + * Describes an ip link. + */ +public interface IpLinkDescription extends Description { + + /** + * Returns the link source. + * + * @return links source + */ + TerminationPoint src(); + + /** + * Returns the link destination. + * + * @return links destination + */ + TerminationPoint dst(); + + /** + * Returns the link identifier. + * + * @return links identifier informations + */ + IpLinkIdentifier linkIdentifier(); + + /** + * Returns the link traffic engineering parameters. + * + * @return links traffic engineering parameters + */ + LinkTed linkTed(); +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkEvent.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkEvent.java new file mode 100644 index 00000000..4050734a --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkEvent.java @@ -0,0 +1,68 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.iptopology.api.IpLink; + +/** + * Describes ip link event. + */ +public class IpLinkEvent extends AbstractEvent { + + /** + * Type of link events. + */ + public enum Type { + /** + * Signifies that a new ip link has been detected. + */ + LINK_ADDED, + + /** + * Signifies that an ip link has been updated or changed state. + */ + LINK_UPDATED, + + /** + * Signifies that an ip link has been removed. + */ + LINK_REMOVED + } + + /** + * Creates an event of a given type and for the specified ip link and the + * current time. + * + * @param type link event type + * @param link event link subject + */ + public IpLinkEvent(Type type, IpLink link) { + super(type, link); + } + + /** + * Creates an event of a given type and for the specified ip link and time. + * + * @param type link event type + * @param link event link subject + * @param time occurrence time + */ + public IpLinkEvent(Type type, IpLink link, long time) { + super(type, link, time); + } + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkListener.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkListener.java new file mode 100644 index 00000000..5acb73aa --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkListener.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of receiving ip link related events. + */ +public interface IpLinkListener extends EventListener { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProvider.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProvider.java new file mode 100644 index 00000000..a58bf610 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.net.provider.Provider; + +/** + * Abstraction of an entity providing information about ip links + * to the core. + */ +public interface IpLinkProvider extends Provider { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderRegistry.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderRegistry.java new file mode 100644 index 00000000..e060ae68 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderRegistry.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.net.provider.ProviderRegistry; + +/** + * Abstraction of an ip link provider registry. + */ +public interface IpLinkProviderRegistry + extends ProviderRegistry { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderService.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderService.java new file mode 100644 index 00000000..c2554425 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkProviderService.java @@ -0,0 +1,57 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + + +import org.onosproject.iptopology.api.TerminationPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderService; + +/** + * Means for injecting ip link information into the core. + */ +public interface IpLinkProviderService extends ProviderService { + + /** + * Signals that an ip link is added or updated with IP topology information. + * + * @param linkDescription ip link information + */ + void addOrUpdateIpLink(IpLinkDescription linkDescription); + + /** + * Signals that an ip link has disappeared. + * + * @param linkDescription ip link information + */ + void removeIpLink(IpLinkDescription linkDescription); + + /** + * Signals that ip links associated with the specified + * termination point have vanished. + * + * @param terminationPoint termination point + */ + void removeIpLink(TerminationPoint terminationPoint); + + /** + * Signals that ip links associated with the specified + * device have vanished. + * + * @param deviceId device identifier + */ + void removeIpLink(DeviceId deviceId); +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkService.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkService.java new file mode 100644 index 00000000..723e907b --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkService.java @@ -0,0 +1,108 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import java.util.Set; + +import org.onosproject.event.ListenerService; +import org.onosproject.iptopology.api.IpLink; +import org.onosproject.iptopology.api.TerminationPoint; +import org.onosproject.net.DeviceId; + +/** + * Service for interacting with the inventory of infrastructure links. + */ +public interface IpLinkService + extends ListenerService { + + /** + * Returns the count of all known ip links. + * + * @return number of ip links + */ + int getIpLinkCount(); + + /** + * Returns a collection of all ip links. + * + * @return all ip links + */ + Iterable getIpLinks(); + + + /** + * Returns set of all ip links leading to and from the + * specified ip device. + * + * @param deviceId device identifier + * @return set of ip device links + */ + Set getIpDeviceLinks(DeviceId deviceId); + + /** + * Returns set of all ip links leading from the specified ip device. + * + * @param deviceId device identifier + * @return set of ip device egress links + */ + Set getIpDeviceEgressLinks(DeviceId deviceId); + + /** + * Returns set of all ip links leading to the specified ip device. + * + * @param deviceId device identifier + * @return set of ip device ingress links + */ + Set getIpDeviceIngressLinks(DeviceId deviceId); + + /** + * Returns set of all ip links leading to and from the + * specified termination point. + * + * @param terminationPoint termination point + * @return set of ip links + */ + Set getIpLinks(TerminationPoint terminationPoint); + + /** + * Returns set of all ip links leading from the specified + * termination point. + * + * @param terminationPoint termination point + * @return set of ip device egress links + */ + Set getEgressIpLinks(TerminationPoint terminationPoint); + + /** + * Returns set of all ip links leading to the specified + * termination point. + * + * @param terminationPoint termination point + * @return set of ip device ingress links + */ + Set getIngressIpLinks(TerminationPoint terminationPoint); + + /** + * Returns the ip links between the specified source + * and destination termination points. + * + * @param src source termination point + * @param dst destination termination point + * @return ip link from source to destination; null if none found + */ + IpLink getIpLink(TerminationPoint src, TerminationPoint dst); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStore.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStore.java new file mode 100644 index 00000000..8f5c60f7 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStore.java @@ -0,0 +1,115 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.iptopology.api.IpLink; +import org.onosproject.iptopology.api.TerminationPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.Store; + +import java.util.Set; + +/** + * Manages inventory of ip links; not intended for direct use. + */ +public interface IpLinkStore extends Store { + + /** + * Returns the number of ip links in the store. + * + * @return number of ip links + */ + int getIpLinkCount(); + + /** + * Returns an iterable collection of all ip links in the inventory. + * + * @return collection of all ip links + */ + Iterable getIpLinks(); + + /** + * Returns all ip links egressing from the specified device. + * + * @param deviceId device identifier + * @return set of ip device links + */ + Set getIpDeviceEgressLinks(DeviceId deviceId); + + /** + * Returns all ip links ingressing from the specified device. + * + * @param deviceId device identifier + * @return set of ip device links + */ + Set getIpDeviceIngressLinks(DeviceId deviceId); + + /** + * Returns the ip link between the two termination points. + * + * @param src source termination point + * @param dst destination termination point + * @return ip link or null if one not found between the termination points + */ + IpLink getIpLink(TerminationPoint src, TerminationPoint dst); + + /** + * Returns all ip links egressing from the specified termination point. + * + * @param src source termination point + * @return set of termination point ip links + */ + Set getEgressIpLinks(TerminationPoint src); + + /** + * Returns all ip links ingressing to the specified termination point. + * + * @param dst destination termination point + * @return set of termination point ip links + */ + Set getIngressIpLinks(TerminationPoint dst); + + /** + * Creates a new ip link, or updates an existing one, based on the given + * information. + * + * @param providerId provider identity + * @param linkDescription ip link description + * @return create or update ip link event, or null if no change resulted + */ + IpLinkEvent createOrUpdateIpLink(ProviderId providerId, + IpLinkDescription linkDescription); + + /** + * Removes ip link, based on the specified information. + * + * @param src ip link source + * @param dst ip link destination + * @return remove or update ip link event, or null if no change resulted + */ + IpLinkEvent removeOrDownIpLink(TerminationPoint src, TerminationPoint dst); + + /** + * Removes ip link based on the specified information. + * + * @param src ip link source + * @param dst ip link destination + * @return remove ip link event, or null if no change resulted + */ + IpLinkEvent removeIpLink(TerminationPoint src, TerminationPoint dst); + +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStoreDelegate.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStoreDelegate.java new file mode 100644 index 00000000..9397a499 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/IpLinkStoreDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.iptopology.api.link; + +import org.onosproject.store.StoreDelegate; + +/** + * Ip link store delegate abstraction. + */ +public interface IpLinkStoreDelegate extends StoreDelegate { +} diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/package-info.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/package-info.java new file mode 100644 index 00000000..581c2367 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/link/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Ip link model & related services API definitions. + */ +package org.onosproject.iptopology.api.link; diff --git a/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/package-info.java b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/package-info.java new file mode 100644 index 00000000..e1133554 --- /dev/null +++ b/framework/src/onos/apps/iptopology-api/src/main/java/org/onosproject/iptopology/api/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Ip Topology API. + */ +package org.onosproject.iptopology.api; diff --git a/framework/src/onos/apps/openstackswitching/app/features.xml b/framework/src/onos/apps/openstackswitching/app/features.xml index acb07b62..a13c2aaf 100644 --- a/framework/src/onos/apps/openstackswitching/app/features.xml +++ b/framework/src/onos/apps/openstackswitching/app/features.xml @@ -15,7 +15,6 @@ ~ limitations under the License. --> - mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features onos-api diff --git a/framework/src/onos/apps/openstackswitching/app/pom.xml b/framework/src/onos/apps/openstackswitching/app/pom.xml index 5460faef..7d26f8f2 100644 --- a/framework/src/onos/apps/openstackswitching/app/pom.xml +++ b/framework/src/onos/apps/openstackswitching/app/pom.xml @@ -31,7 +31,6 @@ SONA Openstack Switching applications - 1.4.0-SNAPSHOT org.onosproject.openstackswitching /onos/openstackswitching 1.0.0 diff --git a/framework/src/onos/apps/pathpainter/pom.xml b/framework/src/onos/apps/pathpainter/pom.xml new file mode 100644 index 00000000..c14294c8 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + + org.onosproject + onos-apps + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-app-pp + bundle + + Path visualization application + + + org.onosproject.pathpainter + + + diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java new file mode 100644 index 00000000..57241705 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pathpainter; + +import org.onosproject.net.Link; +import org.onosproject.net.LinkKey; +import org.onosproject.ui.topo.BiLink; +import org.onosproject.ui.topo.LinkHighlight; +import org.onosproject.ui.topo.LinkHighlight.Flavor; + +import java.util.Set; + +/** + * Bi-directional link capable of different hilights. + */ +public class PathLink extends BiLink { + + private boolean primary = false; + private boolean secondary = false; + + public PathLink(LinkKey key, Link link) { + super(key, link); + } + + public void computeHilight(Set selectedLinks, Set allLinks) { + primary = selectedLinks.contains(this.one()) || + (two() != null && selectedLinks.contains(two())); + secondary = allLinks.contains(this.one()) || + (two() != null && allLinks.contains(two())); + } + + @Override + public LinkHighlight highlight(Enum anEnum) { + Flavor flavor = primary ? Flavor.PRIMARY_HIGHLIGHT : + (secondary ? Flavor.SECONDARY_HIGHLIGHT : Flavor.NO_HIGHLIGHT); + return new LinkHighlight(this.linkId(), flavor); + } +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java new file mode 100644 index 00000000..9f2ea216 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java @@ -0,0 +1,30 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pathpainter; + +import org.onosproject.net.Link; +import org.onosproject.net.LinkKey; +import org.onosproject.ui.topo.BiLinkMap; + +/** + * Our concrete link map. + */ +public class PathLinkMap extends BiLinkMap { + @Override + protected PathLink create(LinkKey linkKey, Link link) { + return new PathLink(linkKey, link); + } +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java new file mode 100644 index 00000000..07ce3fe8 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java @@ -0,0 +1,86 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pathpainter; + +import com.google.common.collect.ImmutableList; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onosproject.ui.UiExtension; +import org.onosproject.ui.UiExtensionService; +import org.onosproject.ui.UiMessageHandlerFactory; +import org.onosproject.ui.UiTopoOverlayFactory; +import org.onosproject.ui.UiView; +import org.onosproject.ui.UiViewHidden; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Skeletal ONOS UI Topology-Overlay application component. + */ +@Component(immediate = true) +public class PathPainter { + + private static final ClassLoader CL = PathPainter.class.getClassLoader(); + private static final String VIEW_ID = "ppTopov"; + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected UiExtensionService uiExtensionService; + + // List of application views + private final List uiViews = ImmutableList.of( + new UiViewHidden(VIEW_ID) + ); + + // Factory for UI message handlers + private final UiMessageHandlerFactory messageHandlerFactory = + () -> ImmutableList.of( + new PathPainterTopovMessageHandler() + ); + + // Factory for UI topology overlays + private final UiTopoOverlayFactory topoOverlayFactory = + () -> ImmutableList.of( + new PathPainterTopovOverlay() + ); + + // Application UI extension + protected UiExtension extension = + new UiExtension.Builder(CL, uiViews) + .resourcePath(VIEW_ID) + .messageHandlerFactory(messageHandlerFactory) + .topoOverlayFactory(topoOverlayFactory) + .build(); + + @Activate + protected void activate() { + uiExtensionService.register(extension); + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + uiExtensionService.unregister(extension); + log.info("Stopped"); + } + +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java new file mode 100644 index 00000000..cf395e49 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java @@ -0,0 +1,388 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pathpainter; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.onlab.osgi.ServiceDirectory; +import org.onosproject.net.DeviceId; +import org.onosproject.net.DisjointPath; +import org.onosproject.net.ElementId; +import org.onosproject.net.HostId; +import org.onosproject.net.Link; +import org.onosproject.net.Path; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.topology.GeoDistanceLinkWeight; +import org.onosproject.net.topology.LinkWeight; +import org.onosproject.net.topology.PathService; +import org.onosproject.net.topology.TopologyEvent; +import org.onosproject.net.topology.TopologyListener; +import org.onosproject.net.topology.TopologyService; +import org.onosproject.ui.RequestHandler; +import org.onosproject.ui.UiConnection; +import org.onosproject.ui.UiMessageHandler; +import org.onosproject.ui.topo.DeviceHighlight; +import org.onosproject.ui.topo.Highlights; +import org.onosproject.ui.topo.HostHighlight; +import org.onosproject.ui.topo.NodeBadge; +import org.onosproject.ui.topo.TopoJson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * Skeletal ONOS UI Topology-Overlay message handler. + */ +public class PathPainterTopovMessageHandler extends UiMessageHandler { + + private static final String PAINTER_CLEAR = "ppTopovClear"; + private static final String PAINTER_SET_SRC = "ppTopovSetSrc"; + private static final String PAINTER_SET_DST = "ppTopovSetDst"; + private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst"; + private static final String PAINTER_SET_MODE = "ppTopovSetMode"; + + private static final String PAINTER_NEXT_PATH = "ppTopovNextPath"; + private static final String PAINTER_PREV_PATH = "ppTopovPrevPath"; + + private static final String ID = "id"; + private static final String MODE = "mode"; + private static final String TYPE = "type"; + private static final String SWITCH = "switch"; + private static final String ENDSTATION = "endstation"; + public static final String DST = "Dst"; + public static final String SRC = "Src"; + private static LinkWeight linkData; + + private final TopologyListener topologyListener = new InternalTopologyListener(); + + private Set allPathLinks; + private boolean listenersRemoved; + + private enum Mode { + SHORTEST, DISJOINT, GEODATA, SRLG, INVALID + } + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private PathService pathService; + + private ElementId src, dst; + private String srcType, dstType; + private Mode currentMode = Mode.SHORTEST; + private List paths; + private int pathIndex; + + protected TopologyService topologyService; + + + // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================ + + + @Override + public void init(UiConnection connection, ServiceDirectory directory) { + super.init(connection, directory); + pathService = directory.get(PathService.class); + topologyService = directory.get(TopologyService.class); + linkData = new GeoDistanceLinkWeight(directory.get(DeviceService.class)); + addListeners(); + } + + + @Override + public void destroy() { + removeListeners(); + super.destroy(); + } + + @Override + protected Collection createRequestHandlers() { + return ImmutableSet.of( + new ClearHandler(), + new SetSrcHandler(), + new SetDstHandler(), + new SwapSrcDstHandler(), + new NextPathHandler(), + new PrevPathHandler(), + new SetModeHandler() + ); + } + + // === ------------------------- + // === Handler classes + + private final class ClearHandler extends RequestHandler { + + public ClearHandler() { + super(PAINTER_CLEAR); + } + + @Override + public void process(long sid, ObjectNode payload) { + src = null; + dst = null; + sendMessage(TopoJson.highlightsMessage(new Highlights())); + } + } + + private final class SetSrcHandler extends RequestHandler { + + public SetSrcHandler() { + super(PAINTER_SET_SRC); + } + + @Override + public void process(long sid, ObjectNode payload) { + String id = string(payload, ID); + src = elementId(id); + srcType = string(payload, TYPE); + if (src.equals(dst)) { + dst = null; + } + sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(), + srcType, + src.toString(), + SRC))); + findAndSendPaths(currentMode); + } + } + + private final class SetDstHandler extends RequestHandler { + public SetDstHandler() { + super(PAINTER_SET_DST); + } + + @Override + public void process(long sid, ObjectNode payload) { + String id = string(payload, ID); + dst = elementId(id); + dstType = string(payload, TYPE); + if (src.equals(dst)) { + src = null; + } + + sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(), + dstType, + dst.toString(), + DST))); + findAndSendPaths(currentMode); + } + } + + private final class SwapSrcDstHandler extends RequestHandler { + public SwapSrcDstHandler() { + super(PAINTER_SWAP_SRC_DST); + } + + @Override + public void process(long sid, ObjectNode payload) { + ElementId temp = src; + src = dst; + dst = temp; + String s = srcType; + srcType = dstType; + dstType = s; + findAndSendPaths(currentMode); + } + } + + + + private final class NextPathHandler extends RequestHandler { + public NextPathHandler() { + super(PAINTER_NEXT_PATH); + } + + @Override + public void process(long sid, ObjectNode payload) { + pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1); + hilightAndSendPaths(); + } + } + + private final class PrevPathHandler extends RequestHandler { + public PrevPathHandler() { + super(PAINTER_PREV_PATH); + } + + @Override + public void process(long sid, ObjectNode payload) { + pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1); + hilightAndSendPaths(); + } + } + + private final class SetModeHandler extends RequestHandler { + public SetModeHandler() { + super(PAINTER_SET_MODE); + } + + @Override + public void process(long sid, ObjectNode payload) { + String mode = string(payload, MODE); + switch (mode) { + case "shortest": + currentMode = Mode.SHORTEST; + break; + case "disjoint": + currentMode = Mode.DISJOINT; + break; + case "geodata": + currentMode = Mode.GEODATA; + break; + case "srlg": + currentMode = Mode.SRLG; + break; + default: + currentMode = Mode.INVALID; + break; + } + //TODO: add support for SRLG + findAndSendPaths(currentMode); + } + } + + // === ------------ + + private ElementId elementId(String id) { + try { + return DeviceId.deviceId(id); + } catch (IllegalArgumentException e) { + return HostId.hostId(id); + } + } + + private void findAndSendPaths(Mode mode) { + log.info("src={}; dst={}; mode={}", src, dst, currentMode); + if (src != null && dst != null) { + pathIndex = 0; + ImmutableSet.Builder builder = ImmutableSet.builder(); + if (mode.equals(Mode.SHORTEST)) { + paths = ImmutableList.copyOf(pathService.getPaths(src, dst)); + allPathLinks = buildPaths(builder).build(); + } else if (mode.equals(Mode.DISJOINT)) { + paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst)); + allPathLinks = buildDisjointPaths(builder).build(); + } else if (mode.equals(Mode.GEODATA)) { + paths = ImmutableList.copyOf(pathService.getPaths(src, dst, linkData)); + allPathLinks = buildPaths(builder).build(); + } else { + log.info("Unsupported MODE"); + } + } else { + paths = ImmutableList.of(); + allPathLinks = ImmutableSet.of(); + } + hilightAndSendPaths(); + + } + + private ImmutableSet.Builder buildPaths(ImmutableSet.Builder pathBuilder) { + paths.forEach(path -> path.links().forEach(pathBuilder::add)); + return pathBuilder; + } + + private ImmutableSet.Builder buildDisjointPaths(ImmutableSet.Builder pathBuilder) { + paths.forEach(path -> { + DisjointPath dp = (DisjointPath) path; + pathBuilder.addAll(dp.primary().links()); + pathBuilder.addAll(dp.backup().links()); + }); + return pathBuilder; + } + + private void hilightAndSendPaths() { + PathLinkMap linkMap = new PathLinkMap(); + allPathLinks.forEach(linkMap::add); + + Set selectedPathLinks; + + // Prepare two working sets; one containing selected path links and + // the other containing all paths links. + if (currentMode.equals(Mode.DISJOINT)) { + DisjointPath dp = (DisjointPath) paths.get(pathIndex); + selectedPathLinks = paths.isEmpty() ? + ImmutableSet.of() : Sets.newHashSet(dp.primary().links()); + selectedPathLinks.addAll(dp.backup().links()); + } else { + selectedPathLinks = paths.isEmpty() ? + ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links()); + } + Highlights highlights = new Highlights(); + for (PathLink plink : linkMap.biLinks()) { + plink.computeHilight(selectedPathLinks, allPathLinks); + highlights.add(plink.highlight(null)); + } + if (src != null) { + highlights = addBadge(highlights, srcType, src.toString(), SRC); + } + if (dst != null) { + highlights = addBadge(highlights, dstType, dst.toString(), DST); + } + sendMessage(TopoJson.highlightsMessage(highlights)); + } + + private Highlights addBadge(Highlights highlights, String type, String elemId, String src) { + if (SWITCH.equals(type)) { + highlights = addDeviceBadge(highlights, elemId, src); + } else if (ENDSTATION.equals(type)) { + highlights = addHostBadge(highlights, elemId, src); + } + return highlights; + } + + private Highlights addDeviceBadge(Highlights h, String elemId, String type) { + DeviceHighlight dh = new DeviceHighlight(elemId); + dh.setBadge(createBadge(type)); + h.add(dh); + return h; + } + + private Highlights addHostBadge(Highlights h, String elemId, String type) { + HostHighlight hh = new HostHighlight(elemId); + hh.setBadge(createBadge(type)); + h.add(hh); + return h; + } + + private NodeBadge createBadge(String type) { + return NodeBadge.text(type); + } + + private synchronized void addListeners() { + listenersRemoved = false; + topologyService.addListener(topologyListener); + } + private synchronized void removeListeners() { + if (!listenersRemoved) { + listenersRemoved = true; + topologyService.removeListener(topologyListener); + } + } + + // Link event listener. + private class InternalTopologyListener implements TopologyListener { + @Override + public void event(TopologyEvent event) { + findAndSendPaths(currentMode); + } + } + +} \ No newline at end of file diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java new file mode 100644 index 00000000..78f5f905 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java @@ -0,0 +1,56 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pathpainter; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.HostId; +import org.onosproject.ui.UiTopoOverlay; +import org.onosproject.ui.topo.ButtonId; +import org.onosproject.ui.topo.PropertyPanel; + +/** + * Our topology overlay. + */ +public class PathPainterTopovOverlay extends UiTopoOverlay { + + // NOTE: this must match the ID defined in ppTopovOverlay.js + private static final String OVERLAY_ID = "pp-overlay"; + + private static final ButtonId SRC_BUTTON = new ButtonId("src"); + private static final ButtonId DST_BUTTON = new ButtonId("dst"); + + public PathPainterTopovOverlay() { + super(OVERLAY_ID); + } + + @Override + public void deactivate() { + super.deactivate(); + log.debug("PathPainterOverlay Deactivated"); + } + + @Override + public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) { + pp.addButton(SRC_BUTTON).addButton(DST_BUTTON); + } + + @Override + public void modifyHostDetails(PropertyPanel pp, HostId hostId) { + pp.addButton(SRC_BUTTON).addButton(DST_BUTTON); + } + + +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java new file mode 100644 index 00000000..e625933b --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Path visualization GUI topology view overlay. + */ +package org.onosproject.pathpainter; \ No newline at end of file diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css new file mode 100644 index 00000000..cbf460f9 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.css @@ -0,0 +1,2 @@ +/* css for sample app topology overlay */ + diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html new file mode 100644 index 00000000..9141975f --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.html @@ -0,0 +1,4 @@ + +
+

This is a hidden view .. just a placeholder to house the javascript

+
diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js new file mode 100644 index 00000000..baaaef98 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopov.js @@ -0,0 +1,119 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + Sample Demo module. This contains the "business logic" for the topology + overlay that we are implementing. + */ + +(function () { + 'use strict'; + + // injected refs + var $log, fs, flash, wss; + + // constants + var srcMessage = 'ppTopovSetSrc', + dstMessage = 'ppTopovSetDst', + swapMessage = 'ppTopovSwapSrcDst', + modeMessage = 'ppTopovSetMode', + nextPathMessage = 'ppTopovNextPath', + clearMessage = 'ppTopovClear', + prevPathMessage = 'ppTopovPrevPath'; + + // internal state + var currentMode = null; + + + // === --------------------------- + // === Helper functions + + + // === --------------------------- + // === Main API functions + + function clear() { + wss.sendEvent(clearMessage); + flash.flash('Source node: ' + node.id); + } + + function setSrc(node) { + wss.sendEvent(srcMessage, { + id: node.id, + type: node.type + }); + flash.flash('Source node: ' + node.id); + } + + function setDst(node) { + wss.sendEvent(dstMessage, { + id: node.id, + type: node.type + }); + flash.flash('Destination node: ' + node.id); + } + + function swapSrcDst() { + wss.sendEvent(swapMessage) + flash.flash('Source and destination swap'); + } + + function nextPath() { + wss.sendEvent(nextPathMessage); + } + + function prevPath() { + wss.sendEvent(prevPathMessage); + } + + + function setMode(mode) { + if (currentMode === mode) { + $log.debug('(in mode', mode, 'already)'); + flash.flash('Already in ' + mode + ' mode'); + } else { + currentMode = mode; + wss.sendEvent(modeMessage, { + mode: mode + }); + flash.flash('Path mode: ' + mode); + } + } + + // === --------------------------- + // === Module Factory Definition + + angular.module('ovPpTopov', []) + .factory('PathPainterTopovService', + ['$log', 'FnService', 'FlashService', 'WebSocketService', + + function (_$log_, _fs_, _flash_, _wss_) { + $log = _$log_; + fs = _fs_; + flash = _flash_; + wss = _wss_; + + return { + setSrc: setSrc, + setDst: setDst, + setMode: setMode, + nextPath: nextPath, + prevPath: prevPath, + swapSrcDst: swapSrcDst, + clear: clear + }; + }]); +}()); diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js new file mode 100644 index 00000000..f98ed2b7 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js @@ -0,0 +1,260 @@ +// path painter topology overlay - client side +// +// This is the glue that binds our business logic (in ppTopovDemo.js) +// to the overlay framework. + +(function () { + 'use strict'; + + // injected refs + var $log, tov, pps; + + // internal state should be kept in the service module (not here) + var selection; + + // our overlay definition + var overlay = { + // NOTE: this must match the ID defined in AppUiTopovOverlay + overlayId: 'pp-overlay', + glyphId: 'topo', + tooltip: 'Path Painter Topo Overlay', + + activate: function () { + $log.debug("Path painter topology overlay ACTIVATED"); + }, + deactivate: function () { + pps.clear(); + $log.debug("Path painter topology overlay DEACTIVATED"); + }, + // These glyphs get installed using the overlayId as a prefix. + // e.g. 'src' is installed as 'pp-overlay-src' + // They can be referenced (from this overlay) as '*src' + // That is, the '*' prefix stands in for 'pp-overlay-' + glyphs: { + src: { + vb: '0 0 110 110', + d: 'M28.7,59.3 M14.9,53 M8.7,39 M32.4,92.5H25l-0.2-3.6' + + 'c-0.5-9-5.4-23.9-12.9-33.5c-5.2-6.6-7-12.8-7-16.3c0-13.3,10.7-24,23.8-24c13.1,0,23.8,10.8,23.8,24c0,3.5-1.8,9.7-7,16.3' + + 'C38,65,33.1,80,32.6,88.9L32.4,92.5z M27.9,89.5h1.7l0-0.7c0.5-9.4,5.7-25.2,13.5-35.2c4.7-6,6.4-11.4,6.4-14.5' + + 'c0-11.6-9.3-21-20.8-21C17.3,18,7.9,27.5,7.9,39c0,3,1.7,8.4,6.4,14.5c7.9,10.1,13.1,25.8,13.5,35.2L27.9,89.5z M28.7,83.2' + + 'M28.6,29.8c-4.7,0-8.5,3.8-8.5,8.5c0,4.7,3.8,8.5,8.5,8.5s8.5-3.8,8.5-8.5C37.1,33.6,33.3,29.8,28.6,29.8z M89.6,47 M89.6,29.5' + + 'c-0.1,3.1-0.1,12.8,0,17c0.1,4.2,14.1-5.5,13.9-8.5C103.4,35.1,89.6,25.6,89.6,29.5z M51,38.1L89.5,38 M89.5,39.5l0-3L51,36.5l0,3' + + 'L89.5,39.5z' + }, + dst: { + vb: '0 0 110 110', + d: 'M80.3,59.8 M85.8,92.5h-7.2L78.4,89c-0.4-8.8-5.2-23.6-12.3-33' + + 'c-4.9-6.5-6.7-12.5-6.7-16c0-13,10.2-23.7,22.7-23.7c12.5,0,22.7,10.6,22.7,23.7c0,3.5-1.8,9.5-6.7,16C91.2,65.4,86.4,80.1,86,89' + + 'L85.8,92.5z M81.4,89.5H83l0-0.7c0.5-9.3,5.4-24.8,12.9-34.7c4.5-5.9,6.1-11.2,6.1-14.2c0-11.4-8.9-20.7-19.8-20.7' + + 'c-10.9,0-19.8,9.3-19.8,20.7c0,3,1.6,8.3,6.1,14.2C76,64,80.9,79.5,81.4,88.8L81.4,89.5z M82.1,30.8c-4.5,0-8.1,3.7-8.1,8.4' + + 's3.6,8.4,8.1,8.4c4.5,0,8.1-3.7,8.1-8.4S86.6,30.8,82.1,30.8z M47.2,47.5 M45.2,30.8c-0.1,3.1-0.1,12.6,0,16.7' + + 'c0.1,4.1,13.4-5.4,13.3-8.4C58.4,36.2,45.2,26.9,45.2,30.8z M45.2,39.1L6.7,39.2 M45.2,40.6l0-3L6.7,37.7l0,3L45.2,40.6z' + }, + jp: { + vb: '0 0 110 110', + d: 'M84.3,89.3L58.9,64.2l-1.4,1.4L83,90.7L84.3,89.3z M27,7.6H7.4v19.2H27V7.6z' + + 'M59.3,47.1H39.8v19.2h19.5V47.1z M102.1,79.5H82.6v19.2h19.5V79.5z M41.7,47.6L19,25.1l-1.2,1.2l22.7,22.5L41.7,47.6z' + }, + djp: { + vb: '0 0 110 110', + d: 'M25.8,84l-9.2-57 M27.3,83.8l-9.2-57l-3,0.5l9.2,57L27.3,83.8z M83.2,37.7L26.8,15.5 M83.7,36.1L26.6,14' + + 'l-1,3.2l57,22.1L83.7,36.1z M34.1,95l61.4-40.6 M96.4,55.7l-1.9-2.5L33.2,93.8l1.9,2.5L96.4,55.7z M26.6,27.6H6.7V7.7h19.9V27.6z' + + 'M102.1,36H82.2v19.9h19.9V36z M35.3,83.5H15.3v19.9h19.9V83.5z' + }, + geo: { + vb: '0 0 110 110', + d: 'M55.7,94.6c-0.1-0.3,0-1-0.1-1.4'+ + 'c-0.7-0.5-1.3-2.2-2.1-2.6c-0.5-0.3-1.4-0.2-2-0.5c-0.3-0.1-0.6-0.3-0.9-0.4c-0.4-0.1-0.8-0.1-1.1-0.3c-1.3-0.7-1.9-3-3.5-2.9'+ + 'c-0.7,0-1.3,0.7-1.9,0.7c-0.6,0-1.6-0.5-2.4-0.9c-0.8-0.4-1.6-0.6-2.3-1c-0.5-0.3-0.9-0.9-1.3-1.1C37.8,84,37.2,84,37,83.9'+ + 'c-0.4-0.2-0.8-0.7-1.3-1.1c-0.5-0.4-1-0.9-1-1.4c0-0.6,0.5-1,0.5-1.6c0.2-1.7-1-2.9-1.7-3.9c-0.5-0.7-1.1-1.4-1.7-2.1'+ + 'c0-0.5,0-0.5,0-1c-0.4-0.4-0.7-1.1-1.1-1.7c-0.4-0.6-1.1-1.2-1.2-1.9c-0.1-0.8,0.3-1.5,0-2.3c-0.5-1.3-2-0.7-1.8,1'+ + 'c0.1,0.5,0.6,1.1,0.8,1.6c0.2,0.5,0.1,1.1,0.3,1.6c0.2,0.6,0.7,1,0.8,1.7c0.3,1,0.3,2,0.5,2.7c0.2,0.5,1,1.1,0.6,1.7'+ + 'c-0.6,0.1-0.8-0.5-1.2-0.9c-0.2-0.2-1-0.6-1.1-1.1c-0.1-0.4,0.2-1,0.1-1.5c-0.2-1-2-1-2-2.1c0-0.7,0.8-0.7,0.8-1.4'+ + 'c0-0.7-0.8-1.3-1-1.9c-0.2-0.5-0.2-1.4-0.3-2.2c-0.1-0.7,0-1.5-0.1-2.1c-0.1-0.5-0.8-1.2-1.2-1.4c-0.6-0.3-1-0.2-1.3-0.7'+ + 'c-0.2-0.4-0.4-1.4-0.4-1.9c-0.1-0.9,0-1.8-0.1-2.7c0-0.9-0.1-1.8,0-2.8c0.3-0.7,0.9-1,1.2-1.7c0.2-0.5,0.3-1.1,0.5-1.6'+ + 'c0.5-0.9,1.5-1.8,2.2-2.7c0.7-1,1.4-1.9,1.8-3.1c0.2-0.4,0.6-1.3,0.5-1.8c-0.1-0.7-1.2-1.3-1.1-2.1c0.1-0.5,0.7-0.5,0.9-1'+ + 'c0.1-0.3,0.2-1,0.2-1.3c0-0.7-0.3-1.4-0.2-2.2c0.1-0.6,0.9-0.9,0.5-1.6c-0.4-0.7-1.2,0.4-1.7-0.1c-0.4-0.4,0.1-0.9,0.1-1.7'+ + 'c0-0.3-0.2-0.6-0.1-0.9c0-0.3,0.6-0.9,0.4-1.1c-0.3-0.5-0.7-1.7-1.5-2.2c-0.9-0.5-1.9-0.2-3.2-0.4c-0.8-0.2-1.2-1-1.9-0.9'+ + 'c-0.5,0-0.7,0.6-1.3,0.9c-0.6,0.3-1.4,0.2-2,0.4c-0.6,0.2-0.9,0.6-1.5,0.6c-0.5,0-0.5-0.6-1.1-0.6c-0.2,0-0.7,0.2-1.1,0.2'+ + 'c-1,0.1-2.8,0.2-3.7-0.1c-0.9-0.2-1.5-0.5-2.5-1.1C7.4,28.2,6,27.7,6.1,27c0-0.4,1.3-0.8,1.8-1c0.8-0.3,1.3-0.7,2-0.8'+ + 'c0.2,0,0.6,0.2,0.9,0.1c0.3,0,0.7-0.4,1.1-0.4c0.9-0.1,2.1,0.1,2-0.9c-0.7-0.6-3.4,0.4-3.5-0.9c0-0.8,1-1,1.8-1.2'+ + 'c0.7-0.2,1.8-0.5,2.5-0.4c0.7,0,1.7,1,2.1-0.1c0.2-0.7-0.2-1.3-0.4-1.9c0.5-0.8,1.5-0.7,2.3-0.9c0.9-0.1,1.6-0.3,2.4-0.7'+ + 'c0.7-0.4,1.5-0.6,2.4-0.7c0.9-0.1,1.7-0.5,2.5-0.6c0.6-0.1,1.2,0,1.8-0.1c0.5-0.1,1.1-0.5,1.7-0.4c0.4,0,0.7,0.4,1.1,0.4'+ + 'c0.4,0.1,0.8,0,1.2,0.1c0.3,0.1,0.6,0.3,0.9,0.4c0.5,0.1,1-0.1,1.5,0c0.4,0.1,0.8,0.4,1.2,0.4c1,0.1,2.1-0.1,3.1,0.1'+ + 'c0.4,0.1,0.7,0.3,1.1,0.4c0.4,0.1,0.8,0,1.1,0.1c0.5,0.1,0.9,0.7,1.5,0.7c1,0.1,2.1-0.5,3.1-0.6c0.7-0.1,1.5,0,2.3-0.1'+ + 'c0.7-0.2,1.4-0.5,2-0.5c0.3,0,0.6,0.1,1,0.1c0.3,0,0.7-0.5,1.1-0.4c0.5,0.1,0.4,0.8,0.9,0.9c0.6-0.3,1.1,0,1.7,0'+ + 'c0.6,0,1.1-0.3,1.8-0.2c1.2,0.2,2.8,1.5,3.7,0.8c0.2-0.2,0.2-0.5,0.4-0.9c0.3-0.6,0.8-1.3,0.7-2.2c-1.3,0-2.5,0.7-3.9,0.8'+ + 'c-1.5-1,0.4-1.7,1.5-2.2c0.9-0.4,1.6-1.3,2.7-1.4C62,12.5,63,12.9,64,13c0.6,0.1,1.2,0,1.6,0.1c0.6,0.2,0.9,0.9,1.5,1.1'+ + 'c0.2,0.1,0.6,0.1,0.9,0.1c0.6,0.1,1.1,0.5,1.7,0c0.4,0.1,0.5,0.6,1,0.7c0.4-0.3,0.7-0.9,1.4-1.1c0.3-0.1,0.6,0.1,0.9,0'+ + 'c0.5-0.1,1.2-0.9,1.5-0.1c-0.1,0.5-0.8,0.6-1.2,1c-0.3,0.4-0.9,1.2-0.8,1.6c0.1,0.7,1,0.4,1,1.3c-0.1,0.5-0.7,0.3-1.1,0.5'+ + 'c-0.4,0.2-0.5,0.6-1,0.7c-1.2,0.2-2.1-0.3-3.1-0.3c0,0.5,0.5,0.8,0.8,0.9c0.9,0.5,1.6,0.5,2.9,0.4c0.7,0,1.4,0.2,2-0.2'+ + 'c0.4-0.3,0.3-0.9,0.6-1.2c0.4-0.4,1.2-0.8,1.7-0.7c0.3,0.1,0.7,0.4,0.7,0.7c0,0.7-0.8,0.4-0.8,1.1c0.5,0.4,2-0.4,2-1'+ + 'c0.1-0.4-0.5-0.7-0.4-1.1c0-0.8,0.9-0.7,0.8-1.5c-0.4-0.4-0.9,0.1-1.3,0c-0.6-0.1-1.2-1-1.5-1.5c0.3-0.4,0.9-0.1,1.3-0.1'+ + 'c0.5-0.7,1.3-1,2.5-1.1c0.4,0,1-0.2,1.2,0.2c0.1,0.7-0.9,1.1-0.7,1.9c0.9,0.2,1.1-1.1,1.8-1.6c0.3-0.2,0.8-0.4,1.2-0.6'+ + 'c0.4-0.2,0.8-0.6,1.1-0.6c0.4,0,0.4,0.3,0.8,0.5c0.3,0.1,0.7-0.1,0.8,0.4c-0.7,1.4-3.5,0.6-4.2,2.1c0.2,1-0.4,1.9,0.1,2.6'+ + 'c0.4,0.5,1.1,0.2,1.3,0.6c0.2,0.7-0.8,0.7-0.5,1.4c0.7,0.5,1.5-0.4,2.1-0.8c0.7-0.4,1.5-0.8,1.6-1.7c-0.3-0.7-1.6-0.2-1.8-0.9'+ + 'c-0.1-0.4,0.4-1.3,0.5-1.5c0.7-0.8,3-2,4.6-1.9c0.3,0,0.6,0.3,1,0.3c1.1,0.1,2.4-0.5,3.2,0c0.7-0.5,1.5,0.1,2.5-0.1'+ + 'c0.7,0.5,0.5,1.5,1.7,2c0.3,0.1,0.7,0,1.1,0.1c0.3,0.1,0.6,0.5,1,0.6c0.5,0.2,0.9,0.2,1,0.6c0.1,0.4-0.3,0.6-0.3,1'+ + 'c0.3,0.3,0,0.6,0.2,1c0.3,0.7,1,0.6,1.6,0.9c0.5,0.2,1.5,0.9,1.5,1.4c0,0.4-1,1-1.3,1.1c-0.2,0.1-1.3,0.7-1.7,0.6'+ + 'c-0.6-0.1-0.8-1.5-1.7-1.4c-0.4,0-0.7,0.3-0.7,0.8c0,0.9,0.9,1,1,1.8c0,1-0.5,1-1.2,1.6c-0.5-0.2-1-0.6-1.7-0.6'+ + 'c-0.4,0.5,0.7,0.7,0.3,1.4c-1,0.2-1.8-0.3-2.7-0.6c-0.3-0.1-0.7-0.1-1-0.2c-0.4-0.2-0.5-0.9-0.8-1.3c-0.3-0.4-1-1-1.6-1'+ + 'c-0.8,0-1.9,1.1-2.5,0.1c0.4-1.6,2.5-0.4,3.8-1c0.5-0.2,0.7-0.8,1.1-1.1c0.8-0.5,2.2-0.6,2-1.7c-0.1-0.5-0.7-0.5-1.1-0.8'+ + 'c-0.5-0.4-0.9-1.7-1.6-1.7c-0.4,0-0.6,0.3-1,0.4c-0.8,0.1-1.7-0.4-2.5,0c-0.3,0.2-0.1,0.6-0.4,1c-0.2,0.3-0.7,0.4-1,0.8'+ + 'c-0.2,0.4-0.2,0.9-0.5,1.2c-0.5,0.5-1.6,0.6-2.3,0.9c-0.3,0.1-0.7,0.5-1,0.5c-0.5,0-0.7-0.8-1.3-0.5c0,0.8,0.7,1.1,1.2,1.4'+ + 'c0.5,0.4,1.1,0.8,1.3,1.4c-0.5,1.2-1.3-0.1-2.2-0.1c-0.9,0-2.2,1.9-3,0.4c0.2-0.8,1-1,1.2-1.8c-0.9,0.2-1.7,1-2.7,1.3'+ + 'c-0.4,0.1-0.9,0.1-1.3,0.2c-0.8,0.3-1.3,0.9-2.1,1.2c-0.3,0.1-0.7,0.1-1,0.2c-0.8,0.3-1.7,0.8-2.5,1.3c-0.8,0.5-1.7,1-2.2,1.5'+ + 'c-0.3,0.3-1,1.2-1,1.5c0,0.4,0.7,0.6,0.8,1c0,0.3-0.4,0.8-0.1,1.2c0.3,0.3,0.8,0.1,1.3,0.1c1,0.1,1.6,1,2.4,1.5'+ + 'c0.6,0.4,1.4,0.8,2,0.9c0.9,0.1,1.8-0.3,2,0.5c0.1,0.8-0.8,1-0.9,1.5c0.5,0.7-0.3,1-0.3,1.6c0,0.5,0.5,1.2,1,1.3'+ + 'c0.6,0.1,1.6-0.7,1.8-1.4c0.3-0.9,0.2-2,0.8-2.7c3,0.1,5.5-1.5,5.3-4.9c0-0.3-0.2-0.8-0.1-1.2c0.1-0.6,0.9-1,0.8-1.7'+ + 'c0.8-0.3,0.8-1.8,1.7-2c0.7-0.2,1.5,0.6,2.5,0.5c0.3,0,0.7-0.3,1-0.3c0.6,0.1,1,1,1.5,1.4c0.4,0.4,0.9,0.2,1,0.7'+ + 'c-0.1,0.8-0.6,0.8-0.6,1.6c0,0.7,0.7,1.2,1,1.2c0.5,0.1,1.1-0.2,1.6-0.4c0.8-0.5,1.6-1.8,2.3-1.7c0.6,0.1,1,2.1,1.1,2.9'+ + 'c0.1,0.8-0.1,1.4-0.1,2.1c0.1,1.2,1.4,1.1,2.1,1.7c0.2,0.2,0.3,0.7,0.4,0.9c0.3,0.5,0.7,0.5,0.8,1c0.1,1.2-1,1.3-0.9,2.7'+ + 'c-0.2,0.5-0.8,0.5-0.8,1.2c0.1,1.1,1.5,0.3,1.9,1.1c0.2,0.5,0,0.8-0.2,1.5c0.5,0.7,0.5,1.7-0.4,1.7c-0.5,0-0.7-0.6-1.2-0.8'+ + 'c-0.3-0.1-0.7-0.1-1.1-0.1c-0.3-0.1-0.7-0.2-1-0.2c-0.8-0.1-1.6,0.2-2.1-0.4c0.8-1.1,1.8-2.3,2.7-3.2c0.3-0.3,0.9-0.5,0.8-1.1'+ + 'c-0.5-0.5-1.2,0-1.7,0.4c-0.5,0.3-1.2,0.8-1.8,0.9c-1.1,0.2-2.4-0.3-3.3,0.3c-0.1,0.5,1,0.3,0.8,1.1C92.8,43,92.4,43,92,42.7'+ + 'c-0.3-0.3-0.1-0.8-0.3-0.9c-0.3-0.3-1.5-0.4-2.1-0.3c-0.7,0.1-1.3,0.6-1.3,1.2c0.8,0.4,2.1-0.4,2.4,0.6c-0.4,0.9-1.5,1.4-1.3,2.6'+ + 'c0.1,0.5,0.5,1.1,0.9,1.1c0.3,0.1,0.5-0.3,0.9-0.3c0.4,0,0.3,0.5,0.7,0.4c0.6-0.3,1-1.3,1.7-1.2c0.8,1.2-0.8,1.7-1.7,2.1'+ + 'c-1,0.4-2.3,0.6-3.1,1c-0.4,0.2-1.9,1.9-2.2,0.6c-0.2-0.9,0.8-0.7,1-1.4c-1-0.2-1.9,0.5-2.8,0.9c-1.3,0.5-3.4,0.9-3.8,2.5'+ + 'c-0.1,0.3,0.1,0.9-0.1,1.1c-0.2,0.2-1.1,0.2-1.5,0.4c-0.6,0.2-1.2,0.7-1.5,0.9C77.7,54,77.2,54,77,54.1c-0.5,0.2-0.7,1-1.3,1.5'+ + 'c-0.2,0.2-0.8,0.4-1,0.6c-0.3,0.4-0.4,1.3-1,1.4c-0.4,0-0.7-0.3-1-0.1c0,0.9,0.3,2.2-0.1,3.1c-0.8,0.7-1.6,1.2-2.5,1.8'+ + 'c-0.5,0.3-1,0.4-1.7,0.8c-0.5,0.3-0.9,0.9-1.4,1.2c-1.2,0.8-2.7,1.8-2.7,3.8c0,0.4,0.2,0.9,0.3,1.4c0,0.3,0,0.6,0,0.9'+ + 'c0.1,0.7,0.6,1.7,0,2.2c-0.9-0.4-1.9-0.5-2.5-1.2c-0.2-0.7,0.3-1.3,0.3-1.9c-0.1-0.5-0.7-1.4-1.1-1.5c-0.4-0.1-0.7,0.4-1.1,0.4'+ + 'c-0.5,0-0.9-0.8-1.5-0.9c-0.9-0.1-1.6,0.2-2.5,0.1c-1,0.6-1.2,1.6-2.4,1.5c-0.4,0-0.8-0.4-1.3-0.5c-0.5-0.1-1.3-0.3-1.8-0.3'+ + 'c-1.1,0.1-1.9,1-2.8,1.5c-0.8,0.5-2,1.1-2.2,2.1c-0.1,0.5,0,1.3-0.2,1.8c-0.1,0.3-0.4,0.6-0.5,0.9c-0.7,1.5-1.3,3.4-0.8,5.5'+ + 'c0.1,0.3,0.8,2.1,1.1,2.4c0.3,0.4,1.3,1,1.8,1c0.5,0,1-0.3,1.5-0.4c0.5-0.1,1.2-0.1,1.7-0.3c1.4-0.5,1.1-2.6,2.5-3.3'+ + 'c0.6-0.3,1.3-0.4,2.4-0.4c0.3,0.3,0.5,0.9,0.4,1.4c0,0.4-0.3,0.7-0.5,1.2c-0.1,0.5-0.2,1-0.3,1.4c-0.2,0.5-0.6,0.8-0.8,1.3'+ + 'c-0.1,0.3,0,0.7-0.1,0.9c-0.1,0.5-0.7,0.8-0.4,1.3c1.4,0.6,3-0.2,4.2,0.1c0.5,0.1,1.5,0.8,1.5,1.7c0,0.7-0.4,1.1-0.5,1.8'+ + 'c-0.1,0.9-0.4,2-0.4,2.7c-0.1,1.2,1.5,3.2,2.7,3.2L55.7,94.6z M39.1,54.2L31.7,54v11.2h10.3v-8.7L39.1,54.2z M52.2,35.7l7.5,0.1'+ + 'V24.6H49.5l0,8.9 M39.1,54.2l2.9,2.3l10.3-20.8l-2.7-2.1L39.1,54.2z M47.2,46.4' + + } + }, + + // detail panel button definitions + buttons: { + src: { + gid: '*src', + tt: 'Set source node', + cb: function (data) { + $log.debug('Set src action invoked with data:', data); + pps.setSrc(selection); + } + }, + dst: { + gid: '*dst', + tt: 'Set destination node', + cb: function (data) { + $log.debug('Set dst action invoked with data:', data); + pps.setDst(selection); + } + } + }, + + // Key bindings for traffic overlay buttons + // NOTE: fully qual. button ID is derived from overlay-id and key-name + // FIXME: use into [ and ] instead of 1 and 2 + // FIXME: find better keys for shortest paths & disjoint paths modes + keyBindings: { + 1: { + cb: function () { + pps.setSrc(selection); + }, + tt: 'Set source node', + gid: '*src' + }, + 2: { + cb: function () { + pps.setDst(selection); + }, + tt: 'Set destination node', + gid: '*dst' + }, + 3: { + cb: function () { + pps.swapSrcDst(); + }, + tt: 'Swap source and destination nodes', + gid: 'refresh' + }, + 4: { + cb: function () { + pps.setMode("shortest"); + }, + tt: 'Set shortest paths mode', + gid: '*jp' + }, + 5: { + cb: function () { + pps.setMode("disjoint"); + }, + tt: 'Set disjoint paths mode', + gid: '*djp' + }, + 6: { + cb: function () { + pps.setMode("geodata"); + }, + tt: 'Set geodata path weight mode', + gid: '*geo' + }, + leftArrow: { + cb: function () { + pps.prevPath(); + }, + tt: 'Highlight previous path', + gid: 'prevIntent' + }, + rightArrow: { + cb: function () { + pps.nextPath(); + }, + tt: 'Highlight next path', + gid: 'nextIntent' + }, + + _keyOrder: [ + '1', '2', '3', '4', '5', '6', 'leftArrow', 'rightArrow' + ] + }, + + hooks: { + // hook for handling escape key + // Must return true to consume ESC, false otherwise. + escape: function () { + selectionCallback(); + pps.setSrc(); + pps.setDst(); + }, + + // hooks for when the selection changes... + empty: function () { + selectionCallback(); + }, + single: function (data) { + selectionCallback(data); + } + } + }; + + + function buttonCallback(x) { + $log.debug('Toolbar-button callback', x); + } + + function selectionCallback(d) { + $log.debug('Selection callback', d); + selection = d; + } + + // invoke code to register with the overlay service + angular.module('ovPpTopov') + .run(['$log', 'TopoOverlayService', 'PathPainterTopovService', + + function (_$log_, _tov_, _pps_) { + $log = _$log_; + tov = _tov_; + pps = _pps_; + tov.register(overlay); + }]); + +}()); diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html new file mode 100644 index 00000000..56b32b4a --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/css.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html new file mode 100644 index 00000000..24124bf7 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/resources/ppTopov/js.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/framework/src/onos/apps/pom.xml b/framework/src/onos/apps/pom.xml index 005052fb..1a279c53 100644 --- a/framework/src/onos/apps/pom.xml +++ b/framework/src/onos/apps/pom.xml @@ -31,6 +31,7 @@ aaa acl + faultmanagement fwd mobility proxyarp @@ -47,6 +48,7 @@ cordfabric xos-integration pcep-api + iptopology-api olt cip flowanalyzer @@ -58,6 +60,8 @@ pim mlb openstackswitching + pathpainter + cpman diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java index 2eb5d0f3..09d4a436 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java @@ -30,6 +30,7 @@ import org.onosproject.core.ApplicationId; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentService; import org.onosproject.net.intent.IntentState; +import org.onosproject.net.intent.IntentUtils; import org.onosproject.net.intent.Key; import org.onosproject.routing.IntentSynchronizationService; import org.slf4j.Logger; diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java deleted file mode 100644 index 863de12a..00000000 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.sdnip; - -import org.onosproject.net.intent.Intent; -import org.onosproject.net.intent.MultiPointToSinglePointIntent; -import org.onosproject.net.intent.PointToPointIntent; -import org.onosproject.net.intent.SinglePointToMultiPointIntent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Objects; - -/** - * Utilities for dealing with intents. - */ -public final class IntentUtils { - - private static final Logger log = LoggerFactory.getLogger(IntentUtils.class); - - private IntentUtils() { - - } - - /** - * Checks if two intents represent the same value. - * - *

({@link Intent#equals(Object)} only checks ID equality)

- * - *

Both intents must be of the same type.

- * - * @param one first intent - * @param two second intent - * @return true if the two intents represent the same value, otherwise false - */ - public static boolean equals(Intent one, Intent two) { - if (one.getClass() != two.getClass()) { - return false; - } - - if (!(Objects.equals(one.appId(), two.appId()) && - Objects.equals(one.key(), two.key()))) { - return false; - } - - if (one instanceof SinglePointToMultiPointIntent) { - SinglePointToMultiPointIntent intent1 = (SinglePointToMultiPointIntent) one; - SinglePointToMultiPointIntent intent2 = (SinglePointToMultiPointIntent) two; - - return Objects.equals(intent1.selector(), intent2.selector()) && - Objects.equals(intent1.treatment(), intent2.treatment()) && - Objects.equals(intent1.ingressPoint(), intent2.ingressPoint()) && - Objects.equals(intent1.egressPoints(), intent2.egressPoints()); - } else if (one instanceof MultiPointToSinglePointIntent) { - MultiPointToSinglePointIntent intent1 = (MultiPointToSinglePointIntent) one; - MultiPointToSinglePointIntent intent2 = (MultiPointToSinglePointIntent) two; - - return Objects.equals(intent1.selector(), intent2.selector()) && - Objects.equals(intent1.treatment(), intent2.treatment()) && - Objects.equals(intent1.ingressPoints(), intent2.ingressPoints()) && - Objects.equals(intent1.egressPoint(), intent2.egressPoint()); - } else if (one instanceof PointToPointIntent) { - PointToPointIntent intent1 = (PointToPointIntent) one; - PointToPointIntent intent2 = (PointToPointIntent) two; - - return Objects.equals(intent1.selector(), intent2.selector()) && - Objects.equals(intent1.treatment(), intent2.treatment()) && - Objects.equals(intent1.ingressPoint(), intent2.ingressPoint()) && - Objects.equals(intent1.egressPoint(), intent2.egressPoint()); - } else { - log.error("Unimplemented intent type"); - return false; - } - } -} diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java index fb008aad..edc2df4d 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java @@ -33,6 +33,7 @@ import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.host.InterfaceIpAddress; +import org.onosproject.net.intent.IntentUtils; import org.onosproject.net.intent.Key; import org.onosproject.net.intent.PointToPointIntent; import org.onosproject.routing.IntentSynchronizationService; diff --git a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java index 6dc3ce10..4736aa1d 100644 --- a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java +++ b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java @@ -45,6 +45,7 @@ import org.onosproject.net.intent.IntentService; import org.onosproject.net.intent.IntentState; import org.onosproject.net.intent.Key; import org.onosproject.net.intent.MultiPointToSinglePointIntent; +import org.onosproject.net.intent.IntentUtils; import org.onosproject.routing.RouteEntry; import java.util.Collections; diff --git a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/TestIntentServiceHelper.java b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/TestIntentServiceHelper.java index 7f825e81..4df7f9de 100644 --- a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/TestIntentServiceHelper.java +++ b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/TestIntentServiceHelper.java @@ -17,6 +17,7 @@ package org.onosproject.sdnip; import org.easymock.IArgumentMatcher; import org.onosproject.net.intent.Intent; +import org.onosproject.net.intent.IntentUtils; import static org.easymock.EasyMock.reportMatcher; diff --git a/framework/src/onos/apps/segmentrouting/pom.xml b/framework/src/onos/apps/segmentrouting/pom.xml index 83ae76db..d170a7ab 100644 --- a/framework/src/onos/apps/segmentrouting/pom.xml +++ b/framework/src/onos/apps/segmentrouting/pom.xml @@ -89,6 +89,11 @@ org.osgi org.osgi.core + + org.onosproject + onlab-junit + test + diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java index 2c6412cf..7f4bcb15 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java @@ -107,7 +107,7 @@ public class ArpHandler { vlanId); // ARP request for router. Send ARP reply. - if (isArpReqForRouter(deviceId, arpRequest)) { + if (isArpForRouter(deviceId, arpRequest)) { Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()); sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId); } else { @@ -130,7 +130,7 @@ public class ArpHandler { vlanId); // ARP reply for router. Process all pending IP packets. - if (isArpReqForRouter(deviceId, arpReply)) { + if (isArpForRouter(deviceId, arpReply)) { Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress()); srManager.ipHandler.forwardPackets(deviceId, hostIpAddress); } else { @@ -141,7 +141,8 @@ public class ArpHandler { // ARP reply for unknown host, Flood in the subnet. } else { // Don't flood to non-edge ports - if (vlanId.equals(VlanId.vlanId(srManager.ASSIGNED_VLAN_NO_SUBNET))) { + if (vlanId.equals( + VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) { return; } removeVlanAndFlood(payload, inPort); @@ -150,14 +151,21 @@ public class ArpHandler { } - private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { - Set gatewayIpAddresses = config.getPortIPs(deviceId); - if (gatewayIpAddresses != null) { - Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest - .getTargetProtocolAddress()); - if (gatewayIpAddresses.contains(targetProtocolAddress)) { + private boolean isArpForRouter(DeviceId deviceId, ARP arpMsg) { + Ip4Address targetProtocolAddress = Ip4Address.valueOf( + arpMsg.getTargetProtocolAddress()); + Set gatewayIpAddresses = null; + try { + if (targetProtocolAddress.equals(config.getRouterIp(deviceId))) { return true; } + gatewayIpAddresses = config.getPortIPs(deviceId); + } catch (DeviceConfigNotFoundException e) { + log.warn(e.getMessage() + " Aborting check for router IP in processing arp"); + } + if (gatewayIpAddresses != null && + gatewayIpAddresses.contains(targetProtocolAddress)) { + return true; } return false; } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java index 99225874..e6451653 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java @@ -513,6 +513,7 @@ public class DefaultRoutingHandler { public void populatePortAddressingRules(DeviceId deviceId) { rulePopulator.populateRouterMacVlanFilters(deviceId); rulePopulator.populateRouterIpPunts(deviceId); + rulePopulator.populateArpPunts(deviceId); } /** diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java index eb3b3fd5..d1dc8ddc 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java @@ -88,10 +88,10 @@ public class IcmpHandler { (destinationAddress.equals(routerIpAddress) || gatewayIpAddresses.contains(destinationAddress))) { sendICMPResponse(ethernet, connectPoint); - // TODO: do we need to set the flow rule again ?? // ICMP for any known host } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) { + // TODO: known host packet should not be coming to controller - resend flows? srManager.ipHandler.forwardPackets(deviceId, destinationAddress); // ICMP for an unknown host in the subnet of the router diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java index b1682e77..d6a9dcfc 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java @@ -98,7 +98,7 @@ public class IpHandler { */ public void addToPacketBuffer(IPv4 ipPacket) { - // Better not buffer TPC packets due to out-of-order packet transfer + // Better not buffer TCP packets due to out-of-order packet transfer if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) { return; } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java index a07a15d2..d4aa770c 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java @@ -147,20 +147,34 @@ public class RoutingRulePopulator { TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); - sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH)); sbuilder.matchEthType(Ethernet.TYPE_IPV4); + sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH)); + TrafficSelector selector = sbuilder.build(); tbuilder.deferred() .setEthDst(hostMac) .setEthSrc(deviceMac) .setOutput(outPort); - TrafficTreatment treatment = tbuilder.build(); - TrafficSelector selector = sbuilder.build(); + + // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed. + // for switch pipelines that need it, provide outgoing vlan as metadata + VlanId outvlan = null; + Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outPort); + if (subnet == null) { + outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET); + } else { + outvlan = srManager.getSubnetAssignedVlanId(deviceId, subnet); + } + TrafficSelector meta = DefaultTrafficSelector.builder() + .matchVlanId(outvlan).build(); + int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outPort, + treatment, meta); return DefaultForwardingObjective.builder() + .withSelector(selector) + .nextStep(portNextObjId) .fromApp(srManager.appId).makePermanent() - .withSelector(selector).withTreatment(treatment) .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); } @@ -454,7 +468,7 @@ public class RoutingRulePopulator { if (srManager.mastershipService.isLocalMaster(deviceId)) { TrafficTreatment tt = DefaultTrafficTreatment.builder() .pushVlan().setVlanId(assignedVlan).build(); - fob.setMeta(tt); + fob.withMeta(tt); } fob.permit().fromApp(srManager.appId); srManager.flowObjectiveService. @@ -510,6 +524,39 @@ public class RoutingRulePopulator { } } + /** + * Creates a forwarding objective to punt all IP packets, destined to the + * router's port IP addresses, to the controller. Note that the input + * port should not be matched on, as these packets can come from any input. + * Furthermore, these are applied only by the master instance. + * + * @param deviceId the switch dpid for the router + */ + public void populateArpPunts(DeviceId deviceId) { + if (!srManager.mastershipService.isLocalMaster(deviceId)) { + log.debug("Not installing port-IP punts - not the master for dev:{} ", + deviceId); + return; + } + + ForwardingObjective.Builder puntArp = DefaultForwardingObjective.builder(); + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); + sbuilder.matchEthType(Ethernet.TYPE_ARP); + tbuilder.setOutput(PortNumber.CONTROLLER); + puntArp.withSelector(sbuilder.build()); + puntArp.withTreatment(tbuilder.build()); + puntArp.withFlag(Flag.VERSATILE) + .withPriority(HIGHEST_PRIORITY) + .makePermanent() + .fromApp(srManager.appId); + log.debug("Installing forwarding objective to punt ARPs"); + srManager.flowObjectiveService. + forward(deviceId, + puntArp.add(new SRObjectiveContext(deviceId, + SRObjectiveContext.ObjectiveType.FORWARDING))); + } + /** * Populates a forwarding objective to send packets that miss other high * priority Bridging Table entries to a group that contains all ports of @@ -526,6 +573,12 @@ public class RoutingRulePopulator { int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet); VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet); + if (nextId < 0 || vlanId == null) { + log.error("Cannot install subnet broadcast rule in dev:{} due" + + "to vlanId:{} or nextId:{}", vlanId, nextId); + return; + } + /* Driver should treat objective with MacAddress.NONE as the * subnet broadcast rule */ diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java index f6bf649c..62722f02 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java @@ -57,6 +57,7 @@ import org.onosproject.segmentrouting.config.SegmentRoutingConfig; import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler; import org.onosproject.segmentrouting.grouphandler.NeighborSet; import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey; +import org.onosproject.segmentrouting.grouphandler.PortNextObjectiveStoreKey; import org.onosproject.mastership.MastershipService; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; @@ -97,7 +98,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -@SuppressWarnings("ALL") @Service @Component(immediate = true) public class SegmentRoutingManager implements SegmentRoutingService { @@ -150,21 +150,27 @@ public class SegmentRoutingManager implements SegmentRoutingService { private ScheduledExecutorService executorService = Executors .newScheduledThreadPool(1); + @SuppressWarnings("unused") private static ScheduledFuture eventHandlerFuture = null; + @SuppressWarnings("rawtypes") private ConcurrentLinkedQueue eventQueue = new ConcurrentLinkedQueue(); private Map groupHandlerMap = new ConcurrentHashMap(); // Per device next objective ID store with (device id + neighbor set) as key private EventuallyConsistentMap nsNextObjStore = null; + // Per device next objective ID store with (device id + subnet) as key private EventuallyConsistentMap subnetNextObjStore = null; - private EventuallyConsistentMap tunnelStore = null; - private EventuallyConsistentMap policyStore = null; + // Per device next objective ID store with (device id + port) as key + private EventuallyConsistentMap + portNextObjStore = null; // Per device, per-subnet assigned-vlans store, with (device id + subnet // IPv4 prefix) as key private EventuallyConsistentMap subnetVidStore = null; + private EventuallyConsistentMap tunnelStore = null; + private EventuallyConsistentMap policyStore = null; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected StorageService storageService; @@ -175,6 +181,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { private final InternalConfigListener cfgListener = new InternalConfigListener(this); + @SuppressWarnings({ "unchecked", "rawtypes" }) private final ConfigFactory cfgFactory = new ConfigFactory(SubjectFactories.DEVICE_SUBJECT_FACTORY, SegmentRoutingConfig.class, @@ -185,7 +192,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { } }; - private final HostListener hostListener = new InternalHostListener(); + private final InternalHostListener hostListener = new InternalHostListener(); private Object threadSchedulerLock = new Object(); private static int numOfEventsQueued = 0; @@ -228,7 +235,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { log.debug("Creating EC map nsnextobjectivestore"); EventuallyConsistentMapBuilder nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder(); - nsNextObjStore = nsNextObjMapBuilder .withName("nsnextobjectivestore") .withSerializer(kryoBuilder) @@ -239,16 +245,23 @@ public class SegmentRoutingManager implements SegmentRoutingService { log.debug("Creating EC map subnetnextobjectivestore"); EventuallyConsistentMapBuilder subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder(); - subnetNextObjStore = subnetNextObjMapBuilder .withName("subnetnextobjectivestore") .withSerializer(kryoBuilder) .withTimestampProvider((k, v) -> new WallClockTimestamp()) .build(); + log.debug("Creating EC map subnetnextobjectivestore"); + EventuallyConsistentMapBuilder + portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder(); + portNextObjStore = portNextObjMapBuilder + .withName("portnextobjectivestore") + .withSerializer(kryoBuilder) + .withTimestampProvider((k, v) -> new WallClockTimestamp()) + .build(); + EventuallyConsistentMapBuilder tunnelMapBuilder = storageService.eventuallyConsistentMapBuilder(); - tunnelStore = tunnelMapBuilder .withName("tunnelstore") .withSerializer(kryoBuilder) @@ -257,7 +270,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { EventuallyConsistentMapBuilder policyMapBuilder = storageService.eventuallyConsistentMapBuilder(); - policyStore = policyMapBuilder .withName("policystore") .withSerializer(kryoBuilder) @@ -266,7 +278,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { EventuallyConsistentMapBuilder subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder(); - subnetVidStore = subnetVidStoreMapBuilder .withName("subnetvidstore") .withSerializer(kryoBuilder) @@ -425,8 +436,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { /** * Returns the next objective ID for the given NeighborSet. * If the nextObjective does not exist, a new one is created and - * it's id is returned. - * TODO move the side-effect creation of a Next Objective into a new method + * its id is returned. * * @param deviceId Device ID * @param ns NegighborSet @@ -441,18 +451,19 @@ public class SegmentRoutingManager implements SegmentRoutingService { return groupHandlerMap .get(deviceId).getNextObjectiveId(ns, meta); } else { - log.warn("getNextObjectiveId query in device {} not found", deviceId); + log.warn("getNextObjectiveId query - groupHandler for device {} " + + "not found", deviceId); return -1; } } /** - * Returns the next objective ID for the Subnet given. If the nextObjectiveID does not exist, - * a new one is created and returned. + * Returns the next objective ID for the given subnet prefix. It is expected + * that the next-objective has been pre-created from configuration. * * @param deviceId Device ID * @param prefix Subnet - * @return next objective ID + * @return next objective ID or -1 if it was not found */ public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) { if (groupHandlerMap.get(deviceId) != null) { @@ -460,7 +471,33 @@ public class SegmentRoutingManager implements SegmentRoutingService { return groupHandlerMap .get(deviceId).getSubnetNextObjectiveId(prefix); } else { - log.warn("getSubnetNextObjectiveId query in device {} not found", deviceId); + log.warn("getSubnetNextObjectiveId query - groupHandler for " + + "device {} not found", deviceId); + return -1; + } + } + + /** + * Returns the next objective ID for the given portNumber, given the treatment. + * There could be multiple different treatments to the same outport, which + * would result in different objectives. If the next object + * does not exist, a new one is created and its id is returned. + * + * @param deviceId Device ID + * @param portNum port number on device for which NextObjective is queried + * @param treatment the actions to apply on the packets (should include outport) + * @param meta metadata passed into the creation of a Next Objective if necessary + * @return next objective ID or -1 if it was not found + */ + public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum, + TrafficTreatment treatment, + TrafficSelector meta) { + DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId); + if (ghdlr != null) { + return ghdlr.getPortNextObjectiveId(portNum, treatment, meta); + } else { + log.warn("getPortNextObjectiveId query - groupHandler for device {}" + + " not found", deviceId); return -1; } } @@ -475,7 +512,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { InboundPacket pkt = context.inPacket(); Ethernet ethernet = pkt.parsed(); - + log.trace("Rcvd pktin: {}", ethernet); if (ethernet.getEtherType() == Ethernet.TYPE_ARP) { arpHandler.processPacketIn(pkt); } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) { @@ -517,6 +554,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { } } + @SuppressWarnings("rawtypes") private void scheduleEventHandlerIfNotScheduled(Event event) { synchronized (threadSchedulerLock) { eventQueue.add(event); @@ -539,6 +577,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { public void run() { try { while (true) { + @SuppressWarnings("rawtypes") Event event = null; synchronized (threadSchedulerLock) { if (!eventQueue.isEmpty()) { @@ -647,7 +686,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { linkService, flowObjectiveService, nsNextObjStore, - subnetNextObjStore); + subnetNextObjStore, + portNextObjStore); } catch (DeviceConfigNotFoundException e) { log.warn(e.getMessage() + " Aborting processDeviceAdded."); return; @@ -658,6 +698,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { // port addressing rules to the driver as well irrespective of whether // this instance is the master or not. defaultRoutingHandler.populatePortAddressingRules(device.id()); + hostListener.readInitialHosts(); } if (mastershipService.isLocalMaster(device.id())) { DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); @@ -713,7 +754,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { linkService, flowObjectiveService, nsNextObjStore, - subnetNextObjStore); + subnetNextObjStore, + portNextObjStore); } catch (DeviceConfigNotFoundException e) { log.warn(e.getMessage() + " Aborting configureNetwork."); return; @@ -725,6 +767,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { // port addressing rules to the driver as well, irrespective of whether // this instance is the master or not. defaultRoutingHandler.populatePortAddressingRules(device.id()); + hostListener.readInitialHosts(); } if (mastershipService.isLocalMaster(device.id())) { DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); @@ -751,22 +794,66 @@ public class SegmentRoutingManager implements SegmentRoutingService { } } + // TODO Move bridging table population to a separate class private class InternalHostListener implements HostListener { + private void readInitialHosts() { + hostService.getHosts().forEach(host -> { + MacAddress mac = host.mac(); + VlanId vlanId = host.vlan(); + DeviceId deviceId = host.location().deviceId(); + PortNumber port = host.location().port(); + Set ips = host.ipAddresses(); + log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); + + // Populate bridging table entry + ForwardingObjective.Builder fob = + getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); + flowObjectiveService.forward(deviceId, fob.add( + new BridgingTableObjectiveContext(mac, vlanId) + )); + + // Populate IP table entry + ips.forEach(ip -> { + if (ip.isIp4()) { + routingRulePopulator.populateIpRuleForHost( + deviceId, ip.getIp4Address(), mac, port); + } + }); + }); + } + private ForwardingObjective.Builder getForwardingObjectiveBuilder( - MacAddress mac, VlanId vlanId, PortNumber port) { + DeviceId deviceId, MacAddress mac, VlanId vlanId, + PortNumber outport) { + // match rule TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); sbuilder.matchEthDst(mac); sbuilder.matchVlanId(vlanId); TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); - // TODO Move popVlan from flow action to group action tbuilder.immediate().popVlan(); - tbuilder.immediate().setOutput(port); + tbuilder.immediate().setOutput(outport); + + // for switch pipelines that need it, provide outgoing vlan as metadata + VlanId outvlan = null; + Ip4Prefix subnet = deviceConfiguration.getPortSubnet(deviceId, outport); + if (subnet == null) { + outvlan = VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET); + } else { + outvlan = getSubnetAssignedVlanId(deviceId, subnet); + } + TrafficSelector meta = DefaultTrafficSelector.builder() + .matchVlanId(outvlan).build(); + + // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed. + int portNextObjId = getPortNextObjectiveId(deviceId, outport, + tbuilder.build(), + meta); return DefaultForwardingObjective.builder() .withFlag(ForwardingObjective.Flag.SPECIFIC) .withSelector(sbuilder.build()) - .withTreatment(tbuilder.build()) + .nextStep(portNextObjId) .withPriority(100) .fromApp(appId) .makePermanent(); @@ -778,12 +865,13 @@ public class SegmentRoutingManager implements SegmentRoutingService { DeviceId deviceId = event.subject().location().deviceId(); PortNumber port = event.subject().location().port(); Set ips = event.subject().ipAddresses(); - log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); + log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); - // TODO Move bridging table population to a separate class // Populate bridging table entry + log.debug("Populate L2 table entry for host {} at {}:{}", + mac, deviceId, port); ForwardingObjective.Builder fob = - getForwardingObjectiveBuilder(mac, vlanId, port); + getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); flowObjectiveService.forward(deviceId, fob.add( new BridgingTableObjectiveContext(mac, vlanId) )); @@ -807,7 +895,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { // Revoke bridging table entry ForwardingObjective.Builder fob = - getForwardingObjectiveBuilder(mac, vlanId, port); + getForwardingObjectiveBuilder(deviceId, mac, vlanId, port); flowObjectiveService.forward(deviceId, fob.remove( new BridgingTableObjectiveContext(mac, vlanId) )); @@ -835,7 +923,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { // Revoke previous bridging table entry ForwardingObjective.Builder prevFob = - getForwardingObjectiveBuilder(mac, vlanId, prevPort); + getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort); flowObjectiveService.forward(prevDeviceId, prevFob.remove( new BridgingTableObjectiveContext(mac, vlanId) )); @@ -850,7 +938,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { // Populate new bridging table entry ForwardingObjective.Builder newFob = - getForwardingObjectiveBuilder(mac, vlanId, prevPort); + getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort); flowObjectiveService.forward(newDeviceId, newFob.add( new BridgingTableObjectiveContext(mac, vlanId) )); diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java index b86adada..5a82e712 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java @@ -158,7 +158,7 @@ public class TunnelHandler { private int createGroupsForTunnel(Tunnel tunnel) { - List portNumbers; + Set portNumbers; final int groupError = -1; DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0)); diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java index 0ad00679..dbac596d 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java @@ -16,7 +16,6 @@ package org.onosproject.segmentrouting.config; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip4Prefix; import org.onlab.packet.MacAddress; @@ -26,7 +25,6 @@ import org.onosproject.incubator.net.intf.Interface; import org.onosproject.net.ConnectPoint; import org.onosproject.net.config.NetworkConfigRegistry; import org.onosproject.net.host.InterfaceIpAddress; -import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid; import org.onosproject.net.DeviceId; import org.onosproject.net.PortNumber; import org.slf4j.Logger; @@ -34,6 +32,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -60,7 +59,7 @@ public class DeviceConfiguration implements DeviceProperties { boolean isEdge; HashMap gatewayIps; HashMap subnets; - List adjacencySids; + Map> adjacencySids; public SegmentRouterInfo() { this.gatewayIps = new HashMap<>(); @@ -83,11 +82,11 @@ public class DeviceConfiguration implements DeviceProperties { cfgService.getConfig(subject, SegmentRoutingConfig.class); SegmentRouterInfo info = new SegmentRouterInfo(); info.deviceId = subject; - info.nodeSid = config.getSid(); - info.ip = config.getIp(); - info.mac = config.getMac(); + info.nodeSid = config.nodeSid(); + info.ip = config.routerIp(); + info.mac = config.routerMac(); info.isEdge = config.isEdgeRouter(); - info.adjacencySids = config.getAdjacencySids(); + info.adjacencySids = config.adjacencySids(); this.deviceConfigMap.put(info.deviceId, info); this.allSegmentIds.add(info.nodeSid); @@ -410,19 +409,13 @@ public class DeviceConfiguration implements DeviceProperties { * * @param deviceId device identification of the router * @param sid adjacency Sid - * @return list of port numbers + * @return set of port numbers */ - public List getPortsForAdjacencySid(DeviceId deviceId, int sid) { + public Set getPortsForAdjacencySid(DeviceId deviceId, int sid) { SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); - if (srinfo != null) { - for (AdjacencySid asid : srinfo.adjacencySids) { - if (asid.getAsid() == sid) { - return asid.getPorts(); - } - } - } - - return Lists.newArrayList(); + return srinfo != null ? + ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) : + ImmutableSet.copyOf(new HashSet<>()); } /** @@ -435,20 +428,6 @@ public class DeviceConfiguration implements DeviceProperties { */ public boolean isAdjacencySid(DeviceId deviceId, int sid) { SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); - if (srinfo != null) { - if (srinfo.adjacencySids.isEmpty()) { - return false; - } else { - for (AdjacencySid asid: - srinfo.adjacencySids) { - if (asid.getAsid() == sid) { - return true; - } - } - return false; - } - } - - return false; + return srinfo != null && srinfo.adjacencySids.containsKey(sid); } } \ No newline at end of file diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java index 6dc3f0db..f788925c 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java @@ -16,113 +16,210 @@ package org.onosproject.segmentrouting.config; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableMap; import org.onlab.packet.Ip4Address; import org.onlab.packet.MacAddress; import org.onosproject.net.DeviceId; import org.onosproject.net.config.Config; -import org.onosproject.net.config.basics.BasicElementConfig; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Optional; +import java.util.Set; /** * Configuration object for Segment Routing Application. */ public class SegmentRoutingConfig extends Config { - private static final String NAME = "name"; - private static final String IP = "routerIp"; - private static final String MAC = "routerMac"; - private static final String SID = "nodeSid"; - private static final String EDGE = "isEdgeRouter"; - private static final String ADJSID = "adjacencySids"; - - public Optional getName() { + public static final String NAME = "name"; + public static final String IP = "routerIp"; + public static final String MAC = "routerMac"; + public static final String SID = "nodeSid"; + public static final String EDGE = "isEdgeRouter"; + public static final String ADJSIDS = "adjacencySids"; + public static final String ADJSID = "adjSid"; + public static final String PORTS = "ports"; + + @Override + public boolean isValid() { + return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) && + this.name() != null && + this.routerIp() != null && + this.routerMac() != null && + this.nodeSid() != -1 && + this.isEdgeRouter() != null && + this.adjacencySids() != null; + } + + /** + * Gets the name of the router. + * + * @return Optional name of the router. May be empty if not configured. + */ + public Optional name() { String name = get(NAME, null); return name != null ? Optional.of(name) : Optional.empty(); } - public BasicElementConfig setName(String name) { - return (BasicElementConfig) setOrClear(NAME, name); + /** + * Sets the name of the router. + * + * @param name name of the router. + * @return the config of the router. + */ + public SegmentRoutingConfig setName(String name) { + return (SegmentRoutingConfig) setOrClear(NAME, name); } - public Ip4Address getIp() { + /** + * Gets the IP address of the router. + * + * @return IP address of the router. Or null if not configured. + */ + public Ip4Address routerIp() { String ip = get(IP, null); return ip != null ? Ip4Address.valueOf(ip) : null; } - public BasicElementConfig setIp(String ip) { - return (BasicElementConfig) setOrClear(IP, ip); + /** + * Sets the IP address of the router. + * + * @param ip IP address of the router. + * @return the config of the router. + */ + public SegmentRoutingConfig setRouterIp(String ip) { + return (SegmentRoutingConfig) setOrClear(IP, ip); } - public MacAddress getMac() { + /** + * Gets the MAC address of the router. + * + * @return MAC address of the router. Or null if not configured. + */ + public MacAddress routerMac() { String mac = get(MAC, null); return mac != null ? MacAddress.valueOf(mac) : null; } - public BasicElementConfig setMac(String mac) { - return (BasicElementConfig) setOrClear(MAC, mac); + /** + * Sets the MAC address of the router. + * + * @param mac MAC address of the router. + * @return the config of the router. + */ + public SegmentRoutingConfig setRouterMac(String mac) { + return (SegmentRoutingConfig) setOrClear(MAC, mac); } - public int getSid() { + /** + * Gets the node SID of the router. + * + * @return node SID of the router. Or -1 if not configured. + */ + public int nodeSid() { return get(SID, -1); } - public BasicElementConfig setSid(int sid) { - return (BasicElementConfig) setOrClear(SID, sid); + /** + * Sets the node SID of the router. + * + * @param sid node SID of the router. + * @return the config of the router. + */ + public SegmentRoutingConfig setNodeSid(int sid) { + return (SegmentRoutingConfig) setOrClear(SID, sid); } - public boolean isEdgeRouter() { - return get(EDGE, false); + /** + * Checks if the router is an edge router. + * + * @return true if the router is an edge router. + * false if the router is not an edge router. + * null if the value is not configured. + */ + public Boolean isEdgeRouter() { + String isEdgeRouter = get(EDGE, null); + return isEdgeRouter != null ? + Boolean.valueOf(isEdgeRouter) : + null; } - public BasicElementConfig setEdgeRouter(boolean isEdgeRouter) { - return (BasicElementConfig) setOrClear(EDGE, isEdgeRouter); + /** + * Specifies if the router is an edge router. + * + * @param isEdgeRouter true if the router is an edge router. + * @return the config of the router. + */ + public SegmentRoutingConfig setIsEdgeRouter(boolean isEdgeRouter) { + return (SegmentRoutingConfig) setOrClear(EDGE, isEdgeRouter); } - public List getAdjacencySids() { - ArrayList adjacencySids = new ArrayList<>(); - - if (!object.has(ADJSID)) { - return adjacencySids; + /** + * Gets the adjacency SIDs of the router. + * + * @return adjacency SIDs of the router. Or null if not configured. + */ + public Map> adjacencySids() { + if (!object.has(ADJSIDS)) { + return null; } - ArrayNode adjacencySidNodes = (ArrayNode) object.path(ADJSID); - adjacencySidNodes.forEach(adjacencySidNode -> { - int asid = adjacencySidNode.path(AdjacencySid.ASID).asInt(); - - ArrayList ports = new ArrayList(); - ArrayNode portsNodes = (ArrayNode) adjacencySidNode.path(AdjacencySid.PORTS); - portsNodes.forEach(portNode -> { - ports.add(portNode.asInt()); - }); - - AdjacencySid adjacencySid = new AdjacencySid(asid, ports); - adjacencySids.add(adjacencySid); - }); + Map> adjacencySids = new HashMap<>(); + ArrayNode adjacencySidsNode = (ArrayNode) object.path(ADJSIDS); + for (JsonNode adjacencySidNode : adjacencySidsNode) { + int asid = adjacencySidNode.path(ADJSID).asInt(-1); + if (asid == -1) { + return null; + } + + HashSet ports = new HashSet<>(); + ArrayNode portsNode = (ArrayNode) adjacencySidNode.path(PORTS); + for (JsonNode portNode : portsNode) { + int port = portNode.asInt(-1); + if (port == -1) { + return null; + } + ports.add(port); + } + adjacencySids.put(asid, ports); + } - return adjacencySids; + return ImmutableMap.copyOf(adjacencySids); } - public class AdjacencySid { - private static final String ASID = "adjSid"; - private static final String PORTS = "ports"; - - int asid; - List ports; - - public AdjacencySid(int asid, List ports) { - this.asid = asid; - this.ports = ports; - } + /** + * Sets the adjacency SIDs of the router. + * + * @param adjacencySids adjacency SIDs of the router. + * @return the config of the router. + */ + public SegmentRoutingConfig setAdjacencySids(Map> adjacencySids) { + if (adjacencySids == null) { + object.remove(ADJSIDS); + } else { + ArrayNode adjacencySidsNode = mapper.createArrayNode(); + + adjacencySids.forEach((sid, ports) -> { + ObjectNode adjacencySidNode = mapper.createObjectNode(); + + adjacencySidNode.put(ADJSID, sid); + + ArrayNode portsNode = mapper.createArrayNode(); + ports.forEach(port -> { + portsNode.add(port.toString()); + }); + adjacencySidNode.set(PORTS, portsNode); + + adjacencySidsNode.add(adjacencySidNode); + }); - public int getAsid() { - return asid; + object.set(ADJSIDS, adjacencySidsNode); } - public List getPorts() { - return ports; - } + return this; } } \ No newline at end of file diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java index 6b6d960a..32c53654 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java @@ -56,9 +56,11 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore, EventuallyConsistentMap subnetNextObjStore) { + Integer> subnetNextObjStore, + EventuallyConsistentMap portNextObjStore) { super(deviceId, appId, config, linkService, flowObjService, - nsNextObjStore, subnetNextObjStore); + nsNextObjStore, subnetNextObjStore, portNextObjStore); } @Override diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java index e792bf66..bc394b84 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java @@ -80,6 +80,8 @@ public class DefaultGroupHandler { NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null; protected EventuallyConsistentMap< SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null; + protected EventuallyConsistentMap< + PortNextObjectiveStoreKey, Integer> portNextObjStore = null; protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() .register(URI.class).register(HashSet.class) @@ -93,11 +95,12 @@ public class DefaultGroupHandler { DeviceProperties config, LinkService linkService, FlowObjectiveService flowObjService, - EventuallyConsistentMap< - NeighborSetNextObjectiveStoreKey, + EventuallyConsistentMap nsNextObjStore, EventuallyConsistentMap subnetNextObjStore) { + Integer> subnetNextObjStore, + EventuallyConsistentMap portNextObjStore) { this.deviceId = checkNotNull(deviceId); this.appId = checkNotNull(appId); this.deviceConfig = checkNotNull(config); @@ -114,6 +117,7 @@ public class DefaultGroupHandler { this.flowObjectiveService = flowObjService; this.nsNextObjStore = nsNextObjStore; this.subnetNextObjStore = subnetNextObjStore; + this.portNextObjStore = portNextObjStore; populateNeighborMaps(); } @@ -133,30 +137,34 @@ public class DefaultGroupHandler { * @throws DeviceConfigNotFoundException if the device configuration is not found * @return default group handler type */ - public static DefaultGroupHandler createGroupHandler(DeviceId deviceId, - ApplicationId appId, - DeviceProperties config, - LinkService linkService, - FlowObjectiveService flowObjService, - EventuallyConsistentMap< - NeighborSetNextObjectiveStoreKey, - Integer> nsNextObjStore, - EventuallyConsistentMap subnetNextObjStore) - throws DeviceConfigNotFoundException { + public static DefaultGroupHandler createGroupHandler( + DeviceId deviceId, + ApplicationId appId, + DeviceProperties config, + LinkService linkService, + FlowObjectiveService flowObjService, + EventuallyConsistentMap nsNextObjStore, + EventuallyConsistentMap subnetNextObjStore, + EventuallyConsistentMap portNextObjStore) + throws DeviceConfigNotFoundException { // handle possible exception in the caller if (config.isEdgeDevice(deviceId)) { return new DefaultEdgeGroupHandler(deviceId, appId, config, linkService, flowObjService, nsNextObjStore, - subnetNextObjStore); + subnetNextObjStore, + portNextObjStore); } else { return new DefaultTransitGroupHandler(deviceId, appId, config, linkService, flowObjService, nsNextObjStore, - subnetNextObjStore); + subnetNextObjStore, + portNextObjStore); } } @@ -231,25 +239,21 @@ public class DefaultGroupHandler { Integer nextId = nsNextObjStore. get(new NeighborSetNextObjectiveStoreKey(deviceId, ns)); - if (nextId != null) { + if (nextId != null && isMaster) { NextObjective.Builder nextObjBuilder = DefaultNextObjective .builder().withId(nextId) .withType(NextObjective.Type.HASHED).fromApp(appId); nextObjBuilder.addTreatment(tBuilder.build()); - log.info("**linkUp in device {}: Adding Bucket " - + "with Port {} to next object id {} and amIMaster:{}", + + "with Port {} to next object id {}", deviceId, newLink.src().port(), - nextId, isMaster); - - if (isMaster) { - NextObjective nextObjective = nextObjBuilder. - addToExisting(new SRNextObjectiveContext(deviceId)); - flowObjectiveService.next(deviceId, nextObjective); - } - } else { + nextId); + NextObjective nextObjective = nextObjBuilder. + addToExisting(new SRNextObjectiveContext(deviceId)); + flowObjectiveService.next(deviceId, nextObjective); + } else if (isMaster) { log.warn("linkUp in device {}, but global store has no record " + "for neighbor-set {}", deviceId, ns); } @@ -331,8 +335,8 @@ public class DefaultGroupHandler { } /** - * Returns the next objective associated with the neighborset. - * If there is no next objective for this neighborset, this API + * Returns the next objective of type hashed associated with the neighborset. + * If there is no next objective for this neighborset, this method * would create a next objective and return. Optionally metadata can be * passed in for the creation of the next objective. * @@ -372,9 +376,10 @@ public class DefaultGroupHandler { } /** - * Returns the next objective associated with the subnet. - * If there is no next objective for this subnet, this API - * would create a next objective and return. + * Returns the next objective of type broadcast associated with the subnet, + * or -1 if no such objective exists. Note that this method does NOT create + * the next objective as a side-effect. It is expected that is objective is + * created at startup from network configuration. * * @param prefix subnet information * @return int if found or -1 @@ -386,6 +391,38 @@ public class DefaultGroupHandler { return (nextId != null) ? nextId : -1; } + /** + * Returns the next objective of type simple associated with the port on the + * device, given the treatment. Different treatments to the same port result + * in different next objectives. If no such objective exists, this method + * creates one and returns the id. Optionally metadata can be passed in for + * the creation of the objective. + * + * @param portNum the port number for the simple next objective + * @param treatment the actions to apply on the packets (should include outport) + * @param meta optional metadata passed into the creation of the next objective + * @return int if found or created, -1 if there are errors during the + * creation of the next objective. + */ + public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment, + TrafficSelector meta) { + Integer nextId = portNextObjStore. + get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment)); + if (nextId == null) { + log.trace("getPortNextObjectiveId in device{}: Next objective id " + + "not found for {} and {} creating", deviceId, portNum); + createGroupFromPort(portNum, treatment, meta); + nextId = portNextObjStore.get( + new PortNextObjectiveStoreKey(deviceId, portNum, treatment)); + if (nextId == null) { + log.warn("getPortNextObjectiveId: unable to create next obj" + + "for dev:{} port{}", deviceId, portNum); + return -1; + } + } + return nextId; + } + /** * Checks if the next objective ID (group) for the neighbor set exists or not. * @@ -561,7 +598,7 @@ public class DefaultGroupHandler { } } if (meta != null) { - nextObjBuilder.setMeta(meta); + nextObjBuilder.withMeta(meta); } NextObjective nextObj = nextObjBuilder. add(new SRNextObjectiveContext(deviceId)); @@ -574,7 +611,10 @@ public class DefaultGroupHandler { } } - + /** + * Creates broadcast groups for all ports in the same configured subnet. + * + */ public void createGroupsFromSubnetConfig() { Map> subnetPortMap = this.deviceConfig.getSubnetPortsMap(this.deviceId); @@ -612,6 +652,37 @@ public class DefaultGroupHandler { }); } + + /** + * Create simple next objective for a single port. The treatments can include + * all outgoing actions that need to happen on the packet. + * + * @param portNum the outgoing port on the device + * @param treatment the actions to apply on the packets (should include outport) + * @param meta optional data to pass to the driver + */ + public void createGroupFromPort(PortNumber portNum, TrafficTreatment treatment, + TrafficSelector meta) { + int nextId = flowObjectiveService.allocateNextId(); + PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey( + deviceId, portNum, treatment); + + NextObjective.Builder nextObjBuilder = DefaultNextObjective + .builder().withId(nextId) + .withType(NextObjective.Type.SIMPLE) + .addTreatment(treatment) + .fromApp(appId) + .withMeta(meta); + + NextObjective nextObj = nextObjBuilder.add(); + flowObjectiveService.next(deviceId, nextObj); + log.debug("createGroupFromPort: Submited next objective {} in device {} " + + "for port {}", nextId, deviceId, portNum); + + portNextObjStore.put(key, nextId); + } + + public GroupKey getGroupKey(Object obj) { return new DefaultGroupKey(kryo.build().serialize(obj)); } diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java index 14d77ba6..7a43e73d 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java @@ -50,9 +50,11 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore, EventuallyConsistentMap subnetNextObjStore) { + Integer> subnetNextObjStore, + EventuallyConsistentMap portNextObjStore) { super(deviceId, appId, config, linkService, flowObjService, - nsNextObjStore, subnetNextObjStore); + nsNextObjStore, subnetNextObjStore, portNextObjStore); } @Override diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java index 55142078..ef143dc7 100644 --- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java @@ -68,9 +68,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler { EventuallyConsistentMap nsNextObjStore, EventuallyConsistentMap subnetNextObjStore) { + Integer> subnetNextObjStore, + EventuallyConsistentMap portNextObjStore) { super(deviceId, appId, config, linkService, flowObjService, - nsNextObjStore, subnetNextObjStore); + nsNextObjStore, subnetNextObjStore, portNextObjStore); } public PolicyGroupIdentifier createPolicyGroupChain(String id, diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PortNextObjectiveStoreKey.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PortNextObjectiveStoreKey.java new file mode 100644 index 00000000..5555565c --- /dev/null +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PortNextObjectiveStoreKey.java @@ -0,0 +1,77 @@ +package org.onosproject.segmentrouting.grouphandler; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.flow.TrafficTreatment; + +import java.util.Objects; + +/** + * Class definition of Key for Device/Port to NextObjective store. Since there + * can be multiple next objectives to the same physical port, we differentiate + * between them by including the treatment in the key. + */ +public class PortNextObjectiveStoreKey { + private final DeviceId deviceId; + private final PortNumber portNum; + private final TrafficTreatment treatment; + + public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum, + TrafficTreatment treatment) { + this.deviceId = deviceId; + this.portNum = portNum; + this.treatment = treatment; + } + + /** + * Gets device id in this PortNextObjectiveStoreKey. + * + * @return device id + */ + public DeviceId deviceId() { + return deviceId; + } + + /** + * Gets port information in this PortNextObjectiveStoreKey. + * + * @return port information + */ + public PortNumber portNumber() { + return portNum; + } + + /** + * Gets treatment information in this PortNextObjectiveStoreKey. + * + * @return treatment information + */ + public TrafficTreatment treatment() { + return treatment; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PortNextObjectiveStoreKey)) { + return false; + } + PortNextObjectiveStoreKey that = + (PortNextObjectiveStoreKey) o; + return (Objects.equals(this.deviceId, that.deviceId) && + Objects.equals(this.portNum, that.portNum) && + Objects.equals(this.treatment, that.treatment)); + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, portNum, treatment); + } + + @Override + public String toString() { + return "Device: " + deviceId + " Port: " + portNum + " Treatment: " + treatment; + } +} diff --git a/framework/src/onos/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingConfigTest.java b/framework/src/onos/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingConfigTest.java new file mode 100644 index 00000000..3e5daa5b --- /dev/null +++ b/framework/src/onos/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingConfigTest.java @@ -0,0 +1,157 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.segmentrouting.config; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onosproject.net.DeviceId; +import org.onosproject.net.config.Config; +import org.onosproject.net.config.ConfigApplyDelegate; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; + +/** + * Tests for class {@link SegmentRoutingConfig}. + */ +public class SegmentRoutingConfigTest { + private SegmentRoutingConfig config; + private Map> adjacencySids1; + private Map> adjacencySids2; + + @Before + public void setUp() throws Exception { + String jsonString = "{" + + "\"name\" : \"Leaf-R1\"," + + "\"nodeSid\" : 101," + + "\"routerIp\" : \"10.0.1.254\"," + + "\"routerMac\" : \"00:00:00:00:01:80\"," + + "\"isEdgeRouter\" : true," + + "\"adjacencySids\" : [" + + " { \"adjSid\" : 100, \"ports\" : [2, 3] }," + + " { \"adjSid\" : 200, \"ports\" : [4, 5] }" + + "]}"; + + adjacencySids1 = new HashMap<>(); + Set ports1 = new HashSet<>(); + ports1.add(2); + ports1.add(3); + adjacencySids1.put(100, ports1); + Set ports2 = new HashSet<>(); + ports2.add(4); + ports2.add(5); + adjacencySids1.put(200, ports2); + + adjacencySids2 = new HashMap<>(); + Set ports3 = new HashSet<>(); + ports3.add(6); + adjacencySids2.put(300, ports3); + + DeviceId subject = DeviceId.deviceId("of:0000000000000001"); + String key = "org.onosproject.segmentrouting"; + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = mapper.readTree(jsonString); + ConfigApplyDelegate delegate = new MockDelegate(); + + config = new SegmentRoutingConfig(); + config.init(subject, key, jsonNode, mapper, delegate); + } + + @Test + public void testName() throws Exception { + assertTrue(config.name().isPresent()); + assertThat(config.name().get(), is("Leaf-R1")); + } + + @Test + public void testSetName() throws Exception { + config.setName("Spine-R1"); + assertTrue(config.name().isPresent()); + assertThat(config.name().get(), is("Spine-R1")); + } + + @Test + public void testRouterIp() throws Exception { + assertThat(config.routerIp(), is(IpAddress.valueOf("10.0.1.254"))); + } + + @Test + public void testSetRouterIp() throws Exception { + config.setRouterIp("10.0.2.254"); + assertThat(config.routerIp(), is(IpAddress.valueOf("10.0.2.254"))); + } + + @Test + public void testRouterMac() throws Exception { + assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:01:80"))); + } + + @Test + public void testSetRouterMac() throws Exception { + config.setRouterMac("00:00:00:00:02:80"); + assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:02:80"))); + } + + @Test + public void testNodeSid() throws Exception { + assertThat(config.nodeSid(), is(101)); + } + + @Test + public void testSetNodeSid() throws Exception { + config.setNodeSid(200); + assertThat(config.nodeSid(), is(200)); + } + + @Test + public void testIsEdgeRouter() throws Exception { + assertThat(config.isEdgeRouter(), is(true)); + } + + @Test + public void testSetIsEdgeRouter() throws Exception { + config.setIsEdgeRouter(false); + assertThat(config.isEdgeRouter(), is(false)); + } + + @Test + public void testAdjacencySids() throws Exception { + assertThat(config.adjacencySids(), is(adjacencySids1)); + } + + @Test + public void testSetAdjacencySids() throws Exception { + config.setAdjacencySids(adjacencySids2); + assertThat(config.adjacencySids(), is(adjacencySids2)); + } + + private class MockDelegate implements ConfigApplyDelegate { + @Override + public void onApply(Config config) { + } + } +} \ No newline at end of file diff --git a/framework/src/onos/apps/test/intent-perf/src/main/java/org/onosproject/intentperf/IntentPerfCollector.java b/framework/src/onos/apps/test/intent-perf/src/main/java/org/onosproject/intentperf/IntentPerfCollector.java index 8c160e85..cae5455d 100644 --- a/framework/src/onos/apps/test/intent-perf/src/main/java/org/onosproject/intentperf/IntentPerfCollector.java +++ b/framework/src/onos/apps/test/intent-perf/src/main/java/org/onosproject/intentperf/IntentPerfCollector.java @@ -106,7 +106,7 @@ public class IntentPerfCollector { /** * Clears all previously accumulated data. */ - public void clearSamples() { + public synchronized void clearSamples() { newestTime = 0; overall = new Sample(0, nodes.length); current = new Sample(0, nodes.length); diff --git a/framework/src/onos/apps/vtn/pom.xml b/framework/src/onos/apps/vtn/pom.xml index a42f91a0..e4528517 100644 --- a/framework/src/onos/apps/vtn/pom.xml +++ b/framework/src/onos/apps/vtn/pom.xml @@ -60,6 +60,12 @@ tests test + + org.onosproject + onos-api + test + tests + com.sun.jersey jersey-servlet diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java deleted file mode 100644 index e91e6b69..00000000 --- a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.sfc.forwarder; - -import org.onosproject.core.ApplicationId; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.vtnrsc.PortChain; - -/** - * Abstraction of an entity which provides Service function forwarder. - */ -public interface ServiceFunctionForwarder { - - /** - * Install Service function chain. - * - * @param portChain Port chain - */ - void install(PortChain portChain); - - /** - * Programs forwarding object for Service Function. - * - * @param portChain port chain - * @param appid application id - * @param type forwarding objective operation type - */ - void programServiceFunctionForwarder(PortChain portChain, ApplicationId appid, - Objective.Operation type); -} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java new file mode 100644 index 00000000..0ed42fcf --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarderService.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.forwarder; + +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.NshServicePathId; +import org.onosproject.vtnrsc.PortChain; + +/** + * Abstraction of an entity which provides Service function forwarder. + */ +public interface ServiceFunctionForwarderService { + + /** + * Install Forwarding rule. + * + * @param portChain port-chain + * @param nshSPI nsh spi + */ + void installForwardingRule(PortChain portChain, NshServicePathId nshSPI); + + /** + * Uninstall Forwarding rule. + * + * @param portChain port-chain + * @param nshSPI nsh spi + */ + void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI); + + /** + * Prepare forwarding object for Service Function. + * + * @param portChain port-chain + * @param nshSPI nsh spi + * @param type forwarding objective operation type + */ + void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI, Objective.Operation type); +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java new file mode 100644 index 00000000..2846ee01 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/ServiceFunctionForwarderImpl.java @@ -0,0 +1,293 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.forwarder.impl; + +import static org.slf4j.LoggerFactory.getLogger; +import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; +import java.util.ListIterator; + +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.osgi.DefaultServiceDirectory; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.behaviour.ExtensionSelectorResolver; +import org.onosproject.net.DeviceId; +import org.onosproject.net.NshServicePathId; +import org.onosproject.net.driver.DriverHandler; +import org.onosproject.net.driver.DriverService; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flowobjective.DefaultForwardingObjective; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.flowobjective.ForwardingObjective.Flag; +import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.service.VtnRscService; +import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.virtualport.VirtualPortService; +import org.onosproject.vtnrsc.portpair.PortPairService; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; +import org.onosproject.vtnrsc.portchain.PortChainService; +import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService; + +import org.slf4j.Logger; + +/** + * Provides Service Function Forwarder implementation. + */ +public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService { + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DriverService driverService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected VirtualPortService virtualPortService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected VtnRscService vtnRscService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortPairService portPairService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortPairGroupService portPairGroupService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FlowClassifierService flowClassifierService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortChainService portChainService; + + private final Logger log = getLogger(getClass()); + protected ApplicationId appId; + protected FlowObjectiveService flowObjectiveService; + + private static final String DRIVER_NAME = "onosfw"; + private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null"; + private static final String PORT_CHAIN_ID_NOT_NULL = "Port-Chain-Id cannot be null"; + private static final String APP_ID_NOT_NULL = "Application-Id cannot be null"; + private static final int NULL = 0; + + /** + * Default constructor. + */ + public ServiceFunctionForwarderImpl() { + } + + /** + * Explicit constructor. + */ + public ServiceFunctionForwarderImpl(ApplicationId appId) { + this.appId = checkNotNull(appId, APP_ID_NOT_NULL); + ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class); + } + + @Override + public void installForwardingRule(PortChain portChain, NshServicePathId nshSPI) { + checkNotNull(portChain, PORT_CHAIN_NOT_NULL); + prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.ADD); + } + + @Override + public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI) { + checkNotNull(portChain, PORT_CHAIN_NOT_NULL); + prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.REMOVE); + } + + @Override + public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI, + Objective.Operation type) { + + // Go through the port pair group list + List portPairGrpList = portChain.portPairGroups(); + ListIterator listGrpIterator = portPairGrpList.listIterator(); + + // Get source port pair group + if (!listGrpIterator.hasNext()) { + return; + } + PortPairGroupId portPairGrpId = listGrpIterator.next(); + PortPairGroup currentPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId); + + // Get destination port pair group + if (!listGrpIterator.hasNext()) { + return; + } + portPairGrpId = listGrpIterator.next(); + PortPairGroup nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId); + + // push SFF to OVS + pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSPI, type); + } + + /** + * Push service-function-forwarder to OVS. + * + * @param currentPortPairGroup current port-pair-group + * @param nextPortPairGroup next port-pair-group + * @param listGrpIterator pointer to port-pair-group list + */ + public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup, + ListIterator listGrpIterator, NshServicePathId nshSPI, Objective.Operation type) { + MacAddress srcMacAddress = null; + MacAddress dstMacAddress = null; + DeviceId deviceId = null; + DeviceId currentDeviceId = null; + DeviceId nextDeviceId = null; + PortPairGroupId portPairGrpId = null; + + // Travel from SF to SF. + do { + // Get the required information on port pairs from source port pair + // group + List portPairList = currentPortPairGroup.portPairs(); + ListIterator portPLIterator = portPairList.listIterator(); + if (!portPLIterator.hasNext()) { + break; + } + + PortPairId portPairId = portPLIterator.next(); + PortPair portPair = portPairService.getPortPair(portPairId); + + currentDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress())); + if (deviceId == null) { + deviceId = currentDeviceId; + } + srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress(); + dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress(); + + // pack traffic selector + TrafficSelector.Builder selector = packTrafficSelector(deviceId, srcMacAddress, dstMacAddress, nshSPI); + + // Get the required information on port pairs from destination port + // pair group + portPairList = nextPortPairGroup.portPairs(); + portPLIterator = portPairList.listIterator(); + if (!portPLIterator.hasNext()) { + break; + } + + portPairId = portPLIterator.next(); + portPair = portPairService.getPortPair(portPairId); + + nextDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress())); + + // pack traffic treatment + TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair); + + // Send SFF to OVS + sendServiceFunctionForwarder(selector, treatment, deviceId, type); + + // Replace source port pair group with destination port pair group + // for moving to next SFF processing. + currentPortPairGroup = nextPortPairGroup; + if (!listGrpIterator.hasNext()) { + break; + } + portPairGrpId = listGrpIterator.next(); + nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId); + } while (true); + } + + /** + * Pack Traffic selector. + * + * @param deviceId device id + * @param srcMacAddress source mac-address + * @param dstMacAddress destination mac-address + * @param nshSPI nsh spi + * @return traffic treatment + */ + public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, MacAddress srcMacAddress, + MacAddress dstMacAddress, NshServicePathId nshSPI) { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + selector.matchEthSrc(srcMacAddress); + selector.matchEthDst(dstMacAddress); + + DriverHandler handler = driverService.createHandler(deviceId); + ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class); + ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type()); + + try { + nspSpiSelector.setPropertyValue("nshSpi", nshSPI); + } catch (Exception e) { + log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId); + } + + selector.extension(nspSpiSelector, deviceId); + return selector; + } + + /** + * Pack Traffic treatment. + * + * @param currentDeviceId current device id + * @param nextDeviceId next device id + * @param portPair port-pair + * @return traffic treatment + */ + public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId, + PortPair portPair) { + MacAddress srcMacAddress = null; + MacAddress dstMacAddress = null; + + // Check the treatment whether destination SF is on same OVS or in + // different OVS. + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); + if (currentDeviceId.equals(nextDeviceId)) { + srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress(); + dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress(); + treatment.setEthSrc(srcMacAddress); + treatment.setEthDst(dstMacAddress); + } else { + treatment.setVlanId(VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair + .tenantId()).toString())))); + } + + return treatment; + } + + /** + * Send service function forwarder to OVS. + * + * @param selector traffic selector + * @param treatment traffic treatment + * @param deviceId device id + * @param type operation type + */ + public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment, + DeviceId deviceId, Objective.Operation type) { + ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build()) + .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC); + if (type.equals(Objective.Operation.ADD)) { + log.debug("ADD"); + flowObjectiveService.forward(deviceId, objective.add()); + } else { + log.debug("REMOVE"); + flowObjectiveService.forward(deviceId, objective.remove()); + } + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java new file mode 100644 index 00000000..02221196 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * SFC Service manager for interacting with SFC. + */ +package org.onosproject.sfc.forwarder.impl; diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/NshSpiIdGenerators.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/NshSpiIdGenerators.java new file mode 100644 index 00000000..1dbe8c8f --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/NshSpiIdGenerators.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.manager; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Unique NSH SPI Id generator for NSH header. + */ +public final class NshSpiIdGenerators { + + private static final AtomicInteger NSH_SPI_ID_GEN = new AtomicInteger(); + private static final int MAX_NSH_SPI_ID = 0x7FFFFFFF; + private static int nshSpiId; + + /** + * Default constructor. + */ + private NshSpiIdGenerators() { + } + + /** + * Get the next NSH SPI id. + * + * @return NSH SPI id + */ + public static int create() { + do { + if (nshSpiId >= MAX_NSH_SPI_ID) { + if (NSH_SPI_ID_GEN.get() >= MAX_NSH_SPI_ID) { + NSH_SPI_ID_GEN.set(0); + } + } + nshSpiId = NSH_SPI_ID_GEN.incrementAndGet(); + } while (nshSpiId > MAX_NSH_SPI_ID); + return nshSpiId; + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java index ef5fc529..4af2d47c 100644 --- a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java @@ -15,6 +15,11 @@ */ package org.onosproject.sfc.manager; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.PortChain; + /** * SFC application that applies flows to the device. */ @@ -23,48 +28,64 @@ public interface SfcService { /** * When port-pair is created, check whether Forwarding Rule needs to be * updated in OVS. + * + * @param portPair port-pair */ - public void onPortPairCreated(); + void onPortPairCreated(PortPair portPair); /** * When port-pair is deleted, check whether Forwarding Rule needs to be * updated in OVS. + * + * @param portPair port-pair */ - public void onPortPairDeleted(); + void onPortPairDeleted(PortPair portPair); /** * When port-pair-group is created, check whether Forwarding Rule needs to * be updated in OVS. + * + * @param portPairGroup port-pair-group */ - public void onPortPairGroupCreated(); + void onPortPairGroupCreated(PortPairGroup portPairGroup); /** * When port-pair-group is deleted, check whether Forwarding Rule needs to * be updated in OVS. + * + * @param portPairGroup port-pair-group */ - public void onPortPairGroupDeleted(); + void onPortPairGroupDeleted(PortPairGroup portPairGroup); /** * When flow-classifier is created, check whether Forwarding Rule needs to * be updated in OVS. + * + * @param flowClassifier flow-classifier */ - public void onFlowClassifierCreated(); + void onFlowClassifierCreated(FlowClassifier flowClassifier); /** * When flow-classifier is deleted, check whether Forwarding Rule needs to * be updated in OVS. + * + * @param flowClassifier flow-classifier */ - public void onFlowClassifierDeleted(); + void onFlowClassifierDeleted(FlowClassifier flowClassifier); /** * When port-chain is created, check whether Forwarding Rule needs to be * updated in OVS. + * + * @param portChain port-chain */ - public void onPortChainCreated(); + void onPortChainCreated(PortChain portChain); /** * When port-chain is deleted, check whether Forwarding Rule needs to be * updated in OVS. + * + * @param portChain port-chain */ - public void onPortChainDeleted(); + void onPortChainDeleted(PortChain portChain); } diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java index 12d27c87..4df07929 100644 --- a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java +++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java @@ -20,9 +20,26 @@ import static org.slf4j.LoggerFactory.getLogger; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; +import org.onlab.util.KryoNamespace; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; import org.onosproject.sfc.manager.SfcService; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.FlowClassifierId; import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortChainId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.event.VtnRscEvent; +import org.onosproject.vtnrsc.event.VtnRscListener; +import org.onosproject.vtnrsc.service.VtnRscService; + import org.slf4j.Logger; /** @@ -33,93 +50,137 @@ import org.slf4j.Logger; public class SfcManager implements SfcService { private final Logger log = getLogger(getClass()); + private static final String APP_ID = "org.onosproject.app.vtn"; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected VtnRscService vtnRscService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + protected ApplicationId appId; + + private final VtnRscListener vtnRscListener = new InnerVtnRscListener(); @Activate public void activate() { + appId = coreService.registerApplication(APP_ID); + + vtnRscService.addListener(vtnRscListener); + + KryoNamespace.Builder serializer = KryoNamespace.newBuilder() + .register(TenantId.class) + .register(PortPairId.class) + .register(PortPairGroupId.class) + .register(FlowClassifierId.class) + .register(PortChainId.class); + log.info("Started"); } @Deactivate public void deactivate() { + vtnRscService.removeListener(vtnRscListener); + log.info("Stopped"); } + /* + * Handle events. + */ + private class InnerVtnRscListener implements VtnRscListener { + @Override + public void event(VtnRscEvent event) { + + if (VtnRscEvent.Type.PORT_PAIR_PUT == event.type()) { + PortPair portPair = (PortPair) event.subject(); + onPortPairCreated(portPair); + } else if (VtnRscEvent.Type.PORT_PAIR_DELETE == event.type()) { + PortPair portPair = (PortPair) event.subject(); + onPortPairDeleted(portPair); + } else if (VtnRscEvent.Type.PORT_PAIR_UPDATE == event.type()) { + PortPair portPair = (PortPair) event.subject(); + onPortPairDeleted(portPair); + onPortPairCreated(portPair); + } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_PUT == event.type()) { + PortPairGroup portPairGroup = (PortPairGroup) event.subject(); + onPortPairGroupCreated(portPairGroup); + } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_DELETE == event.type()) { + PortPairGroup portPairGroup = (PortPairGroup) event.subject(); + onPortPairGroupDeleted(portPairGroup); + } else if (VtnRscEvent.Type.PORT_PAIR_GROUP_UPDATE == event.type()) { + PortPairGroup portPairGroup = (PortPairGroup) event.subject(); + onPortPairGroupDeleted(portPairGroup); + onPortPairGroupCreated(portPairGroup); + } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_PUT == event.type()) { + FlowClassifier flowClassifier = (FlowClassifier) event.subject(); + onFlowClassifierCreated(flowClassifier); + } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_DELETE == event.type()) { + FlowClassifier flowClassifier = (FlowClassifier) event.subject(); + onFlowClassifierDeleted(flowClassifier); + } else if (VtnRscEvent.Type.FLOW_CLASSIFIER_UPDATE == event.type()) { + FlowClassifier flowClassifier = (FlowClassifier) event.subject(); + onFlowClassifierDeleted(flowClassifier); + onFlowClassifierCreated(flowClassifier); + } else if (VtnRscEvent.Type.PORT_CHAIN_PUT == event.type()) { + PortChain portChain = (PortChain) event.subject(); + onPortChainCreated(portChain); + } else if (VtnRscEvent.Type.PORT_CHAIN_DELETE == event.type()) { + PortChain portChain = (PortChain) event.subject(); + onPortChainDeleted(portChain); + } else if (VtnRscEvent.Type.PORT_CHAIN_UPDATE == event.type()) { + PortChain portChain = (PortChain) event.subject(); + onPortChainDeleted(portChain); + onPortChainCreated(portChain); + } + } + } + @Override - public void onPortPairCreated() { + public void onPortPairCreated(PortPair portPair) { log.debug("onPortPairCreated"); - // TODO: Process port-pair on creation. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on port-pair creation. } @Override - public void onPortPairDeleted() { + public void onPortPairDeleted(PortPair portPair) { log.debug("onPortPairDeleted"); - // TODO: Process port-pair on deletion. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on port-pair deletion. } @Override - public void onPortPairGroupCreated() { + public void onPortPairGroupCreated(PortPairGroup portPairGroup) { log.debug("onPortPairGroupCreated"); - // TODO: Process port-pair-group on creation. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on port-pair-group creation. } @Override - public void onPortPairGroupDeleted() { + public void onPortPairGroupDeleted(PortPairGroup portPairGroup) { log.debug("onPortPairGroupDeleted"); - // TODO: Process port-pair-group on deletion. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on port-pair-group deletion. } @Override - public void onFlowClassifierCreated() { + public void onFlowClassifierCreated(FlowClassifier flowClassifier) { log.debug("onFlowClassifierCreated"); - // TODO: Process flow-classifier on creation. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on flow-classifier creation. } @Override - public void onFlowClassifierDeleted() { + public void onFlowClassifierDeleted(FlowClassifier flowClassifier) { log.debug("onFlowClassifierDeleted"); - // TODO: Process flow-classifier on deletion. - // TODO: Parameter also needs to be modified. + // TODO: Modify forwarding rule on flow-classifier deletion. } @Override - public void onPortChainCreated() { - log.debug("onPortChainCreated"); - // TODO: Process port-chain on creation. - // TODO: Parameter also needs to be modified. - + public void onPortChainCreated(PortChain portChain) { + log.debug("onPortChainCreated"); + //TODO: Apply forwarding rule on port-chain creation. } @Override - public void onPortChainDeleted() { + public void onPortChainDeleted(PortChain portChain) { log.debug("onPortChainDeleted"); - // TODO: Process port-chain on deletion. - // TODO: Parameter also needs to be modified. - } - - /** - * Install SF Forwarding rule into OVS. - * - * @param portChain - * port chain - */ - public void installForwardingRule(PortChain portChain) { - log.debug("installForwardingRule"); - // TODO: Installation of SF Forwarding rule into OVS. - } - - /** - * Uninstall SF Forwarding rule from OVS. - * - * @param portChain - * port chain - */ - public void unInstallForwardingRule(PortChain portChain) { - log.debug("unInstallForwardingRule"); - // TODO: Uninstallation of SF Forwarding rule from OVS. + //TODO: Apply forwarding rule on port-chain deletion. } -} \ No newline at end of file +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/manager/impl/SfcManagerTest.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/manager/impl/SfcManagerTest.java new file mode 100644 index 00000000..e4f31f98 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/manager/impl/SfcManagerTest.java @@ -0,0 +1,269 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.manager.impl; + +import org.junit.Test; + +import java.util.List; +import java.util.LinkedList; + +import org.onlab.packet.IpPrefix; +import org.onosproject.sfc.manager.SfcService; +import org.onosproject.vtnrsc.DefaultPortChain; +import org.onosproject.vtnrsc.DefaultPortPair; +import org.onosproject.vtnrsc.DefaultPortPairGroup; +import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortChainId; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.DefaultFlowClassifier; +import org.onosproject.vtnrsc.FlowClassifierId; +import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.FlowClassifier; + +/** + * Unit tests for SfcManager class. + */ +public class SfcManagerTest { + /** + * Checks the operation of onPortPairCreated() method. + */ + @Test + public void testOnPortPairCreated() { + final PortPairId portPairId = PortPairId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortPair"; + final String description = "PortPair"; + final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1"; + final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345"; + DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder(); + PortPair portPair = null; + SfcService sfcService = new SfcManager(); + + // create port pair + portPair = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name).setDescription(description) + .setIngress(ingress).setEgress(egress).build(); + sfcService.onPortPairCreated(portPair); + } + + /** + * Checks the operation of onPortPairDeleted() method. + */ + @Test + public void testOnPortPairDeleted() { + final PortPairId portPairId = PortPairId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortPair"; + final String description = "PortPair"; + final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1"; + final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345"; + DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder(); + PortPair portPair = null; + SfcService sfcService = new SfcManager(); + + // create port pair + portPair = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name).setDescription(description) + .setIngress(ingress).setEgress(egress).build(); + sfcService.onPortPairDeleted(portPair); + } + + /** + * Checks the operation of onPortPairGroupCreated() method. + */ + @Test + public void testOnPortPairGroupCreated() { + final PortPairGroupId portPairGroupId = PortPairGroupId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortPairGroup"; + final String description = "PortPairGroup"; + final List portPairIdList = new LinkedList(); + DefaultPortPairGroup.Builder portPairGroupBuilder = new DefaultPortPairGroup.Builder(); + PortPairGroup portPairGroup = null; + SfcService sfcService = new SfcManager(); + + // create port-pair-id list + PortPairId portPairId = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairIdList.add(portPairId); + portPairId = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairIdList.add(portPairId); + + // create port pair + portPairGroup = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId).setName(name) + .setDescription(description).setPortPairs(portPairIdList).build(); + sfcService.onPortPairGroupCreated(portPairGroup); + } + + /** + * Checks the operation of onPortPairGroupDeleted() method. + */ + @Test + public void testOnPortPairGroupDeleted() { + final PortPairGroupId portPairGroupId = PortPairGroupId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortPairGroup"; + final String description = "PortPairGroup"; + final List portPairIdList = new LinkedList(); + DefaultPortPairGroup.Builder portPairGroupBuilder = new DefaultPortPairGroup.Builder(); + PortPairGroup portPairGroup = null; + SfcService sfcService = new SfcManager(); + + // create port-pair-id list + PortPairId portPairId = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairIdList.add(portPairId); + portPairId = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairIdList.add(portPairId); + + // create port pair + portPairGroup = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId).setName(name) + .setDescription(description).setPortPairs(portPairIdList).build(); + sfcService.onPortPairGroupDeleted(portPairGroup); + } + + /** + * Checks the operation of onFlowClassifierCreated() method. + */ + @Test + public void testOnFlowClassifierCreated() { + final String name = "FlowClassifier"; + final String description = "FlowClassifier"; + final String ethType = "IPv4"; + final String protocol = "udp"; + final int minSrcPortRange = 1024; + final int maxSrcPortRange = 5000; + final int minDstPortRange = 1024; + final int maxDstPortRange = 5000; + final FlowClassifierId flowClassifierId = FlowClassifierId.of("71111111-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("8"); + final IpPrefix srcIpPrefix = IpPrefix.valueOf("0.0.0.0/0"); + final IpPrefix dstIpPrefix = IpPrefix.valueOf("100.100.100.100/0"); + final VirtualPortId virtualSrcPort = VirtualPortId.portId("100"); + final VirtualPortId virtualDstPort = VirtualPortId.portId("200"); + DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder(); + FlowClassifier flowClassifier = null; + SfcService sfcService = new SfcManager(); + + // create flow classifier + flowClassifier = flowClassifierBuilder.setFlowClassifierId(flowClassifierId).setTenantId(tenantId) + .setName(name).setDescription(description).setEtherType(ethType).setProtocol(protocol) + .setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange) + .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix) + .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build(); + sfcService.onFlowClassifierCreated(flowClassifier); + } + + /** + * Checks the operation of onFlowClassifierDeleted() method. + */ + @Test + public void testOnFlowClassifierDeleted() { + final String name = "FlowClassifier"; + final String description = "FlowClassifier"; + final String ethType = "IPv4"; + final String protocol = "udp"; + final int minSrcPortRange = 1024; + final int maxSrcPortRange = 5000; + final int minDstPortRange = 1024; + final int maxDstPortRange = 5000; + final FlowClassifierId flowClassifierId = FlowClassifierId.of("71111111-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("8"); + final IpPrefix srcIpPrefix = IpPrefix.valueOf("0.0.0.0/0"); + final IpPrefix dstIpPrefix = IpPrefix.valueOf("100.100.100.100/0"); + final VirtualPortId virtualSrcPort = VirtualPortId.portId("100"); + final VirtualPortId virtualDstPort = VirtualPortId.portId("200"); + DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder(); + FlowClassifier flowClassifier = null; + SfcService sfcService = new SfcManager(); + + // create flow classifier + flowClassifier = flowClassifierBuilder.setFlowClassifierId(flowClassifierId).setTenantId(tenantId) + .setName(name).setDescription(description).setEtherType(ethType).setProtocol(protocol) + .setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange) + .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix) + .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build(); + sfcService.onFlowClassifierDeleted(flowClassifier); + } + + /** + * Checks the operation of onPortChainCreated() method. + */ + @Test + public void testOnPortChainCreated() { + final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortChain"; + final String description = "PortChain"; + final List portPairGroupList = new LinkedList(); + final List flowClassifierList = new LinkedList(); + DefaultPortChain.Builder portChainBuilder = new DefaultPortChain.Builder(); + DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder(); + PortChain portChain = null; + SfcService sfcService = new SfcManager(); + + // create list of Port Pair Groups. + PortPairGroupId portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairGroupList.add(portPairGroupId); + portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3af"); + portPairGroupList.add(portPairGroupId); + + // create list of Flow classifiers. + FlowClassifierId flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae"); + flowClassifierList.add(flowClassifierId); + flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3af"); + flowClassifierList.add(flowClassifierId); + + // create port chain + portChain = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name).setDescription(description) + .setPortPairGroups(portPairGroupList).setFlowClassifiers(flowClassifierList).build(); + sfcService.onPortChainCreated(portChain); + } + + /** + * Checks the operation of onPortChainDeleted() method. + */ + @Test + public void testOnPortChainDeleted() { + final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae"); + final TenantId tenantId = TenantId.tenantId("1"); + final String name = "PortChain"; + final String description = "PortChain"; + final List portPairGroupList = new LinkedList(); + final List flowClassifierList = new LinkedList(); + DefaultPortChain.Builder portChainBuilder = new DefaultPortChain.Builder(); + DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder(); + PortChain portChain = null; + SfcService sfcService = new SfcManager(); + + // create list of Port Pair Groups. + PortPairGroupId portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae"); + portPairGroupList.add(portPairGroupId); + portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3af"); + portPairGroupList.add(portPairGroupId); + + // create list of Flow classifiers. + FlowClassifierId flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae"); + flowClassifierList.add(flowClassifierId); + flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3af"); + flowClassifierList.add(flowClassifierId); + + // create port chain + portChain = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name).setDescription(description) + .setPortPairGroups(portPairGroupList).setFlowClassifiers(flowClassifierList).build(); + sfcService.onPortChainDeleted(portChain); + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowClassifierManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowClassifierManagerTestImpl.java new file mode 100644 index 00000000..fe5babbd --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowClassifierManagerTestImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.onosproject.vtnrsc.FlowClassifierId; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierListener; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; + +import com.google.common.collect.ImmutableList; + +/** + * Provides implementation of the Flow Classifier Service. + */ +public class FlowClassifierManagerTestImpl implements FlowClassifierService { + + private final ConcurrentMap flowClassifierStore = new ConcurrentHashMap<>(); + + @Override + public boolean exists(FlowClassifierId id) { + return flowClassifierStore.containsKey(id); + } + + @Override + public int getFlowClassifierCount() { + return flowClassifierStore.size(); + } + + @Override + public Iterable getFlowClassifiers() { + return ImmutableList.copyOf(flowClassifierStore.values()); + } + + @Override + public FlowClassifier getFlowClassifier(FlowClassifierId id) { + return flowClassifierStore.get(id); + } + + @Override + public boolean createFlowClassifier(FlowClassifier flowClassifier) { + FlowClassifierId id = flowClassifier.flowClassifierId(); + + flowClassifierStore.put(id, flowClassifier); + if (!flowClassifierStore.containsKey(id)) { + return false; + } + return true; + } + + @Override + public boolean updateFlowClassifier(FlowClassifier flowClassifier) { + + if (!flowClassifierStore.containsKey(flowClassifier.flowClassifierId())) { + return false; + } + + flowClassifierStore.put(flowClassifier.flowClassifierId(), flowClassifier); + + if (!flowClassifier.equals(flowClassifierStore.get(flowClassifier.flowClassifierId()))) { + return false; + } + return true; + } + + @Override + public boolean removeFlowClassifier(FlowClassifierId id) { + return true; + } + + @Override + public void addListener(FlowClassifierListener listener) { + } + + @Override + public void removeListener(FlowClassifierListener listener) { + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowObjectiveServiceTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowObjectiveServiceTestImpl.java new file mode 100644 index 00000000..9da9ee94 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/FlowObjectiveServiceTestImpl.java @@ -0,0 +1,53 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.FilteringObjective; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.NextObjective; + +/** + * Testing version of implementation on FlowObjectiveService. + */ +public class FlowObjectiveServiceTestImpl implements FlowObjectiveService { + + @Override + public void filter(DeviceId deviceId, FilteringObjective filteringObjective) { + + } + + @Override + public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) { + + } + + @Override + public void next(DeviceId deviceId, NextObjective nextObjective) { + + } + + @Override + public int allocateNextId() { + return 0; + } + + @Override + public void initPolicy(String policy) { + + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortChainManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortChainManagerTestImpl.java new file mode 100644 index 00000000..4a3ba03d --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortChainManagerTestImpl.java @@ -0,0 +1,85 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Collections; + +import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortChainId; +import org.onosproject.vtnrsc.portchain.PortChainService; +import org.onosproject.vtnrsc.portchain.PortChainEvent; +import org.onosproject.vtnrsc.portchain.PortChainListener; +import org.onosproject.event.AbstractListenerManager; + +/** + * Provides implementation of the portChainService. + */ +public class PortChainManagerTestImpl + extends AbstractListenerManager + implements PortChainService { + + private ConcurrentMap portChainStore = new ConcurrentHashMap<>(); + + @Override + public boolean exists(PortChainId portChainId) { + return portChainStore.containsKey(portChainId); + } + + @Override + public int getPortChainCount() { + return portChainStore.size(); + } + + @Override + public Iterable getPortChains() { + return Collections.unmodifiableCollection(portChainStore.values()); + } + + @Override + public PortChain getPortChain(PortChainId portChainId) { + return portChainStore.get(portChainId); + } + + @Override + public boolean createPortChain(PortChain portChain) { + portChainStore.put(portChain.portChainId(), portChain); + if (!portChainStore.containsKey(portChain.portChainId())) { + return false; + } + return true; + } + + @Override + public boolean updatePortChain(PortChain portChain) { + if (!portChainStore.containsKey(portChain.portChainId())) { + return false; + } + + portChainStore.put(portChain.portChainId(), portChain); + + if (!portChain.equals(portChainStore.get(portChain.portChainId()))) { + return false; + } + return true; + } + + @Override + public boolean removePortChain(PortChainId portChainId) { + return true; + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairGroupManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairGroupManagerTestImpl.java new file mode 100644 index 00000000..ba31cd60 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairGroupManagerTestImpl.java @@ -0,0 +1,89 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Collections; + +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupListener; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; + +/** + * Provides implementation of the portPairGroupService. + */ +public class PortPairGroupManagerTestImpl implements PortPairGroupService { + + private ConcurrentMap portPairGroupStore = new ConcurrentHashMap<>(); + + @Override + public boolean exists(PortPairGroupId portPairGroupId) { + return portPairGroupStore.containsKey(portPairGroupId); + } + + @Override + public int getPortPairGroupCount() { + return portPairGroupStore.size(); + } + + @Override + public Iterable getPortPairGroups() { + return Collections.unmodifiableCollection(portPairGroupStore.values()); + } + + @Override + public PortPairGroup getPortPairGroup(PortPairGroupId portPairGroupId) { + return portPairGroupStore.get(portPairGroupId); + } + + @Override + public boolean createPortPairGroup(PortPairGroup portPairGroup) { + portPairGroupStore.put(portPairGroup.portPairGroupId(), portPairGroup); + if (!portPairGroupStore.containsKey(portPairGroup.portPairGroupId())) { + return false; + } + return true; + } + + @Override + public boolean updatePortPairGroup(PortPairGroup portPairGroup) { + if (!portPairGroupStore.containsKey(portPairGroup.portPairGroupId())) { + return false; + } + + portPairGroupStore.put(portPairGroup.portPairGroupId(), portPairGroup); + + if (!portPairGroup.equals(portPairGroupStore.get(portPairGroup.portPairGroupId()))) { + return false; + } + return true; + } + + @Override + public boolean removePortPairGroup(PortPairGroupId portPairGroupId) { + return true; + } + + @Override + public void addListener(PortPairGroupListener listener) { + } + + @Override + public void removeListener(PortPairGroupListener listener) { + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairManagerTestImpl.java new file mode 100644 index 00000000..aff58823 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/PortPairManagerTestImpl.java @@ -0,0 +1,89 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Collections; + +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.portpair.PortPairListener; +import org.onosproject.vtnrsc.portpair.PortPairService; + +/** + * Provides implementation of the portPairService. + */ +public class PortPairManagerTestImpl implements PortPairService { + + private ConcurrentMap portPairStore = new ConcurrentHashMap<>(); + + @Override + public boolean exists(PortPairId portPairId) { + return portPairStore.containsKey(portPairId); + } + + @Override + public int getPortPairCount() { + return portPairStore.size(); + } + + @Override + public Iterable getPortPairs() { + return Collections.unmodifiableCollection(portPairStore.values()); + } + + @Override + public PortPair getPortPair(PortPairId portPairId) { + return portPairStore.get(portPairId); + } + + @Override + public boolean createPortPair(PortPair portPair) { + portPairStore.put(portPair.portPairId(), portPair); + if (!portPairStore.containsKey(portPair.portPairId())) { + return false; + } + return true; + } + + @Override + public boolean updatePortPair(PortPair portPair) { + if (!portPairStore.containsKey(portPair.portPairId())) { + return false; + } + + portPairStore.put(portPair.portPairId(), portPair); + + if (!portPair.equals(portPairStore.get(portPair.portPairId()))) { + return false; + } + return true; + } + + @Override + public boolean removePortPair(PortPairId portPairId) { + return true; + } + + @Override + public void addListener(PortPairListener listener) { + } + + @Override + public void removeListener(PortPairListener listener) { + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VirtualPortManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VirtualPortManagerTestImpl.java new file mode 100644 index 00000000..de056a78 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VirtualPortManagerTestImpl.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.Collection; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.onlab.packet.IpAddress; +import org.onosproject.net.DeviceId; +import org.onosproject.vtnrsc.FixedIp; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.VirtualPort; +import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.TenantNetworkId; +import org.onosproject.vtnrsc.virtualport.VirtualPortService; + +/** + * Provides implementation of the VirtualPort APIs. + */ +public class VirtualPortManagerTestImpl implements VirtualPortService { + + protected ConcurrentMap vPortStore = new ConcurrentHashMap<>(); + + @Override + public boolean exists(VirtualPortId vPortId) { + return vPortStore.containsKey(vPortId); + } + + @Override + public VirtualPort getPort(VirtualPortId vPortId) { + return vPortStore.get(vPortId); + } + + @Override + public VirtualPort getPort(FixedIp fixedIP) { + return null; + } + + @Override + public Collection getPorts() { + return null; + } + + @Override + public Collection getPorts(TenantNetworkId networkId) { + return null; + } + + @Override + public Collection getPorts(TenantId tenantId) { + return null; + } + + @Override + public Collection getPorts(DeviceId deviceId) { + return null; + } + + @Override + public VirtualPort getPort(TenantNetworkId networkId, IpAddress ipAddress) { + return null; + } + + @Override + public boolean createPorts(Iterable vPorts) { + for (VirtualPort vPort : vPorts) { + vPortStore.put(vPort.portId(), vPort); + if (!vPortStore.containsKey(vPort.portId())) { + return false; + } + } + return true; + } + + @Override + public boolean updatePorts(Iterable vPorts) { + return true; + } + + @Override + public boolean removePorts(Iterable vPortIds) { + return true; + } +} diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VtnRscManagerTestImpl.java b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VtnRscManagerTestImpl.java new file mode 100644 index 00000000..4188cee6 --- /dev/null +++ b/framework/src/onos/apps/vtn/sfcmgr/src/test/java/org/onosproject/sfc/util/VtnRscManagerTestImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.sfc.util; + +import java.util.Iterator; + +import org.onlab.packet.MacAddress; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.HostId; +import org.onosproject.vtnrsc.SegmentationId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.event.VtnRscListener; +import org.onosproject.vtnrsc.service.VtnRscService; + +/** + * Provides implementation of the VtnRsc service. + */ +public class VtnRscManagerTestImpl implements VtnRscService { + @Override + public void addListener(VtnRscListener listener) { + } + + @Override + public void removeListener(VtnRscListener listener) { + } + + @Override + public SegmentationId getL3vni(TenantId tenantId) { + return null; + } + + @Override + public Iterator getClassifierOfTenant(TenantId tenantId) { + return null; + } + + @Override + public Iterator getSFFOfTenant(TenantId tenantId) { + return null; + } + + @Override + public MacAddress getGatewayMac(HostId hostId) { + return null; + } + + @Override + public boolean isServiceFunction(VirtualPortId portId) { + // TODO Auto-generated method stub + return false; + } + + @Override + public DeviceId getSFToSFFMaping(VirtualPortId portId) { + return DeviceId.deviceId("www.google.com"); + } +} diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java index a104e529..d7ee3607 100644 --- a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java +++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java @@ -17,6 +17,7 @@ package org.onosproject.vtn.manager; import org.onosproject.net.Device; import org.onosproject.net.Host; +import org.onosproject.vtnrsc.event.VtnRscEventFeedback; /** * VTN application that applies configuration and flows to the device. @@ -67,4 +68,32 @@ public interface VTNService { */ void onHostVanished(Host host); + /** + * Applies east west flows when neutron created router interface. + * + * @param l3Feedback VtnrscEventFeedback + */ + void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback); + + /** + * Remove east west flows when neutron removed router interface. + * + * @param l3Feedback VtnrscEventFeedback + */ + void onRouterInterfaceVanished(VtnRscEventFeedback l3Feedback); + + /** + * Applies north south flows when neutron bind floating ip. + * + * @param l3Feedback VtnrscEventFeedback + */ + void onFloatingIpDetected(VtnRscEventFeedback l3Feedback); + + /** + * Applies north south flows when neutron unbind floating ip. + * + * @param l3Feedback VtnrscEventFeedback + */ + void onFloatingIpVanished(VtnRscEventFeedback l3Feedback); + } diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java index be6b9364..6429314e 100644 --- a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java +++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java @@ -18,6 +18,7 @@ package org.onosproject.vtn.manager.impl; import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST; import static org.slf4j.LoggerFactory.getLogger; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -25,6 +26,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -39,9 +41,11 @@ import org.onlab.util.KryoNamespace; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.mastership.MastershipService; +import org.onosproject.net.AnnotationKeys; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Host; +import org.onosproject.net.HostId; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.behaviour.BridgeConfig; @@ -74,8 +78,12 @@ import org.onosproject.store.service.EventuallyConsistentMap; import org.onosproject.store.service.LogicalClockService; import org.onosproject.store.service.StorageService; import org.onosproject.vtn.manager.VTNService; +import org.onosproject.vtn.table.ArpService; import org.onosproject.vtn.table.ClassifierService; +import org.onosproject.vtn.table.DnatService; import org.onosproject.vtn.table.L2ForwardService; +import org.onosproject.vtn.table.L3ForwardService; +import org.onosproject.vtn.table.SnatService; import org.onosproject.vtn.table.impl.ClassifierServiceImpl; import org.onosproject.vtn.table.impl.L2ForwardServiceImpl; import org.onosproject.vtn.util.DataPathIdGenerator; @@ -85,6 +93,11 @@ import org.onosproject.vtnrsc.AllowedAddressPair; import org.onosproject.vtnrsc.BindingHostId; import org.onosproject.vtnrsc.DefaultVirtualPort; import org.onosproject.vtnrsc.FixedIp; +import org.onosproject.vtnrsc.FloatingIp; +import org.onosproject.vtnrsc.Router; +import org.onosproject.vtnrsc.RouterGateway; +import org.onosproject.vtnrsc.RouterId; +import org.onosproject.vtnrsc.RouterInterface; import org.onosproject.vtnrsc.SecurityGroup; import org.onosproject.vtnrsc.SegmentationId; import org.onosproject.vtnrsc.SubnetId; @@ -93,6 +106,14 @@ import org.onosproject.vtnrsc.TenantNetwork; import org.onosproject.vtnrsc.TenantNetworkId; import org.onosproject.vtnrsc.VirtualPort; import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.event.VtnRscEvent; +import org.onosproject.vtnrsc.event.VtnRscEventFeedback; +import org.onosproject.vtnrsc.event.VtnRscListener; +import org.onosproject.vtnrsc.floatingip.FloatingIpService; +import org.onosproject.vtnrsc.router.RouterService; +import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService; +import org.onosproject.vtnrsc.service.VtnRscService; +import org.onosproject.vtnrsc.subnet.SubnetService; import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService; import org.onosproject.vtnrsc.virtualport.VirtualPortService; import org.slf4j.Logger; @@ -142,12 +163,32 @@ public class VTNManager implements VTNService { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected GroupService groupService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected SubnetService subnetService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected VtnRscService vtnRscService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FloatingIpService floatingIpService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected RouterService routerService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected RouterInterfaceService routerInterfaceService; + private ApplicationId appId; private ClassifierService classifierService; private L2ForwardService l2ForwardService; + private ArpService arpService; + private L3ForwardService l3ForwardService; + private SnatService snatService; + private DnatService dnatService; private final HostListener hostListener = new InnerHostListener(); private final DeviceListener deviceListener = new InnerDeviceListener(); + private final VtnRscListener l3EventListener = new VtnL3EventListener(); private static final String IFACEID = "ifaceid"; private static final String CONTROLLER_IP_KEY = "ipaddress"; @@ -156,11 +197,19 @@ public class VTNManager implements VTNService { private static final String VIRTUALPORT = "vtn-virtual-port"; private static final String SWITCHES_OF_CONTROLLER = "switchesOfController"; private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts"; + private static final String ROUTERINF_FLAG_OF_TENANT = "routerInfFlagOfTenant"; + private static final String HOSTS_OF_SUBNET = "hostsOfSubnet"; + private static final String EX_PORT_OF_DEVICE = "exPortOfDevice"; private static final String DEFAULT_IP = "0.0.0.0"; + private static final String PORT_MAC = "portMac"; + private static final int SUBNET_NUM = 2; private EventuallyConsistentMap vPortStore; private EventuallyConsistentMap switchesOfController; private EventuallyConsistentMap switchOfLocalHostPorts; + private EventuallyConsistentMap> hostsOfSubnet; + private EventuallyConsistentMap routerInfFlagOfTenant; + private EventuallyConsistentMap exPortOfDevice; @Activate public void activate() { @@ -206,6 +255,24 @@ public class VTNManager implements VTNService { .withTimestampProvider((k, v) -> clockService.getTimestamp()) .build(); + hostsOfSubnet = storageService + .>eventuallyConsistentMapBuilder() + .withName(HOSTS_OF_SUBNET).withSerializer(serializer) + .withTimestampProvider((k, v) -> clockService.getTimestamp()) + .build(); + + routerInfFlagOfTenant = storageService + .eventuallyConsistentMapBuilder() + .withName(ROUTERINF_FLAG_OF_TENANT).withSerializer(serializer) + .withTimestampProvider((k, v) -> clockService.getTimestamp()) + .build(); + + exPortOfDevice = storageService + .eventuallyConsistentMapBuilder() + .withName(EX_PORT_OF_DEVICE).withSerializer(serializer) + .withTimestampProvider((k, v) -> clockService.getTimestamp()) + .build(); + log.info("Started"); } @@ -213,6 +280,7 @@ public class VTNManager implements VTNService { public void deactivate() { deviceService.removeListener(deviceListener); hostService.removeListener(hostListener); + vtnRscService.removeListener(l3EventListener); log.info("Stopped"); } @@ -278,14 +346,36 @@ public class VTNManager implements VTNService { @Override public void onHostDetected(Host host) { + DeviceId deviceId = host.location().deviceId(); + if (!mastershipService.isLocalMaster(deviceId)) { + return; + } + String ifaceId = host.annotations().value(IFACEID); + if (ifaceId == null) { + log.error("The ifaceId of Host is null"); + return; + } // apply L2 openflow rules applyHostMonitoredL2Rules(host, Objective.Operation.ADD); + // apply L3 openflow rules + applyHostMonitoredL3Rules(host, Objective.Operation.ADD); } @Override public void onHostVanished(Host host) { + DeviceId deviceId = host.location().deviceId(); + if (!mastershipService.isLocalMaster(deviceId)) { + return; + } + String ifaceId = host.annotations().value(IFACEID); + if (ifaceId == null) { + log.error("The ifaceId of Host is null"); + return; + } // apply L2 openflow rules applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE); + // apply L3 openflow rules + applyHostMonitoredL3Rules(host, Objective.Operation.REMOVE); } private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp, @@ -376,7 +466,7 @@ public class VTNManager implements VTNService { VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId); VirtualPort virtualPort = virtualPortService.getPort(virtualPortId); if (virtualPort == null) { - virtualPort = vPortStore.get(virtualPortId); + virtualPort = VtnData.getPort(vPortStore, virtualPortId); } Iterable devices = deviceService.getAvailableDevices(); @@ -582,4 +672,388 @@ public class VTNManager implements VTNService { appid); groupService.addGroup(groupDescription); } + + private class VtnL3EventListener implements VtnRscListener { + @Override + public void event(VtnRscEvent event) { + VtnRscEventFeedback l3Feedback = event.subject(); + if (VtnRscEvent.Type.ROUTER_INTERFACE_PUT == event.type()) { + onRouterInterfaceDetected(l3Feedback); + } else + if (VtnRscEvent.Type.ROUTER_INTERFACE_DELETE == event.type()) { + onRouterInterfaceVanished(l3Feedback); + } else if (VtnRscEvent.Type.FLOATINGIP_PUT == event.type()) { + onFloatingIpDetected(l3Feedback); + } else if (VtnRscEvent.Type.FLOATINGIP_DELETE == event.type()) { + onFloatingIpVanished(l3Feedback); + } + } + + } + + @Override + public void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback) { + Objective.Operation operation = Objective.Operation.ADD; + RouterInterface routerInf = l3Feedback.routerInterface(); + Iterable interfaces = routerInterfaceService + .getRouterInterfaces(); + Set interfacesSet = Sets.newHashSet(interfaces) + .stream().filter(r -> r.tenantId().equals(routerInf.tenantId())) + .collect(Collectors.toSet()); + if (routerInfFlagOfTenant.get(routerInf.tenantId()) != null) { + programRouterInterface(routerInf, operation); + } else { + if (interfacesSet.size() >= SUBNET_NUM) { + programInterfacesSet(interfacesSet, operation); + } + } + } + + @Override + public void onRouterInterfaceVanished(VtnRscEventFeedback l3Feedback) { + Objective.Operation operation = Objective.Operation.REMOVE; + RouterInterface routerInf = l3Feedback.routerInterface(); + Iterable interfaces = routerInterfaceService + .getRouterInterfaces(); + Set interfacesSet = Sets.newHashSet(interfaces) + .stream().filter(r -> r.tenantId().equals(routerInf.tenantId())) + .collect(Collectors.toSet()); + if (routerInfFlagOfTenant.get(routerInf.tenantId()) != null) { + programRouterInterface(routerInf, operation); + if (interfacesSet.size() == 1) { + routerInfFlagOfTenant.remove(routerInf.tenantId()); + interfacesSet.stream().forEach(r -> { + programRouterInterface(r, operation); + }); + } + } + } + + @Override + public void onFloatingIpDetected(VtnRscEventFeedback l3Feedback) { + programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_PUT); + } + + @Override + public void onFloatingIpVanished(VtnRscEventFeedback l3Feedback) { + programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_DELETE); + } + + private void programInterfacesSet(Set interfacesSet, + Objective.Operation operation) { + int subnetVmNum = 0; + for (RouterInterface r : interfacesSet) { + // Get all the host of the subnet + Map hosts = hostsOfSubnet.get(r.subnetId()); + if (hosts.size() > 0) { + subnetVmNum++; + if (subnetVmNum >= SUBNET_NUM) { + routerInfFlagOfTenant.put(r.tenantId(), true); + interfacesSet.stream().forEach(f -> { + programRouterInterface(f, operation); + }); + break; + } + } + } + } + + private void programRouterInterface(RouterInterface routerInf, + Objective.Operation operation) { + SegmentationId l3vni = vtnRscService.getL3vni(routerInf.tenantId()); + // Get all the host of the subnet + Map hosts = hostsOfSubnet.get(routerInf.subnetId()); + hosts.values().stream().forEach(h -> { + applyEastWestL3Flows(h, l3vni, operation); + }); + } + + private void applyEastWestL3Flows(Host h, SegmentationId l3vni, + Objective.Operation operation) { + if (!mastershipService.isLocalMaster(h.location().deviceId())) { + log.debug("not master device:{}", h.location().deviceId()); + return; + } + String ifaceId = h.annotations().value(IFACEID); + VirtualPort hPort = virtualPortService + .getPort(VirtualPortId.portId(ifaceId)); + if (hPort == null) { + hPort = VtnData.getPort(vPortStore, VirtualPortId.portId(ifaceId)); + } + IpAddress srcIp = null; + IpAddress srcGwIp = null; + MacAddress srcVmGwMac = null; + SubnetId srcSubnetId = null; + Iterator srcIps = hPort.fixedIps().iterator(); + if (srcIps.hasNext()) { + FixedIp fixedIp = srcIps.next(); + srcIp = fixedIp.ip(); + srcSubnetId = fixedIp.subnetId(); + srcGwIp = subnetService.getSubnet(srcSubnetId).gatewayIp(); + FixedIp fixedGwIp = FixedIp.fixedIp(srcSubnetId, srcGwIp); + VirtualPort gwPort = virtualPortService.getPort(fixedGwIp); + if (gwPort == null) { + gwPort = VtnData.getPort(vPortStore, fixedGwIp); + } + srcVmGwMac = gwPort.macAddress(); + } + TenantNetwork network = tenantNetworkService + .getNetwork(hPort.networkId()); + // Classifier rules + classifierService + .programL3InPortClassifierRules(h.location().deviceId(), + h.location().port(), h.mac(), + srcVmGwMac, l3vni, operation); + // Arp rules + if (operation == Objective.Operation.ADD) { + classifierService.programArpClassifierRules(h.location().deviceId(), + srcGwIp, + network.segmentationId(), + operation); + DriverHandler handler = driverService.createHandler(h.location().deviceId()); + arpService.programArpRules(handler, h.location().deviceId(), srcGwIp, + network.segmentationId(), srcVmGwMac, + operation); + } + Iterable devices = deviceService.getAvailableDevices(); + IpAddress srcArpIp = srcIp; + MacAddress srcArpGwMac = srcVmGwMac; + Sets.newHashSet(devices).stream() + .filter(d -> Device.Type.SWITCH == d.type()).forEach(d -> { + // L3FWD rules + l3ForwardService.programRouteRules(d.id(), l3vni, srcArpIp, + network.segmentationId(), + srcArpGwMac, h.mac(), + operation); + }); + } + + private void programFloatingIpEvent(VtnRscEventFeedback l3Feedback, + VtnRscEvent.Type type) { + FloatingIp floaingIp = l3Feedback.floatingIp(); + if (floaingIp != null) { + VirtualPortId vmPortId = floaingIp.portId(); + VirtualPort vmPort = virtualPortService.getPort(vmPortId); + VirtualPort fipPort = virtualPortService + .getPort(floaingIp.networkId(), floaingIp.floatingIp()); + if (vmPort == null) { + vmPort = VtnData.getPort(vPortStore, vmPortId); + } + if (fipPort == null) { + fipPort = VtnData.getPort(vPortStore, floaingIp.networkId(), + floaingIp.floatingIp()); + } + Set hostSet = hostService.getHostsByMac(vmPort.macAddress()); + Host host = null; + for (Host h : hostSet) { + String ifaceid = h.annotations().value(IFACEID); + if (ifaceid != null && ifaceid.equals(vmPortId.portId())) { + host = h; + break; + } + } + if (host != null && vmPort != null && fipPort != null) { + DeviceId deviceId = host.location().deviceId(); + Port exPort = exPortOfDevice.get(deviceId); + SegmentationId l3vni = vtnRscService + .getL3vni(vmPort.tenantId()); + // Floating ip BIND + if (type == VtnRscEvent.Type.FLOATINGIP_PUT) { + applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort, + floaingIp, l3vni, exPort, + Objective.Operation.ADD); + } else if (type == VtnRscEvent.Type.FLOATINGIP_DELETE) { + // Floating ip UNBIND + applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort, + floaingIp, l3vni, exPort, + Objective.Operation.REMOVE); + } + } + } + } + + private void applyNorthSouthL3Flows(DeviceId deviceId, Host host, + VirtualPort vmPort, VirtualPort fipPort, + FloatingIp floatingIp, + SegmentationId l3Vni, Port exPort, + Objective.Operation operation) { + if (!mastershipService.isLocalMaster(deviceId)) { + log.debug("not master device:{}", deviceId); + return; + } + List gwIpMac = getGwIpAndMac(vmPort); + IpAddress dstVmGwIp = (IpAddress) gwIpMac.get(0); + MacAddress dstVmGwMac = (MacAddress) gwIpMac.get(1); + FixedIp fixedGwIp = getGwFixedIp(floatingIp); + MacAddress fGwMac = null; + if (fixedGwIp != null) { + VirtualPort gwPort = virtualPortService.getPort(fixedGwIp); + if (gwPort == null) { + gwPort = VtnData.getPort(vPortStore, fixedGwIp); + } + fGwMac = gwPort.macAddress(); + } + TenantNetwork vmNetwork = tenantNetworkService + .getNetwork(vmPort.networkId()); + TenantNetwork fipNetwork = tenantNetworkService + .getNetwork(fipPort.networkId()); + // L3 downlink traffic flow + MacAddress exPortMac = MacAddress.valueOf(exPort.annotations().value(PORT_MAC)); + classifierService.programArpClassifierRules(deviceId, floatingIp.floatingIp(), + fipNetwork.segmentationId(), + operation); + classifierService.programL3ExPortClassifierRules(deviceId, exPort.number(), + floatingIp.floatingIp(), operation); + DriverHandler handler = driverService.createHandler(deviceId); + arpService.programArpRules(handler, deviceId, floatingIp.floatingIp(), + fipNetwork.segmentationId(), exPortMac, + operation); + dnatService.programRules(deviceId, floatingIp.floatingIp(), + fGwMac, floatingIp.fixedIp(), + l3Vni, operation); + l3ForwardService + .programRouteRules(deviceId, l3Vni, floatingIp.fixedIp(), + vmNetwork.segmentationId(), dstVmGwMac, + vmPort.macAddress(), operation); + + // L3 uplink traffic flow + classifierService.programL3InPortClassifierRules(deviceId, + host.location().port(), + host.mac(), dstVmGwMac, + l3Vni, operation); + snatService.programRules(deviceId, l3Vni, floatingIp.fixedIp(), + fGwMac, exPortMac, + floatingIp.floatingIp(), + fipNetwork.segmentationId(), operation); + if (operation == Objective.Operation.ADD) { + classifierService.programArpClassifierRules(deviceId, dstVmGwIp, + vmNetwork.segmentationId(), + operation); + arpService.programArpRules(handler, deviceId, dstVmGwIp, + vmNetwork.segmentationId(), dstVmGwMac, + operation); + l2ForwardService.programLocalOut(deviceId, + fipNetwork.segmentationId(), + exPort.number(), fGwMac, operation); + } + } + + private Port getExPort(DeviceId deviceId) { + List ports = deviceService.getPorts(deviceId); + Port exPort = null; + for (Port port : ports) { + String portName = port.annotations().value(AnnotationKeys.PORT_NAME); + if (portName != null && portName.equals(EX_PORT_NAME)) { + exPort = port; + break; + } + } + return exPort; + } + + private List getGwIpAndMac(VirtualPort port) { + List list = new ArrayList(); + MacAddress gwMac = null; + SubnetId subnetId = null; + IpAddress gwIp = null; + Iterator fixips = port.fixedIps().iterator(); + if (fixips.hasNext()) { + FixedIp fixip = fixips.next(); + subnetId = fixip.subnetId(); + gwIp = subnetService.getSubnet(subnetId).gatewayIp(); + FixedIp fixedGwIp = FixedIp.fixedIp(fixip.subnetId(), gwIp); + VirtualPort gwPort = virtualPortService.getPort(fixedGwIp); + if (gwPort == null) { + gwPort = VtnData.getPort(vPortStore, fixedGwIp); + } + gwMac = gwPort.macAddress(); + } + list.add(gwIp); + list.add(gwMac); + return list; + } + + private FixedIp getGwFixedIp(FloatingIp floatingIp) { + RouterId routerId = floatingIp.routerId(); + Router router = routerService.getRouter(routerId); + RouterGateway routerGateway = router.externalGatewayInfo(); + Iterable externalFixedIps = routerGateway.externalFixedIps(); + FixedIp fixedGwIp = null; + if (externalFixedIps != null) { + Iterator exFixedIps = externalFixedIps.iterator(); + if (exFixedIps.hasNext()) { + fixedGwIp = exFixedIps.next(); + } + } + return fixedGwIp; + } + + private void applyHostMonitoredL3Rules(Host host, + Objective.Operation operation) { + String ifaceId = host.annotations().value(IFACEID); + DeviceId deviceId = host.location().deviceId(); + VirtualPortId portId = VirtualPortId.portId(ifaceId); + VirtualPort port = virtualPortService.getPort(portId); + if (port == null) { + port = VtnData.getPort(vPortStore, portId); + } + TenantId tenantId = port.tenantId(); + Port exPort = exPortOfDevice.get(deviceId); + SegmentationId l3vni = vtnRscService.getL3vni(tenantId); + Iterator fixips = port.fixedIps().iterator(); + SubnetId sid = null; + IpAddress hostIp = null; + if (fixips.hasNext()) { + FixedIp fixip = fixips.next(); + sid = fixip.subnetId(); + hostIp = fixip.ip(); + } + final SubnetId subnetId = sid; + // L3 internal network access to each other + Iterable interfaces = routerInterfaceService + .getRouterInterfaces(); + Set interfacesSet = Sets.newHashSet(interfaces) + .stream().filter(r -> r.tenantId().equals(tenantId)) + .collect(Collectors.toSet()); + long count = interfacesSet.stream() + .filter(r -> !r.subnetId().equals(subnetId)).count(); + if (count > 0) { + if (operation == Objective.Operation.ADD) { + if (routerInfFlagOfTenant.get(tenantId) != null) { + applyEastWestL3Flows(host, l3vni, operation); + } else { + if (interfacesSet.size() > 1) { + programInterfacesSet(interfacesSet, operation); + } + } + } else if (operation == Objective.Operation.REMOVE) { + if (routerInfFlagOfTenant.get(tenantId) != null) { + applyEastWestL3Flows(host, l3vni, operation); + } + } + } + // L3 external and internal network access to each other + FloatingIp floatingIp = null; + Iterable floatingIps = floatingIpService.getFloatingIps(); + Set floatingIpSet = Sets.newHashSet(floatingIps).stream() + .filter(f -> f.tenantId().equals(tenantId)) + .collect(Collectors.toSet()); + for (FloatingIp f : floatingIpSet) { + IpAddress fixedIp = f.fixedIp(); + if (fixedIp.equals(hostIp)) { + floatingIp = f; + break; + } + } + if (floatingIp != null) { + VirtualPort fipPort = virtualPortService + .getPort(floatingIp.networkId(), floatingIp.floatingIp()); + if (fipPort == null) { + fipPort = VtnData.getPort(vPortStore, floatingIp.networkId(), + floatingIp.floatingIp()); + } + applyNorthSouthL3Flows(deviceId, host, port, fipPort, floatingIp, + l3vni, exPort, operation); + } + } } diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java index b548938b..ebb9ac3b 100644 --- a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java +++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java @@ -17,10 +17,13 @@ package org.onosproject.vtn.table; import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; + import org.onosproject.net.DeviceId; +import org.onosproject.net.driver.DriverHandler; import org.onosproject.net.flowobjective.Objective; import org.onosproject.vtnrsc.SegmentationId; + /** * ArpService interface providing the rules in ARP table which is Table(10). */ @@ -32,13 +35,14 @@ public interface ArpService { * Action: set arp_operation, move arp_eth_src to arp_eth_dst, set arp_eth_src, * move arp_ip_src to arp_ip_dst, set arp_ip_src, set output port. * + * @param hander DriverHandler * @param deviceId Device Id * @param dstIP destination ip * @param matchVni the vni of the source network (l2vni) * @param dstMac destination mac * @param type the operation type of the flow rules */ - void programArpRules(DeviceId deviceId, IpAddress dstIP, + void programArpRules(DriverHandler hander, DeviceId deviceId, IpAddress dstIP, SegmentationId matchVni, MacAddress dstMac, Objective.Operation type); } diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ArpServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ArpServiceImpl.java new file mode 100644 index 00000000..574d15a7 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ArpServiceImpl.java @@ -0,0 +1,113 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtn.table.impl; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +import org.onlab.osgi.DefaultServiceDirectory; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.packet.EthType.EtherType; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.behaviour.ExtensionTreatmentResolver; +import org.onosproject.net.driver.DriverHandler; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; +import org.onosproject.net.flowobjective.DefaultForwardingObjective; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.ForwardingObjective.Flag; +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.flowobjective.Objective.Operation; +import org.onosproject.vtn.table.ArpService; +import org.onosproject.vtnrsc.SegmentationId; +import org.slf4j.Logger; + +/** + * ArpTable class providing the rules in ARP table. + */ +public class ArpServiceImpl implements ArpService { + private final Logger log = getLogger(getClass()); + + private static final int ARP_PRIORITY = 0xffff; + private static final short ARP_RESPONSE = 0x2; + private static final EtherType ARP_TYPE = EtherType.ARP; + + private final FlowObjectiveService flowObjectiveService; + private final ApplicationId appId; + + /** + * Construct a ArpServiceImpl object. + * + * @param appId the application id of vtn + */ + public ArpServiceImpl(ApplicationId appId) { + this.appId = checkNotNull(appId, "ApplicationId can not be null"); + ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class); + } + + @Override + public void programArpRules(DriverHandler hander, DeviceId deviceId, + IpAddress dstIP, SegmentationId srcVni, + MacAddress dstMac, Operation type) { + TrafficSelector selector = DefaultTrafficSelector.builder() + .matchEthType(ARP_TYPE.ethType().toShort()) + .matchArpTpa(Ip4Address.valueOf(dstIP.toString())) + .matchTunnelId(Long.parseLong(srcVni.segmentationId())).build(); + + ExtensionTreatmentResolver resolver = hander + .behaviour(ExtensionTreatmentResolver.class); + ExtensionTreatment ethSrcToDst = resolver + .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ETH_SRC_TO_DST.type()); + ExtensionTreatment arpShaToTha = resolver + .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ARP_SHA_TO_THA.type()); + ExtensionTreatment arpSpaToTpa = resolver + .getExtensionInstruction(ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ARP_SPA_TO_TPA.type()); + TrafficTreatment treatment = DefaultTrafficTreatment.builder() + .extension(ethSrcToDst, deviceId) + .setEthSrc(dstMac).setArpOp(ARP_RESPONSE) + .extension(arpShaToTha, deviceId) + .extension(arpSpaToTpa, deviceId) + .setArpSha(dstMac).setArpSpa(dstIP) + .setOutput(PortNumber.IN_PORT).build(); + + ForwardingObjective.Builder objective = DefaultForwardingObjective + .builder().withTreatment(treatment).withSelector(selector) + .fromApp(appId).withFlag(Flag.SPECIFIC) + .withPriority(ARP_PRIORITY); + + if (type.equals(Objective.Operation.ADD)) { + log.debug("PrivateArpRules-->ADD"); + flowObjectiveService.forward(deviceId, objective.add()); + } else { + log.debug("PrivateArpRules-->REMOVE"); + flowObjectiveService.forward(deviceId, objective.remove()); + } + } +} diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java index a8562e7f..cca905c2 100644 --- a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java +++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java @@ -17,12 +17,20 @@ package org.onosproject.vtn.util; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.onlab.packet.IpAddress; import org.onosproject.net.AnnotationKeys; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; +import org.onosproject.store.service.EventuallyConsistentMap; +import org.onosproject.vtnrsc.FixedIp; +import org.onosproject.vtnrsc.TenantNetworkId; +import org.onosproject.vtnrsc.VirtualPort; +import org.onosproject.vtnrsc.VirtualPortId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,4 +102,78 @@ public final class VtnData { return localTunnelPorts; } + /** + * Get VirtualPort. + * + * @param vPortStore EventuallyConsistentMap of VirtualPort + * @param vPortId VirtualPortId of the VirtualPort + * @return VirtualPort + */ + public static VirtualPort getPort(EventuallyConsistentMap vPortStore, + VirtualPortId vPortId) { + if (vPortStore != null) { + return vPortStore.get(vPortId); + } + return null; + } + + /** + * Get VirtualPort. + * + * @param vPortStore EventuallyConsistentMap of VirtualPort + * @param fixedIP FixedIp of the VirtualPort + * @return VirtualPort + */ + public static VirtualPort getPort(EventuallyConsistentMap vPortStore, + FixedIp fixedIP) { + if (vPortStore != null) { + List vPorts = new ArrayList<>(); + vPortStore.values().stream().forEach(p -> { + Iterator fixedIps = p.fixedIps().iterator(); + while (fixedIps.hasNext()) { + if (fixedIps.next().equals(fixedIP)) { + vPorts.add(p); + break; + } + } + }); + if (vPorts.size() == 0) { + return null; + } + return vPorts.get(0); + } + return null; + } + + /** + * Get VirtualPort. + * + * @param vPortStore EventuallyConsistentMap of VirtualPort + * @param networkId TenantNetworkId of the VirtualPort + * @param ip IpAddress of the VirtualPort + * @return VirtualPort + */ + public static VirtualPort getPort(EventuallyConsistentMap vPortStore, + TenantNetworkId networkId, IpAddress ip) { + if (vPortStore != null) { + List vPorts = new ArrayList<>(); + vPortStore.values().stream() + .filter(p -> p.networkId().equals(networkId)) + .forEach(p -> { + Iterator fixedIps = p.fixedIps().iterator(); + while (fixedIps.hasNext()) { + if (fixedIps.next().ip().equals(ip)) { + vPorts.add(p); + break; + } + } + }); + if (vPorts.size() == 0) { + return null; + } + return vPorts.get(0); + } + return null; + } + } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/ClassifierService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/ClassifierService.java new file mode 100644 index 00000000..a15da3ef --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/ClassifierService.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.classifier; + +import org.onosproject.net.DeviceId; + +/** + * Provides Services for Classifier. + */ +public interface ClassifierService { + + /** + * Get Classifier devices for sfc. + * + * @return list of device id's for classifiers + */ + Iterable getClassifiers(); + + /** + * Add Classifier device for sfc. + */ + void addClassifier(DeviceId deviceId); + + /** + * Remove Classifier device for sfc. + */ + void removeClassifier(DeviceId deviceId); +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/ClassifierManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/ClassifierManager.java new file mode 100644 index 00000000..a12d6221 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/ClassifierManager.java @@ -0,0 +1,78 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.classifier.impl; + +import static org.slf4j.LoggerFactory.getLogger; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.net.DeviceId; +import org.onosproject.store.serializers.KryoNamespaces; +import org.onosproject.store.service.DistributedSet; +import org.onosproject.store.service.Serializer; +import org.onosproject.store.service.StorageService; +import org.onosproject.vtnrsc.classifier.ClassifierService; +import org.slf4j.Logger; + +import com.google.common.collect.ImmutableList; + +/** + * Provides implementation of the Classifier Service. + */ +@Component(immediate = true) +@Service +public class ClassifierManager implements ClassifierService { + + private final Logger log = getLogger(ClassifierManager.class); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + private DistributedSet classifierList; + + @Activate + protected void activate() { + classifierList = storageService.setBuilder() + .withName("classifier") + .withSerializer(Serializer.using(KryoNamespaces.API)) + .build(); + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + log.info("Stopped"); + } + + @Override + public void addClassifier(DeviceId deviceId) { + classifierList.add(deviceId); + } + + @Override + public Iterable getClassifiers() { + return ImmutableList.copyOf(classifierList); + } + + @Override + public void removeClassifier(DeviceId deviceId) { + classifierList.remove(deviceId); + } +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/package-info.java new file mode 100644 index 00000000..dc72e806 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Provides implementation of the Classifier service. + */ +package org.onosproject.vtnrsc.classifier.impl; diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/package-info.java new file mode 100644 index 00000000..56976d96 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/classifier/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Service for interacting with Classifier of SFC. + */ +package org.onosproject.vtnrsc.classifier; diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetCreateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetCreateCommand.java index 56236408..de8cfe53 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetCreateCommand.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetCreateCommand.java @@ -98,7 +98,7 @@ public class SubnetCreateCommand extends AbstractShellCommand { protected void execute() { SubnetService service = get(SubnetService.class); if (id == null || networkId == null || tenantId == null) { - print(null, "id,networkId,tenantId can not be null"); + print("id,networkId,tenantId can not be null"); return; } Subnet subnet = new DefaultSubnet(SubnetId.subnetId(id), subnetName, diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetUpdateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetUpdateCommand.java index b0578a1e..c76ca5b2 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetUpdateCommand.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/subnet/SubnetUpdateCommand.java @@ -98,7 +98,7 @@ public class SubnetUpdateCommand extends AbstractShellCommand { protected void execute() { SubnetService service = get(SubnetService.class); if (id == null || networkId == null || tenantId == null) { - print(null, "id,networkId,tenantId can not be null"); + print("id,networkId,tenantId can not be null"); return; } Subnet subnet = new DefaultSubnet(SubnetId.subnetId(id), subnetName, diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java index 3bac158b..ce3faae7 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java @@ -51,7 +51,55 @@ public class VtnRscEvent /** * Signifies that router interface has remove. */ - ROUTER_INTERFACE_DELETE + ROUTER_INTERFACE_DELETE, + /** + * Signifies that port-pair has add. + */ + PORT_PAIR_PUT, + /** + * Signifies that port-pair has remove. + */ + PORT_PAIR_DELETE, + /** + * Signifies that port-pair has update. + */ + PORT_PAIR_UPDATE, + /** + * Signifies that port-pair-group has add. + */ + PORT_PAIR_GROUP_PUT, + /** + * Signifies that port-pair-group has remove. + */ + PORT_PAIR_GROUP_DELETE, + /** + * Signifies that port-pair-group has update. + */ + PORT_PAIR_GROUP_UPDATE, + /** + * Signifies that flow-classifier has add. + */ + FLOW_CLASSIFIER_PUT, + /** + * Signifies that flow-classifier has remove. + */ + FLOW_CLASSIFIER_DELETE, + /** + * Signifies that flow-classifier has update. + */ + FLOW_CLASSIFIER_UPDATE, + /** + * Signifies that port-chain has add. + */ + PORT_CHAIN_PUT, + /** + * Signifies that port-chain has remove. + */ + PORT_CHAIN_DELETE, + /** + * Signifies that port-chain has update. + */ + PORT_CHAIN_UPDATE } /** diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java index 63dcaeee..112c6411 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java @@ -20,6 +20,10 @@ import java.util.Objects; import org.onosproject.vtnrsc.FloatingIp; import org.onosproject.vtnrsc.Router; import org.onosproject.vtnrsc.RouterInterface; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.PortChain; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; @@ -31,6 +35,10 @@ public class VtnRscEventFeedback { private final FloatingIp floaingtIp; private final Router router; private final RouterInterface routerInterface; + private final PortPair portPair; + private final PortPairGroup portPairGroup; + private final FlowClassifier flowClassifier; + private final PortChain portChain; /** * Creates VtnRscEventFeedback object. @@ -41,6 +49,10 @@ public class VtnRscEventFeedback { this.floaingtIp = checkNotNull(floatingIp, "floaintIp cannot be null"); this.router = null; this.routerInterface = null; + this.portPair = null; + this.portPairGroup = null; + this.flowClassifier = null; + this.portChain = null; } /** @@ -52,6 +64,10 @@ public class VtnRscEventFeedback { this.floaingtIp = null; this.router = checkNotNull(router, "router cannot be null"); this.routerInterface = null; + this.portPair = null; + this.portPairGroup = null; + this.flowClassifier = null; + this.portChain = null; } /** @@ -64,6 +80,74 @@ public class VtnRscEventFeedback { this.router = null; this.routerInterface = checkNotNull(routerInterface, "routerInterface cannot be null"); + this.portPair = null; + this.portPairGroup = null; + this.flowClassifier = null; + this.portChain = null; + } + + /** + * Creates VtnRscEventFeedback object. + * + * @param portPair the Port-Pair + */ + public VtnRscEventFeedback(PortPair portPair) { + this.floaingtIp = null; + this.router = null; + this.routerInterface = null; + this.portPair = checkNotNull(portPair, + "Port-Pair cannot be null"); + this.portPairGroup = null; + this.flowClassifier = null; + this.portChain = null; + } + + /** + * Creates VtnRscEventFeedback object. + * + * @param portPairGroup the Port-Pair-Group + */ + public VtnRscEventFeedback(PortPairGroup portPairGroup) { + this.floaingtIp = null; + this.router = null; + this.routerInterface = null; + this.portPair = null; + this.portPairGroup = checkNotNull(portPairGroup, + "Port-Pair-Group cannot be null"); + this.flowClassifier = null; + this.portChain = null; + } + + /** + * Creates VtnRscEventFeedback object. + * + * @param flowClassifier the Flow-Classifier + */ + public VtnRscEventFeedback(FlowClassifier flowClassifier) { + this.floaingtIp = null; + this.router = null; + this.routerInterface = null; + this.portPair = null; + this.portPairGroup = null; + this.flowClassifier = checkNotNull(flowClassifier, + "Flow-Classifier cannot be null"); + this.portChain = null; + } + + /** + * Creates VtnRscEventFeedback object. + * + * @param portChain the Port-Chain + */ + public VtnRscEventFeedback(PortChain portChain) { + this.floaingtIp = null; + this.router = null; + this.routerInterface = null; + this.portPair = null; + this.portPairGroup = null; + this.flowClassifier = null; + this.portChain = checkNotNull(portChain, + "Port-Chain cannot be null"); } /** @@ -93,9 +177,46 @@ public class VtnRscEventFeedback { return routerInterface; } + /** + * Returns Port-Pair. + * + * @return portPair the Port-Pair + */ + public PortPair portPair() { + return portPair; + } + + /** + * Returns Port-Pair-Group. + * + * @return portPairGroup the Port-Pair-Group + */ + public PortPairGroup portPairGroup() { + return portPairGroup; + } + + /** + * Returns Flow-Classifier. + * + * @return flowClassifier the Flow-Classifier + */ + public FlowClassifier flowClassifier() { + return flowClassifier; + } + + /** + * Returns Port-Chain. + * + * @return portChain the Port-Chain + */ + public PortChain portChain() { + return portChain; + } + @Override public int hashCode() { - return Objects.hash(floaingtIp, router, routerInterface); + return Objects.hash(floaingtIp, router, routerInterface, portPair, + portPairGroup, flowClassifier, portChain); } @Override @@ -107,7 +228,11 @@ public class VtnRscEventFeedback { final VtnRscEventFeedback that = (VtnRscEventFeedback) obj; return Objects.equals(this.floaingtIp, that.floaingtIp) && Objects.equals(this.router, that.router) - && Objects.equals(this.routerInterface, that.routerInterface); + && Objects.equals(this.routerInterface, that.routerInterface) + && Objects.equals(this.portPair, that.portPair) + && Objects.equals(this.portPairGroup, that.portPairGroup) + && Objects.equals(this.flowClassifier, that.flowClassifier) + && Objects.equals(this.portChain, that.portChain); } return false; } @@ -118,6 +243,10 @@ public class VtnRscEventFeedback { .add("router", router) .add("floaingtIp", floaingtIp) .add("routerInterface", routerInterface) + .add("portPair", portPair) + .add("portPairGroup", portPairGroup) + .add("flowClassifier", flowClassifier) + .add("portChain", portChain) .toString(); } } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java index 9f944da1..ce9bb21f 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java @@ -202,27 +202,24 @@ public class FloatingIpManager implements FloatingIpService { public boolean updateFloatingIps(Collection floatingIps) { checkNotNull(floatingIps, FLOATINGIP_NOT_NULL); boolean result = true; - if (floatingIps != null) { - for (FloatingIp floatingIp : floatingIps) { - verifyFloatingIpData(floatingIp); - if (floatingIp.portId() != null) { - floatingIpStore.put(floatingIp.id(), floatingIp); - if (!floatingIpStore.containsKey(floatingIp.id())) { + for (FloatingIp floatingIp : floatingIps) { + verifyFloatingIpData(floatingIp); + if (floatingIp.portId() != null) { + floatingIpStore.put(floatingIp.id(), floatingIp); + if (!floatingIpStore.containsKey(floatingIp.id())) { + log.debug("The floating Ip is updated failed whose identifier is {}", + floatingIp.id().toString()); + result = false; + } + } else { + FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id()); + if (oldFloatingIp != null) { + floatingIpStore.remove(floatingIp.id(), oldFloatingIp); + if (floatingIpStore.containsKey(floatingIp.id())) { log.debug("The floating Ip is updated failed whose identifier is {}", floatingIp.id().toString()); result = false; } - } else { - FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp - .id()); - if (oldFloatingIp != null) { - floatingIpStore.remove(floatingIp.id(), oldFloatingIp); - if (floatingIpStore.containsKey(floatingIp.id())) { - log.debug("The floating Ip is updated failed whose identifier is {}", - floatingIp.id().toString()); - result = false; - } - } } } } @@ -233,21 +230,19 @@ public class FloatingIpManager implements FloatingIpService { public boolean removeFloatingIps(Collection floatingIpIds) { checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL); boolean result = true; - if (floatingIpIds != null) { - for (FloatingIpId floatingIpId : floatingIpIds) { - if (!floatingIpStore.containsKey(floatingIpId)) { - log.debug("The floatingIp is not exist whose identifier is {}", - floatingIpId.toString()); - throw new IllegalArgumentException( - "FloatingIP ID doesn't exist"); - } - FloatingIp floatingIp = floatingIpStore.get(floatingIpId); - floatingIpStore.remove(floatingIpId, floatingIp); - if (floatingIpStore.containsKey(floatingIpId)) { - log.debug("The floating Ip is deleted failed whose identifier is {}", - floatingIpId.toString()); - result = false; - } + for (FloatingIpId floatingIpId : floatingIpIds) { + if (!floatingIpStore.containsKey(floatingIpId)) { + log.debug("The floatingIp is not exist whose identifier is {}", + floatingIpId.toString()); + throw new IllegalArgumentException( + "FloatingIP ID doesn't exist"); + } + FloatingIp floatingIp = floatingIpStore.get(floatingIpId); + floatingIpStore.remove(floatingIpId, floatingIp); + if (floatingIpStore.containsKey(floatingIpId)) { + log.debug("The floating Ip is deleted failed whose identifier is {}", + floatingIpId.toString()); + result = false; } } return result; diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierEvent.java new file mode 100644 index 00000000..d81ab48a --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierEvent.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.flowclassifier; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.vtnrsc.FlowClassifier; + +/** + * Describes network Flow-Classifier event. + */ +public class FlowClassifierEvent extends AbstractEvent { + /** + * Type of flow-classifier events. + */ + public enum Type { + /** + * Signifies that flow-classifier has been created. + */ + FLOW_CLASSIFIER_PUT, + /** + * Signifies that flow-classifier has been deleted. + */ + FLOW_CLASSIFIER_DELETE, + /** + * Signifies that flow-classifier has been updated. + */ + FLOW_CLASSIFIER_UPDATE + } + + /** + * Creates an event of a given type and for the specified Flow-Classifier. + * + * @param type Flow-Classifier event type + * @param flowClassifier Flow-Classifier subject + */ + public FlowClassifierEvent(Type type, FlowClassifier flowClassifier) { + super(type, flowClassifier); + } + + /** + * Creates an event of a given type and for the specified Flow-Classifier. + * + * @param type Flow-Classifier event type + * @param flowClassifier Flow-Classifier subject + * @param time occurrence time + */ + public FlowClassifierEvent(Type type, FlowClassifier flowClassifier, long time) { + super(type, flowClassifier, time); + } +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierListener.java new file mode 100644 index 00000000..3c0409ad --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierListener.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.flowclassifier; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of Flow-Classifier related events. + */ +public interface FlowClassifierListener extends EventListener { + +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java index c5911ff2..48438846 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java @@ -15,13 +15,14 @@ */ package org.onosproject.vtnrsc.flowclassifier; +import org.onosproject.event.ListenerService; import org.onosproject.vtnrsc.FlowClassifier; import org.onosproject.vtnrsc.FlowClassifierId; /** * Provides Services for Flow Classifier. */ -public interface FlowClassifierService { +public interface FlowClassifierService extends ListenerService { /** * Check whether Flow Classifier is present based on given Flow Classifier diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java index 4a60cd34..18f63b30 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java @@ -15,6 +15,9 @@ */ package org.onosproject.vtnrsc.flowclassifier.impl; +import static org.slf4j.LoggerFactory.getLogger; +import static com.google.common.base.Preconditions.checkNotNull; + import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -22,6 +25,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.util.KryoNamespace; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.EventuallyConsistentMap; import org.onosproject.store.service.MultiValuedTimestamp; @@ -29,12 +33,11 @@ import org.onosproject.store.service.StorageService; import org.onosproject.store.service.WallClockTimestamp; import org.onosproject.vtnrsc.FlowClassifierId; import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierEvent; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierListener; import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; import org.slf4j.Logger; -import static org.slf4j.LoggerFactory.getLogger; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.collect.ImmutableList; /** @@ -42,14 +45,17 @@ import com.google.common.collect.ImmutableList; */ @Component(immediate = true) @Service -public class FlowClassifierManager implements FlowClassifierService { - - private final Logger log = getLogger(FlowClassifierManager.class); +public class FlowClassifierManager extends AbstractListenerManager + implements FlowClassifierService { private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow Classifier cannot be null"; private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow Classifier Id cannot be null"; + private static final String LISTENER_NOT_NULL = "Listener cannot be null"; + + private final Logger log = getLogger(FlowClassifierManager.class); private EventuallyConsistentMap flowClassifierStore; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected StorageService storageService; diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainEvent.java new file mode 100644 index 00000000..44a4e8ed --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainEvent.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portchain; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.vtnrsc.PortChain; + +/** + * Describes network Port-Chain event. + */ +public class PortChainEvent extends AbstractEvent { + /** + * Type of port-chain events. + */ + public enum Type { + /** + * Signifies that port-chain has been created. + */ + PORT_CHAIN_PUT, + /** + * Signifies that port-chain has been deleted. + */ + PORT_CHAIN_DELETE, + /** + * Signifies that port-chain has been updated. + */ + PORT_CHAIN_UPDATE + } + + /** + * Creates an event of a given type and for the specified Port-Chain. + * + * @param type Port-Chain event type + * @param portChain Port-Chain subject + */ + public PortChainEvent(Type type, PortChain portChain) { + super(type, portChain); + } + + /** + * Creates an event of a given type and for the specified Port-Chain. + * + * @param type Port-Chain event type + * @param portChain Port-Chain subject + * @param time occurrence time + */ + public PortChainEvent(Type type, PortChain portChain, long time) { + super(type, portChain, time); + } +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainListener.java new file mode 100644 index 00000000..27a498b5 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainListener.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portchain; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of Port-Chain related events. + */ +public interface PortChainListener extends EventListener { + +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java index b4ff917e..5b08262b 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java @@ -15,13 +15,14 @@ */ package org.onosproject.vtnrsc.portchain; +import org.onosproject.event.ListenerService; import org.onosproject.vtnrsc.PortChain; import org.onosproject.vtnrsc.PortChainId; /** * Service for interacting with the inventory of port chains. */ -public interface PortChainService { +public interface PortChainService extends ListenerService { /** * Returns if the port chain is existed. diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java index 5201a2ca..0062db48 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java @@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.util.KryoNamespace; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.EventuallyConsistentMap; import org.onosproject.store.service.MultiValuedTimestamp; @@ -34,6 +35,8 @@ import org.onosproject.store.service.StorageService; import org.onosproject.store.service.WallClockTimestamp; import org.onosproject.vtnrsc.PortChain; import org.onosproject.vtnrsc.PortChainId; +import org.onosproject.vtnrsc.portchain.PortChainEvent; +import org.onosproject.vtnrsc.portchain.PortChainListener; import org.onosproject.vtnrsc.portchain.PortChainService; import org.slf4j.Logger; @@ -42,13 +45,14 @@ import org.slf4j.Logger; */ @Component(immediate = true) @Service -public class PortChainManager implements PortChainService { - - private final Logger log = getLogger(getClass()); +public class PortChainManager extends AbstractListenerManager implements + PortChainService { private static final String PORT_CHAIN_ID_NULL = "PortChain ID cannot be null"; private static final String PORT_CHAIN_NULL = "PortChain cannot be null"; + private static final String LISTENER_NOT_NULL = "Listener cannot be null"; + private final Logger log = getLogger(getClass()); private EventuallyConsistentMap portChainStore; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairEvent.java new file mode 100644 index 00000000..31ecc737 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairEvent.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portpair; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.vtnrsc.PortPair; + +/** + * Describes network Port-Pair event. + */ +public class PortPairEvent extends AbstractEvent { + /** + * Type of port-pair events. + */ + public enum Type { + /** + * Signifies that port-pair has been created. + */ + PORT_PAIR_PUT, + /** + * Signifies that port-pair has been deleted. + */ + PORT_PAIR_DELETE, + /** + * Signifies that port-pair has been updated. + */ + PORT_PAIR_UPDATE + } + + /** + * Creates an event of a given type and for the specified Port-Pair. + * + * @param type Port-Pair event type + * @param portPair Port-Pair subject + */ + public PortPairEvent(Type type, PortPair portPair) { + super(type, portPair); + } + + /** + * Creates an event of a given type and for the specified Port-Pair. + * + * @param type Port-Pair event type + * @param portPair Port-Pair subject + * @param time occurrence time + */ + public PortPairEvent(Type type, PortPair portPair, long time) { + super(type, portPair, time); + } +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairListener.java new file mode 100644 index 00000000..3bdb9e4e --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairListener.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portpair; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of Port-Pair related events. + */ +public interface PortPairListener extends EventListener { + +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java index f99cc2cf..e98a6a20 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java @@ -77,4 +77,18 @@ public interface PortPairService { * @return true if the give port pair is deleted successfully. */ boolean removePortPair(PortPairId portPairId); + + /** + * Adds the specified listener to Port-Pair manager. + * + * @param listener Port-Pair listener + */ + void addListener(PortPairListener listener); + + /** + * Removes the specified listener to Port-Pair manager. + * + * @param listener Port-Pair listener + */ + void removeListener(PortPairListener listener); } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java index 93c8782a..ad6fd4bb 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static org.slf4j.LoggerFactory.getLogger; import java.util.Collections; +import java.util.Set; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -34,9 +35,12 @@ import org.onosproject.store.service.StorageService; import org.onosproject.store.service.WallClockTimestamp; import org.onosproject.vtnrsc.PortPair; import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.portpair.PortPairListener; import org.onosproject.vtnrsc.portpair.PortPairService; import org.slf4j.Logger; +import com.google.common.collect.Sets; + /** * Provides implementation of the portPairService. */ @@ -44,11 +48,12 @@ import org.slf4j.Logger; @Service public class PortPairManager implements PortPairService { - private final Logger log = getLogger(getClass()); - private static final String PORT_PAIR_ID_NULL = "PortPair ID cannot be null"; private static final String PORT_PAIR_NULL = "PortPair cannot be null"; + private static final String LISTENER_NOT_NULL = "Listener cannot be null"; + private final Logger log = getLogger(getClass()); + private final Set listeners = Sets.newCopyOnWriteArraySet(); private EventuallyConsistentMap portPairStore; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -73,6 +78,7 @@ public class PortPairManager implements PortPairService { @Deactivate public void deactivate() { portPairStore.destroy(); + listeners.clear(); log.info("Stopped"); } @@ -143,4 +149,16 @@ public class PortPairManager implements PortPairService { } return true; } + + @Override + public void addListener(PortPairListener listener) { + checkNotNull(listener, LISTENER_NOT_NULL); + listeners.add(listener); + } + + @Override + public void removeListener(PortPairListener listener) { + checkNotNull(listener, LISTENER_NOT_NULL); + listeners.remove(listener); + } } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupEvent.java new file mode 100644 index 00000000..88e1d7fb --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupEvent.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portpairgroup; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.vtnrsc.PortPairGroup; + +/** + * Describes network Port-Pair-Group event. + */ +public class PortPairGroupEvent extends AbstractEvent { + /** + * Type of port-pair-group events. + */ + public enum Type { + /** + * Signifies that port-pair-group has been created. + */ + PORT_PAIR_GROUP_PUT, + /** + * Signifies that port-pair-group has been deleted. + */ + PORT_PAIR_GROUP_DELETE, + /** + * Signifies that port-pair-group has been updated. + */ + PORT_PAIR_GROUP_UPDATE + } + + /** + * Creates an event of a given type and for the specified Port-Pair-Group. + * + * @param type Port-Pair-Group event type + * @param portPairGroup Port-Pair-Group subject + */ + public PortPairGroupEvent(Type type, PortPairGroup portPairGroup) { + super(type, portPairGroup); + } + + /** + * Creates an event of a given type and for the specified Port-Pair-Group. + * + * @param type Port-Pair-Group event type + * @param portPairGroup Port-Pair-Group subject + * @param time occurrence time + */ + public PortPairGroupEvent(Type type, PortPairGroup portPairGroup, long time) { + super(type, portPairGroup, time); + } +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupListener.java new file mode 100644 index 00000000..637149e3 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupListener.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnrsc.portpairgroup; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of Port-Pair-Group related events. + */ +public interface PortPairGroupListener extends EventListener { + +} diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java index 77f483fc..efee0eb9 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java @@ -77,4 +77,18 @@ public interface PortPairGroupService { * @return true if the give port pair group is deleted successfully. */ boolean removePortPairGroup(PortPairGroupId portPairGroupId); + + /** + * Adds the specified listener to Port-Pair-Group manager. + * + * @param listener Port-Pair-Group listener + */ + void addListener(PortPairGroupListener listener); + + /** + * Removes the specified listener to Port-Pair-Group manager. + * + * @param listener Port-Pair-Group listener + */ + void removeListener(PortPairGroupListener listener); } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java index 55fb4e43..5f80ef64 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static org.slf4j.LoggerFactory.getLogger; import java.util.Collections; +import java.util.Set; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -34,9 +35,12 @@ import org.onosproject.store.service.StorageService; import org.onosproject.store.service.WallClockTimestamp; import org.onosproject.vtnrsc.PortPairGroup; import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupListener; import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; import org.slf4j.Logger; +import com.google.common.collect.Sets; + /** * Provides implementation of the portPairGroupService. */ @@ -44,11 +48,12 @@ import org.slf4j.Logger; @Service public class PortPairGroupManager implements PortPairGroupService { - private final Logger log = getLogger(getClass()); - private static final String PORT_PAIR_GROUP_ID_NULL = "PortPairGroup ID cannot be null"; private static final String PORT_PAIR_GROUP_NULL = "PortPairGroup cannot be null"; + private static final String LISTENER_NOT_NULL = "Listener cannot be null"; + private final Logger log = getLogger(getClass()); + private final Set listeners = Sets.newCopyOnWriteArraySet(); private EventuallyConsistentMap portPairGroupStore; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -73,6 +78,7 @@ public class PortPairGroupManager implements PortPairGroupService { @Deactivate public void deactivate() { portPairGroupStore.destroy(); + listeners.clear(); log.info("Stopped"); } @@ -143,4 +149,16 @@ public class PortPairGroupManager implements PortPairGroupService { } return true; } + + @Override + public void addListener(PortPairGroupListener listener) { + checkNotNull(listener, LISTENER_NOT_NULL); + listeners.add(listener); + } + + @Override + public void removeListener(PortPairGroupListener listener) { + checkNotNull(listener, LISTENER_NOT_NULL); + listeners.remove(listener); + } } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java index 21161ba5..bc9f4e68 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java @@ -18,32 +18,20 @@ package org.onosproject.vtnrsc.service; import java.util.Iterator; import org.onlab.packet.MacAddress; +import org.onosproject.event.ListenerService; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.HostId; import org.onosproject.vtnrsc.SegmentationId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.event.VtnRscEvent; import org.onosproject.vtnrsc.event.VtnRscListener; /** * Service for interacting with the inventory of Vtn resource. */ -public interface VtnRscService { - /** - * Adds the specified listener. - * - * @param listener VtnRsc listener - */ - void addListener(VtnRscListener listener); - - /** - * Removes the specified listener. - * - * @param listener VtnRsc listener - */ - void removeListener(VtnRscListener listener); - +public interface VtnRscService extends ListenerService { /** * Returns the SegmentationId of tenant. * diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java index ec9ca3ef..b21ad200 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java @@ -32,6 +32,7 @@ import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; import org.onlab.util.KryoNamespace; import org.onosproject.core.CoreService; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Host; @@ -54,6 +55,11 @@ import org.onosproject.vtnrsc.SubnetId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.VirtualPort; import org.onosproject.vtnrsc.VirtualPortId; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.PortChain; import org.onosproject.vtnrsc.event.VtnRscEvent; import org.onosproject.vtnrsc.event.VtnRscEventFeedback; import org.onosproject.vtnrsc.event.VtnRscListener; @@ -70,16 +76,27 @@ import org.onosproject.vtnrsc.service.VtnRscService; import org.onosproject.vtnrsc.subnet.SubnetService; import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService; import org.onosproject.vtnrsc.virtualport.VirtualPortService; +import org.onosproject.vtnrsc.portpair.PortPairEvent; +import org.onosproject.vtnrsc.portpair.PortPairListener; +import org.onosproject.vtnrsc.portpair.PortPairService; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupEvent; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupListener; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierEvent; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierListener; +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; +import org.onosproject.vtnrsc.portchain.PortChainEvent; +import org.onosproject.vtnrsc.portchain.PortChainListener; +import org.onosproject.vtnrsc.portchain.PortChainService; import org.slf4j.Logger; -import com.google.common.collect.Sets; - /** * Provides implementation of the VtnRsc service. */ @Component(immediate = true) @Service -public class VtnRscManager implements VtnRscService { +public class VtnRscManager extends AbstractListenerManager + implements VtnRscService { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected CoreService coreService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -88,11 +105,14 @@ public class VtnRscManager implements VtnRscService { protected LogicalClockService clockService; private final Logger log = getLogger(getClass()); - private final Set listeners = Sets.newCopyOnWriteArraySet(); private HostListener hostListener = new InnerHostListener(); private FloatingIpListener floatingIpListener = new InnerFloatingIpListener(); private RouterListener routerListener = new InnerRouterListener(); private RouterInterfaceListener routerInterfaceListener = new InnerRouterInterfaceListener(); + private PortPairListener portPairListener = new InnerPortPairListener(); + private PortPairGroupListener portPairGroupListener = new InnerPortPairGroupListener(); + private FlowClassifierListener flowClassifierListener = new InnerFlowClassifierListener(); + private PortChainListener portChainListener = new InnerPortChainListener(); private EventuallyConsistentMap l3vniMap; private EventuallyConsistentMap> classifierOvsMap; @@ -125,6 +145,14 @@ public class VtnRscManager implements VtnRscService { protected TenantNetworkService tenantNetworkService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortPairService portPairService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortPairGroupService portPairGroupService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FlowClassifierService flowClassifierService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PortChainService portChainService; @Activate public void activate() { @@ -132,6 +160,10 @@ public class VtnRscManager implements VtnRscService { floatingIpService.addListener(floatingIpListener); routerService.addListener(routerListener); routerInterfaceService.addListener(routerInterfaceListener); + portPairService.addListener(portPairListener); + portPairGroupService.addListener(portPairGroupListener); + flowClassifierService.addListener(flowClassifierListener); + portChainService.addListener(portChainListener); KryoNamespace.Builder serializer = KryoNamespace.newBuilder() .register(KryoNamespaces.API) @@ -161,25 +193,17 @@ public class VtnRscManager implements VtnRscService { floatingIpService.removeListener(floatingIpListener); routerService.removeListener(routerListener); routerInterfaceService.removeListener(routerInterfaceListener); + portPairService.removeListener(portPairListener); + portPairGroupService.removeListener(portPairGroupListener); + flowClassifierService.removeListener(flowClassifierListener); + portChainService.removeListener(portChainListener); + l3vniMap.destroy(); classifierOvsMap.destroy(); sffOvsMap.destroy(); - listeners.clear(); log.info("Stopped"); } - @Override - public void addListener(VtnRscListener listener) { - checkNotNull(listener, LISTENER_NOT_NULL); - listeners.add(listener); - } - - @Override - public void removeListener(VtnRscListener listener) { - checkNotNull(listener, LISTENER_NOT_NULL); - listeners.add(listener); - } - @Override public SegmentationId getL3vni(TenantId tenantId) { checkNotNull(tenantId, "tenantId cannot be null"); @@ -282,6 +306,93 @@ public class VtnRscManager implements VtnRscService { } } + private class InnerPortPairListener implements PortPairListener { + + @Override + public void event(PortPairEvent event) { + checkNotNull(event, EVENT_NOT_NULL); + PortPair portPair = event.subject(); + if (PortPairEvent.Type.PORT_PAIR_PUT == event.type()) { + notifyListeners(new VtnRscEvent(VtnRscEvent.Type.PORT_PAIR_PUT, + new VtnRscEventFeedback(portPair))); + } else if (PortPairEvent.Type.PORT_PAIR_DELETE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_PAIR_DELETE, + new VtnRscEventFeedback(portPair))); + } else if (PortPairEvent.Type.PORT_PAIR_UPDATE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_PAIR_UPDATE, + new VtnRscEventFeedback(portPair))); + } + } + } + + private class InnerPortPairGroupListener implements PortPairGroupListener { + + @Override + public void event(PortPairGroupEvent event) { + checkNotNull(event, EVENT_NOT_NULL); + PortPairGroup portPairGroup = event.subject(); + if (PortPairGroupEvent.Type.PORT_PAIR_GROUP_PUT == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_PAIR_GROUP_PUT, + new VtnRscEventFeedback(portPairGroup))); + } else if (PortPairGroupEvent.Type.PORT_PAIR_GROUP_DELETE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_PAIR_GROUP_DELETE, + new VtnRscEventFeedback(portPairGroup))); + } else if (PortPairGroupEvent.Type.PORT_PAIR_GROUP_UPDATE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_PAIR_GROUP_UPDATE, + new VtnRscEventFeedback(portPairGroup))); + } + } + } + + private class InnerFlowClassifierListener implements FlowClassifierListener { + + @Override + public void event(FlowClassifierEvent event) { + checkNotNull(event, EVENT_NOT_NULL); + FlowClassifier flowClassifier = event.subject(); + if (FlowClassifierEvent.Type.FLOW_CLASSIFIER_PUT == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.FLOW_CLASSIFIER_PUT, + new VtnRscEventFeedback(flowClassifier))); + } else if (FlowClassifierEvent.Type.FLOW_CLASSIFIER_DELETE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.FLOW_CLASSIFIER_DELETE, + new VtnRscEventFeedback(flowClassifier))); + } else if (FlowClassifierEvent.Type.FLOW_CLASSIFIER_UPDATE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.FLOW_CLASSIFIER_UPDATE, + new VtnRscEventFeedback(flowClassifier))); + } + } + } + + private class InnerPortChainListener implements PortChainListener { + + @Override + public void event(PortChainEvent event) { + checkNotNull(event, EVENT_NOT_NULL); + PortChain portChain = event.subject(); + if (PortChainEvent.Type.PORT_CHAIN_PUT == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_CHAIN_PUT, + new VtnRscEventFeedback(portChain))); + } else if (PortChainEvent.Type.PORT_CHAIN_DELETE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_CHAIN_DELETE, + new VtnRscEventFeedback(portChain))); + } else if (PortChainEvent.Type.PORT_CHAIN_UPDATE == event.type()) { + notifyListeners(new VtnRscEvent( + VtnRscEvent.Type.PORT_CHAIN_UPDATE, + new VtnRscEventFeedback(portChain))); + } + } + } + @Override public Iterator getClassifierOfTenant(TenantId tenantId) { checkNotNull(tenantId, TENANTID_NOT_NULL); @@ -333,8 +444,7 @@ public class VtnRscManager implements VtnRscService { @Override public boolean isServiceFunction(VirtualPortId portId) { - // TODO Auto-generated method stub - return false; + return portPairService.exists(PortPairId.of(portId.portId())); } @Override @@ -343,7 +453,7 @@ public class VtnRscManager implements VtnRscService { VirtualPort vmPort = virtualPortService.getPort(portId); Set hostSet = hostService.getHostsByMac(vmPort.macAddress()); for (Host host : hostSet) { - if (host.annotations().value(IFACEID).equals(vmPort.portId())) { + if (host.annotations().value(IFACEID).equals(vmPort.portId().portId())) { return host.location().deviceId(); } } @@ -467,6 +577,6 @@ public class VtnRscManager implements VtnRscService { */ private void notifyListeners(VtnRscEvent event) { checkNotNull(event, EVENT_NOT_NULL); - listeners.forEach(listener -> listener.event(event)); + post(event); } } diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java index 0a3ea2cd..19548db8 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java @@ -17,6 +17,7 @@ package org.onosproject.vtnrsc.virtualport; import java.util.Collection; +import org.onlab.packet.IpAddress; import org.onosproject.net.DeviceId; import org.onosproject.vtnrsc.FixedIp; import org.onosproject.vtnrsc.TenantId; @@ -52,6 +53,15 @@ public interface VirtualPortService { */ VirtualPort getPort(FixedIp fixedIP); + /** + * Returns the virtualPort associated with the networkId and ip. + * + * @param networkId the TenantNetworkId identifier + * @param ip the ip identifier + * @return virtualPort. + */ + VirtualPort getPort(TenantNetworkId networkId, IpAddress ip); + /** * Returns the collection of the currently known virtualPort. * @return collection of VirtualPort. diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java index daec7839..9639e086 100644 --- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java +++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java @@ -72,6 +72,7 @@ public class VirtualPortManager implements VirtualPortService { private static final String NETWORKID_NOT_NULL = "NetworkId cannot be null"; private static final String DEVICEID_NOT_NULL = "DeviceId cannot be null"; private static final String FIXEDIP_NOT_NULL = "FixedIp cannot be null"; + private static final String IP_NOT_NULL = "Ip cannot be null"; protected Map vPortStore; protected ApplicationId appId; @@ -147,6 +148,27 @@ public class VirtualPortManager implements VirtualPortService { return vPorts.get(0); } + @Override + public VirtualPort getPort(TenantNetworkId networkId, IpAddress ip) { + checkNotNull(networkId, NETWORKID_NOT_NULL); + checkNotNull(ip, IP_NOT_NULL); + List vPorts = new ArrayList<>(); + vPortStore.values().stream().filter(p -> p.networkId().equals(networkId)) + .forEach(p -> { + Iterator fixedIps = p.fixedIps().iterator(); + while (fixedIps.hasNext()) { + if (fixedIps.next().ip().equals(ip)) { + vPorts.add(p); + break; + } + } + }); + if (vPorts.size() == 0) { + return null; + } + return vPorts.get(0); + } + @Override public Collection getPorts() { return Collections.unmodifiableCollection(vPortStore.values()); diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java index 08e37f96..4fd3fa48 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java @@ -36,12 +36,10 @@ import org.onosproject.rest.AbstractWebResource; import org.onosproject.vtnrsc.FlowClassifier; import org.onosproject.vtnrsc.FlowClassifierId; import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; -import org.onosproject.vtnweb.web.FlowClassifierCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -64,11 +62,11 @@ public class FlowClassifierWebResource extends AbstractWebResource { @Produces(MediaType.APPLICATION_JSON) public Response getFlowClassifiers() { Iterable flowClassifiers = get(FlowClassifierService.class).getFlowClassifiers(); - ObjectNode result = new ObjectMapper().createObjectNode(); + ObjectNode result = mapper().createObjectNode(); ArrayNode flowClassifierEntry = result.putArray("flow_classifiers"); if (flowClassifiers != null) { for (final FlowClassifier flowClassifier : flowClassifiers) { - flowClassifierEntry.add(new FlowClassifierCodec().encode(flowClassifier, this)); + flowClassifierEntry.add(codec(FlowClassifier.class).encode(flowClassifier, this)); } } return ok(result.toString()).build(); @@ -85,11 +83,11 @@ public class FlowClassifierWebResource extends AbstractWebResource { @Path("{flow_id}") @Produces(MediaType.APPLICATION_JSON) public Response getFlowClassifier(@PathParam("flow_id") String id) { - FlowClassifier flowClassifier = nullIsNotFound( - get(FlowClassifierService.class).getFlowClassifier(FlowClassifierId.of(id)), FLOW_CLASSIFIER_NOT_FOUND); + FlowClassifier flowClassifier = nullIsNotFound(get(FlowClassifierService.class) + .getFlowClassifier(FlowClassifierId.of(id)), FLOW_CLASSIFIER_NOT_FOUND); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("flow_classifier", new FlowClassifierCodec().encode(flowClassifier, this)); + ObjectNode result = mapper().createObjectNode(); + result.set("flow_classifier", codec(FlowClassifier.class).encode(flowClassifier, this)); return ok(result.toString()).build(); } @@ -107,13 +105,12 @@ public class FlowClassifierWebResource extends AbstractWebResource { @Produces(MediaType.APPLICATION_JSON) public Response createFlowClassifier(InputStream stream) { try { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream); + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); JsonNode flow = jsonTree.get("flow_classifier"); - FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this); + FlowClassifier flowClassifier = codec(FlowClassifier.class).decode((ObjectNode) flow, this); Boolean issuccess = nullIsNotFound(get(FlowClassifierService.class).createFlowClassifier(flowClassifier), - FLOW_CLASSIFIER_NOT_FOUND); + FLOW_CLASSIFIER_NOT_FOUND); return Response.status(OK).entity(issuccess.toString()).build(); } catch (IOException ex) { log.error("Exception while creating flow classifier {}.", ex.toString()); @@ -139,9 +136,9 @@ public class FlowClassifierWebResource extends AbstractWebResource { JsonNode jsonTree = mapper().readTree(stream); JsonNode flow = jsonTree.get("flow_classifier"); - FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this); + FlowClassifier flowClassifier = codec(FlowClassifier.class).decode((ObjectNode) flow, this); Boolean result = nullIsNotFound(get(FlowClassifierService.class).updateFlowClassifier(flowClassifier), - FLOW_CLASSIFIER_NOT_FOUND); + FLOW_CLASSIFIER_NOT_FOUND); return Response.status(OK).entity(result.toString()).build(); } catch (IOException e) { log.error("Update flow classifier failed because of exception {}.", e.toString()); @@ -161,7 +158,7 @@ public class FlowClassifierWebResource extends AbstractWebResource { log.debug("Deletes flow classifier by identifier {}.", id); FlowClassifierId flowClassifierId = FlowClassifierId.of(id); Boolean issuccess = nullIsNotFound(get(FlowClassifierService.class).removeFlowClassifier(flowClassifierId), - FLOW_CLASSIFIER_NOT_FOUND); + FLOW_CLASSIFIER_NOT_FOUND); } } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java index db12bcc7..e7b908b7 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java @@ -15,7 +15,6 @@ */ package org.onosproject.vtnweb.resources; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.onlab.util.Tools.nullIsNotFound; @@ -37,11 +36,11 @@ import org.onosproject.rest.AbstractWebResource; import org.onosproject.vtnrsc.PortChain; import org.onosproject.vtnrsc.PortChainId; import org.onosproject.vtnrsc.portchain.PortChainService; -import org.onosproject.vtnweb.web.PortChainCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** @@ -52,7 +51,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public class PortChainWebResource extends AbstractWebResource { private final Logger log = LoggerFactory.getLogger(PortChainWebResource.class); - private final PortChainService service = get(PortChainService.class); public static final String PORT_CHAIN_NOT_FOUND = "Port chain not found"; public static final String PORT_CHAIN_ID_EXIST = "Port chain exists"; public static final String PORT_CHAIN_ID_NOT_EXIST = "Port chain does not exist with identifier"; @@ -65,10 +63,15 @@ public class PortChainWebResource extends AbstractWebResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getPortChains() { - Iterable portChains = service.getPortChains(); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("port_chains", new PortChainCodec().encode(portChains, this)); - return ok(result).build(); + Iterable portChains = get(PortChainService.class).getPortChains(); + ObjectNode result = mapper().createObjectNode(); + ArrayNode portChainEntry = result.putArray("port_chains"); + if (portChains != null) { + for (final PortChain portChain : portChains) { + portChainEntry.add(codec(PortChain.class).encode(portChain, this)); + } + } + return ok(result.toString()).build(); } /** @@ -82,14 +85,11 @@ public class PortChainWebResource extends AbstractWebResource { @Produces(MediaType.APPLICATION_JSON) public Response getPortPain(@PathParam("chain_id") String id) { - if (!service.exists(PortChainId.of(id))) { - return Response.status(NOT_FOUND).entity(PORT_CHAIN_NOT_FOUND).build(); - } - PortChain portChain = nullIsNotFound(service.getPortChain(PortChainId.of(id)), + PortChain portChain = nullIsNotFound(get(PortChainService.class).getPortChain(PortChainId.of(id)), PORT_CHAIN_NOT_FOUND); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("port_chain", new PortChainCodec().encode(portChain, this)); - return ok(result).build(); + ObjectNode result = mapper().createObjectNode(); + result.set("port_chain", codec(PortChain.class).encode(portChain, this)); + return ok(result.toString()).build(); } /** @@ -105,8 +105,10 @@ public class PortChainWebResource extends AbstractWebResource { public Response createPortChain(InputStream stream) { try { ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); - PortChain portChain = codec(PortChain.class).decode(jsonTree, this); - Boolean issuccess = nullIsNotFound(service.createPortChain(portChain), PORT_CHAIN_NOT_FOUND); + JsonNode port = jsonTree.get("port_chain"); + PortChain portChain = codec(PortChain.class).decode((ObjectNode) port, this); + Boolean issuccess = nullIsNotFound(get(PortChainService.class).createPortChain(portChain), + PORT_CHAIN_NOT_FOUND); return Response.status(OK).entity(issuccess.toString()).build(); } catch (IOException e) { log.error("Exception while creating port chain {}.", e.toString()); @@ -129,8 +131,10 @@ public class PortChainWebResource extends AbstractWebResource { final InputStream stream) { try { ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); - PortChain portChain = codec(PortChain.class).decode(jsonTree, this); - Boolean result = nullIsNotFound(service.updatePortChain(portChain), PORT_CHAIN_NOT_FOUND); + JsonNode port = jsonTree.get("port_chain"); + PortChain portChain = codec(PortChain.class).decode((ObjectNode) port, this); + Boolean result = nullIsNotFound(get(PortChainService.class).updatePortChain(portChain), + PORT_CHAIN_NOT_FOUND); return Response.status(OK).entity(result.toString()).build(); } catch (IOException e) { log.error("Update port chain failed because of exception {}.", e.toString()); @@ -149,7 +153,8 @@ public class PortChainWebResource extends AbstractWebResource { log.debug("Deletes port chain by identifier {}.", id); PortChainId portChainId = PortChainId.of(id); - Boolean issuccess = nullIsNotFound(service.removePortChain(portChainId), PORT_CHAIN_NOT_FOUND); + Boolean issuccess = nullIsNotFound(get(PortChainService.class).removePortChain(portChainId), + PORT_CHAIN_NOT_FOUND); if (!issuccess) { log.debug("Port Chain identifier {} does not exist", id); } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java index 69daad37..dc5328a2 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java @@ -16,7 +16,6 @@ package org.onosproject.vtnweb.resources; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.onlab.util.Tools.nullIsNotFound; @@ -38,11 +37,12 @@ import org.onosproject.rest.AbstractWebResource; import org.onosproject.vtnrsc.PortPairGroup; import org.onosproject.vtnrsc.PortPairGroupId; import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; -import org.onosproject.vtnweb.web.PortPairGroupCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** @@ -53,7 +53,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public class PortPairGroupWebResource extends AbstractWebResource { private final Logger log = LoggerFactory.getLogger(PortPairGroupWebResource.class); - private final PortPairGroupService service = get(PortPairGroupService.class); public static final String PORT_PAIR_GROUP_NOT_FOUND = "Port pair group not found"; public static final String PORT_PAIR_GROUP_ID_EXIST = "Port pair group exists"; public static final String PORT_PAIR_GROUP_ID_NOT_EXIST = "Port pair group does not exist with identifier"; @@ -66,10 +65,15 @@ public class PortPairGroupWebResource extends AbstractWebResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getPortPairGroups() { - Iterable portPairGroups = service.getPortPairGroups(); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("port_pair_groups", new PortPairGroupCodec().encode(portPairGroups, this)); - return ok(result).build(); + Iterable portPairGroups = get(PortPairGroupService.class).getPortPairGroups(); + ObjectNode result = mapper().createObjectNode(); + ArrayNode portPairGroupEntry = result.putArray("port_pair_groups"); + if (portPairGroups != null) { + for (final PortPairGroup portPairGroup : portPairGroups) { + portPairGroupEntry.add(codec(PortPairGroup.class).encode(portPairGroup, this)); + } + } + return ok(result.toString()).build(); } /** @@ -82,17 +86,13 @@ public class PortPairGroupWebResource extends AbstractWebResource { @Path("{group_id}") @Produces(MediaType.APPLICATION_JSON) public Response getPortPairGroup(@PathParam("group_id") String id) { - - if (!service.exists(PortPairGroupId.of(id))) { - return Response.status(NOT_FOUND) - .entity(PORT_PAIR_GROUP_NOT_FOUND).build(); - } - PortPairGroup portPairGroup = nullIsNotFound(service.getPortPairGroup(PortPairGroupId.of(id)), + PortPairGroup portPairGroup = nullIsNotFound(get(PortPairGroupService.class) + .getPortPairGroup(PortPairGroupId.of(id)), PORT_PAIR_GROUP_NOT_FOUND); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("port_pair_group", new PortPairGroupCodec().encode(portPairGroup, this)); - return ok(result).build(); + ObjectNode result = mapper().createObjectNode(); + result.set("port_pair_group", codec(PortPairGroup.class).encode(portPairGroup, this)); + return ok(result.toString()).build(); } /** @@ -108,10 +108,12 @@ public class PortPairGroupWebResource extends AbstractWebResource { public Response createPortPairGroup(InputStream stream) { try { - ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); + ObjectMapper mapper = new ObjectMapper(); + ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream); + JsonNode port = jsonTree.get("port_pair_group"); - PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this); - Boolean issuccess = nullIsNotFound(service.createPortPairGroup(portPairGroup), + PortPairGroup portPairGroup = codec(PortPairGroup.class).decode((ObjectNode) port, this); + Boolean issuccess = nullIsNotFound(get(PortPairGroupService.class).createPortPairGroup(portPairGroup), PORT_PAIR_GROUP_NOT_FOUND); return Response.status(OK).entity(issuccess.toString()).build(); } catch (IOException e) { @@ -134,9 +136,12 @@ public class PortPairGroupWebResource extends AbstractWebResource { public Response updatePortPairGroup(@PathParam("group_id") String id, final InputStream stream) { try { - ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); - PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this); - Boolean isSuccess = nullIsNotFound(service.updatePortPairGroup(portPairGroup), PORT_PAIR_GROUP_NOT_FOUND); + ObjectMapper mapper = new ObjectMapper(); + ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream); + JsonNode port = jsonTree.get("port_pair_group"); + PortPairGroup portPairGroup = codec(PortPairGroup.class).decode((ObjectNode) port, this); + Boolean isSuccess = nullIsNotFound(get(PortPairGroupService.class).updatePortPairGroup(portPairGroup), + PORT_PAIR_GROUP_NOT_FOUND); return Response.status(OK).entity(isSuccess.toString()).build(); } catch (IOException e) { log.error("Update port pair group failed because of exception {}.", e.toString()); @@ -154,7 +159,7 @@ public class PortPairGroupWebResource extends AbstractWebResource { public void deletePortPairGroup(@PathParam("group_id") String id) { log.debug("Deletes port pair group by identifier {}.", id); PortPairGroupId portPairGroupId = PortPairGroupId.of(id); - Boolean issuccess = nullIsNotFound(service.removePortPairGroup(portPairGroupId), + Boolean issuccess = nullIsNotFound(get(PortPairGroupService.class).removePortPairGroup(portPairGroupId), PORT_PAIR_GROUP_NOT_FOUND); if (!issuccess) { log.debug("Port pair group identifier {} does not exist", id); diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java index b9012898..4ed8ecd8 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java @@ -16,7 +16,6 @@ package org.onosproject.vtnweb.resources; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.onlab.util.Tools.nullIsNotFound; @@ -38,12 +37,10 @@ import org.onosproject.rest.AbstractWebResource; import org.onosproject.vtnrsc.PortPair; import org.onosproject.vtnrsc.PortPairId; import org.onosproject.vtnrsc.portpair.PortPairService; -import org.onosproject.vtnweb.web.PortPairCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -54,7 +51,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public class PortPairWebResource extends AbstractWebResource { private final Logger log = LoggerFactory.getLogger(PortPairWebResource.class); - private final PortPairService service = get(PortPairService.class); public static final String PORT_PAIR_NOT_FOUND = "Port pair not found"; public static final String PORT_PAIR_ID_EXIST = "Port pair exists"; public static final String PORT_PAIR_ID_NOT_EXIST = "Port pair does not exist with identifier"; @@ -67,12 +63,12 @@ public class PortPairWebResource extends AbstractWebResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getPortPairs() { - Iterable portPairs = service.getPortPairs(); - ObjectNode result = new ObjectMapper().createObjectNode(); + Iterable portPairs = get(PortPairService.class).getPortPairs(); + ObjectNode result = mapper().createObjectNode(); ArrayNode portPairEntry = result.putArray("port_pairs"); if (portPairs != null) { for (final PortPair portPair : portPairs) { - portPairEntry.add(new PortPairCodec().encode(portPair, this)); + portPairEntry.add(codec(PortPair.class).encode(portPair, this)); } } return ok(result.toString()).build(); @@ -88,13 +84,10 @@ public class PortPairWebResource extends AbstractWebResource { @Path("{pair_id}") @Produces(MediaType.APPLICATION_JSON) public Response getPortPair(@PathParam("pair_id") String id) { - - if (!service.exists(PortPairId.of(id))) { - return Response.status(NOT_FOUND).entity(PORT_PAIR_NOT_FOUND).build(); - } - PortPair portPair = nullIsNotFound(service.getPortPair(PortPairId.of(id)), PORT_PAIR_NOT_FOUND); - ObjectNode result = new ObjectMapper().createObjectNode(); - result.set("port_pair", new PortPairCodec().encode(portPair, this)); + PortPair portPair = nullIsNotFound(get(PortPairService.class).getPortPair(PortPairId.of(id)), + PORT_PAIR_NOT_FOUND); + ObjectNode result = mapper().createObjectNode(); + result.set("port_pair", codec(PortPair.class).encode(portPair, this)); return ok(result.toString()).build(); } @@ -110,11 +103,11 @@ public class PortPairWebResource extends AbstractWebResource { @Produces(MediaType.APPLICATION_JSON) public Response createPortPair(InputStream stream) { try { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream); + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); JsonNode port = jsonTree.get("port_pair"); - PortPair portPair = new PortPairCodec().decode((ObjectNode) port, this); - Boolean isSuccess = nullIsNotFound(service.createPortPair(portPair), PORT_PAIR_NOT_FOUND); + PortPair portPair = codec(PortPair.class).decode((ObjectNode) port, this); + Boolean isSuccess = nullIsNotFound(get(PortPairService.class).createPortPair(portPair), + PORT_PAIR_NOT_FOUND); return Response.status(OK).entity(isSuccess.toString()).build(); } catch (IOException e) { log.error("Exception while creating port pair {}.", e.toString()); @@ -136,11 +129,11 @@ public class PortPairWebResource extends AbstractWebResource { public Response updatePortPair(@PathParam("pair_id") String id, final InputStream stream) { try { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream); + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); JsonNode port = jsonTree.get("port_pair"); - PortPair portPair = new PortPairCodec().decode((ObjectNode) port, this); - Boolean isSuccess = nullIsNotFound(service.updatePortPair(portPair), PORT_PAIR_NOT_FOUND); + PortPair portPair = codec(PortPair.class).decode((ObjectNode) port, this); + Boolean isSuccess = nullIsNotFound(get(PortPairService.class).updatePortPair(portPair), + PORT_PAIR_NOT_FOUND); return Response.status(OK).entity(isSuccess.toString()).build(); } catch (IOException e) { log.error("Update port pair failed because of exception {}.", e.toString()); @@ -158,7 +151,7 @@ public class PortPairWebResource extends AbstractWebResource { public void deletePortPair(@PathParam("pair_id") String id) { PortPairId portPairId = PortPairId.of(id); - Boolean isSuccess = nullIsNotFound(service.removePortPair(portPairId), PORT_PAIR_NOT_FOUND); + Boolean isSuccess = nullIsNotFound(get(PortPairService.class).removePortPair(portPairId), PORT_PAIR_NOT_FOUND); if (!isSuccess) { log.debug("Port pair identifier {} does not exist", id); } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java new file mode 100644 index 00000000..e2defe59 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VtnCodecRegistrator.java @@ -0,0 +1,56 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnweb.web; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onosproject.codec.CodecService; +import org.onosproject.vtnrsc.FlowClassifier; +import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortPair; +import org.onosproject.vtnrsc.PortPairGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of the JSON codec brokering service for VTN app. + */ +@Component(immediate = true) +public class VtnCodecRegistrator { + + private static Logger log = LoggerFactory.getLogger(VtnCodecRegistrator.class); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CodecService codecService; + + @Activate + public void activate() { + codecService.registerCodec(PortPair.class, new PortPairCodec()); + codecService.registerCodec(PortPairGroup.class, new PortPairGroupCodec()); + codecService.registerCodec(FlowClassifier.class, new FlowClassifierCodec()); + codecService.registerCodec(PortChain.class, new PortChainCodec()); + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + log.info("Stopped"); + } +} diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java index be645be0..db08d7c4 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java @@ -40,11 +40,13 @@ import org.onlab.osgi.ServiceDirectory; import org.onlab.osgi.TestServiceDirectory; import org.onlab.packet.IpPrefix; import org.onlab.rest.BaseResource; +import org.onosproject.codec.CodecService; import org.onosproject.vtnrsc.FlowClassifier; import org.onosproject.vtnrsc.FlowClassifierId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.VirtualPortId; import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService; +import org.onosproject.vtnweb.web.SfcCodecContext; import com.eclipsesource.json.JsonObject; import com.sun.jersey.api.client.ClientResponse; @@ -192,8 +194,11 @@ public class FlowClassifierResourceTest extends VtnResourceTest { */ @Before public void setUpTest() { - ServiceDirectory testDirectory = new TestServiceDirectory().add(FlowClassifierService.class, - flowClassifierService); + SfcCodecContext context = new SfcCodecContext(); + + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(FlowClassifierService.class, flowClassifierService) + .add(CodecService.class, context.codecManager()); BaseResource.setServiceDirectory(testDirectory); } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java new file mode 100644 index 00000000..3cb2c83f --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java @@ -0,0 +1,247 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnweb.resources; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.codec.CodecService; +import org.onosproject.vtnrsc.FlowClassifierId; +import org.onosproject.vtnrsc.PortChain; +import org.onosproject.vtnrsc.PortChainId; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.portchain.PortChainService; +import org.onosproject.vtnweb.web.SfcCodecContext; + +import com.eclipsesource.json.JsonObject; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; + +/** + * Unit tests for port chain REST APIs. + */ +public class PortChainResourceTest extends VtnResourceTest { + + final PortChainService portChainService = createMock(PortChainService.class); + + PortChainId portChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae"); + TenantId tenantId1 = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5"); + private final List portPairGroupList1 = Lists.newArrayList(); + private final List flowClassifierList1 = Lists.newArrayList(); + + + final MockPortChain portChain1 = new MockPortChain(portChainId1, tenantId1, "portChain1", + "Mock port chain", portPairGroupList1, + flowClassifierList1); + + /** + * Mock class for a port chain. + */ + private static class MockPortChain implements PortChain { + + private final PortChainId portChainId; + private final TenantId tenantId; + private final String name; + private final String description; + private final List portPairGroupList; + private final List flowClassifierList; + + public MockPortChain(PortChainId portChainId, TenantId tenantId, + String name, String description, + List portPairGroupList, + List flowClassifierList) { + + this.portChainId = portChainId; + this.tenantId = tenantId; + this.name = name; + this.description = description; + this.portPairGroupList = portPairGroupList; + this.flowClassifierList = flowClassifierList; + } + + @Override + public PortChainId portChainId() { + return portChainId; + } + + @Override + public TenantId tenantId() { + return tenantId; + } + + @Override + public String name() { + return name; + } + + @Override + public String description() { + return description; + } + + @Override + public List portPairGroups() { + return ImmutableList.copyOf(portPairGroupList); + } + + @Override + public List flowClassifiers() { + return ImmutableList.copyOf(flowClassifierList); + } + + @Override + public boolean exactMatch(PortChain portChain) { + return this.equals(portChain) && + Objects.equals(this.portChainId, portChain.portChainId()) && + Objects.equals(this.tenantId, portChain.tenantId()); + } + } + + /** + * Sets up the global values for all the tests. + */ + @Before + public void setUpTest() { + SfcCodecContext context = new SfcCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(PortChainService.class, portChainService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + } + + /** + * Cleans up. + */ + @After + public void tearDownTest() { + } + + /** + * Tests the result of the rest api GET when there are no port chains. + */ + @Test + public void testPortChainsEmpty() { + + expect(portChainService.getPortChains()).andReturn(null).anyTimes(); + replay(portChainService); + final WebResource rs = resource(); + final String response = rs.path("port_chains").get(String.class); + assertThat(response, is("{\"port_chains\":[]}")); + } + + /** + * Tests the result of a rest api GET for port chain id. + */ + @Test + public void testGetPortChainId() { + + final Set portChains = new HashSet<>(); + portChains.add(portChain1); + + expect(portChainService.exists(anyObject())).andReturn(true).anyTimes(); + expect(portChainService.getPortChain(anyObject())).andReturn(portChain1).anyTimes(); + replay(portChainService); + + final WebResource rs = resource(); + final String response = rs.path("port_chains/1278dcd4-459f-62ed-754b-87fc5e4a6751").get(String.class); + final JsonObject result = JsonObject.readFrom(response); + assertThat(result, notNullValue()); + } + + /** + * Tests that a fetch of a non-existent port chain object throws an exception. + */ + @Test + public void testBadGet() { + expect(portChainService.getPortChain(anyObject())) + .andReturn(null).anyTimes(); + replay(portChainService); + WebResource rs = resource(); + try { + rs.path("port_chains/78dcd363-fc23-aeb6-f44b-56dc5aafb3ae").get(String.class); + fail("Fetch of non-existent port chain did not throw an exception"); + } catch (UniformInterfaceException ex) { + assertThat(ex.getMessage(), + containsString("returned a response status of")); + } + } + + /** + * Tests creating a port chain with POST. + */ + @Test + public void testPost() { + + expect(portChainService.createPortChain(anyObject())) + .andReturn(true).anyTimes(); + replay(portChainService); + + WebResource rs = resource(); + InputStream jsonStream = PortChainResourceTest.class.getResourceAsStream("post-PortChain.json"); + + ClientResponse response = rs.path("port_chains") + .type(MediaType.APPLICATION_JSON_TYPE) + .post(ClientResponse.class, jsonStream); + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); + } + + /** + * Tests deleting a port chain. + */ + @Test + public void testDelete() { + expect(portChainService.removePortChain(anyObject())) + .andReturn(true).anyTimes(); + replay(portChainService); + + WebResource rs = resource(); + + String location = "port_chains/1278dcd4-459f-62ed-754b-87fc5e4a6751"; + + ClientResponse deleteResponse = rs.path(location) + .type(MediaType.APPLICATION_JSON_TYPE) + .delete(ClientResponse.class); + assertThat(deleteResponse.getStatus(), + is(HttpURLConnection.HTTP_NO_CONTENT)); + } +} diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java new file mode 100644 index 00000000..c13f2141 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java @@ -0,0 +1,234 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.vtnweb.resources; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.codec.CodecService; +import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.vtnrsc.PortPairGroupId; +import org.onosproject.vtnrsc.PortPairId; +import org.onosproject.vtnrsc.TenantId; +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService; +import org.onosproject.vtnweb.web.SfcCodecContext; + +import com.eclipsesource.json.JsonObject; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; +/** + * Unit tests for port pair group REST APIs. + */ +public class PortPairGroupResourceTest extends VtnResourceTest { + + final PortPairGroupService portPairGroupService = createMock(PortPairGroupService.class); + + PortPairGroupId portPairGroupId1 = PortPairGroupId.of("4512d643-24fc-4fae-af4b-321c5e2eb3d1"); + TenantId tenantId1 = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5"); + private final List portPairList1 = Lists.newArrayList(); + + final MockPortPairGroup portPairGroup1 = new MockPortPairGroup(portPairGroupId1, tenantId1, "portPairGroup1", + "Mock port pair group", portPairList1); + + /** + * Mock class for a port pair group. + */ + private static class MockPortPairGroup implements PortPairGroup { + + private final PortPairGroupId portPairGroupId; + private final TenantId tenantId; + private final String name; + private final String description; + private final List portPairList; + + public MockPortPairGroup(PortPairGroupId portPairGroupId, TenantId tenantId, + String name, String description, + List portPairList) { + + this.portPairGroupId = portPairGroupId; + this.tenantId = tenantId; + this.name = name; + this.description = description; + this.portPairList = portPairList; + } + + @Override + public PortPairGroupId portPairGroupId() { + return portPairGroupId; + } + + @Override + public TenantId tenantId() { + return tenantId; + } + + @Override + public String name() { + return name; + } + + @Override + public String description() { + return description; + } + + @Override + public List portPairs() { + return ImmutableList.copyOf(portPairList); + } + + @Override + public boolean exactMatch(PortPairGroup portPairGroup) { + return this.equals(portPairGroup) && + Objects.equals(this.portPairGroupId, portPairGroup.portPairGroupId()) && + Objects.equals(this.tenantId, portPairGroup.tenantId()); + } + } + + /** + * Sets up the global values for all the tests. + */ + @Before + public void setUpTest() { + SfcCodecContext context = new SfcCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(PortPairGroupService.class, portPairGroupService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + } + + /** + * Cleans up. + */ + @After + public void tearDownTest() { + } + + /** + * Tests the result of the rest api GET when there are no port pair groups. + */ + @Test + public void testPortPairGroupsEmpty() { + + expect(portPairGroupService.getPortPairGroups()).andReturn(null).anyTimes(); + replay(portPairGroupService); + final WebResource rs = resource(); + final String response = rs.path("port_pair_groups").get(String.class); + assertThat(response, is("{\"port_pair_groups\":[]}")); + } + + /** + * Tests the result of a rest api GET for port pair group id. + */ + @Test + public void testGetPortPairGroupId() { + + final Set portPairGroups = new HashSet<>(); + portPairGroups.add(portPairGroup1); + + expect(portPairGroupService.exists(anyObject())).andReturn(true).anyTimes(); + expect(portPairGroupService.getPortPairGroup(anyObject())).andReturn(portPairGroup1).anyTimes(); + replay(portPairGroupService); + + final WebResource rs = resource(); + final String response = rs.path("port_pair_groups/4512d643-24fc-4fae-af4b-321c5e2eb3d1").get(String.class); + final JsonObject result = JsonObject.readFrom(response); + assertThat(result, notNullValue()); + } + + /** + * Tests that a fetch of a non-existent port pair group object throws an exception. + */ + @Test + public void testBadGet() { + expect(portPairGroupService.getPortPairGroup(anyObject())) + .andReturn(null).anyTimes(); + replay(portPairGroupService); + WebResource rs = resource(); + try { + rs.path("port_pair_groups/78dcd363-fc23-aeb6-f44b-56dc5aafb3ae").get(String.class); + fail("Fetch of non-existent port pair group did not throw an exception"); + } catch (UniformInterfaceException ex) { + assertThat(ex.getMessage(), + containsString("returned a response status of")); + } + } + + /** + * Tests creating a port pair group with POST. + */ + @Test + public void testPost() { + + expect(portPairGroupService.createPortPairGroup(anyObject())) + .andReturn(true).anyTimes(); + replay(portPairGroupService); + + WebResource rs = resource(); + InputStream jsonStream = PortPairGroupResourceTest.class.getResourceAsStream("post-PortPairGroup.json"); + + ClientResponse response = rs.path("port_pair_groups") + .type(MediaType.APPLICATION_JSON_TYPE) + .post(ClientResponse.class, jsonStream); + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); + } + + /** + * Tests deleting a port pair group. + */ + @Test + public void testDelete() { + expect(portPairGroupService.removePortPairGroup(anyObject())) + .andReturn(true).anyTimes(); + replay(portPairGroupService); + + WebResource rs = resource(); + + String location = "port_pair_groups/4512d643-24fc-4fae-af4b-321c5e2eb3d1"; + + ClientResponse deleteResponse = rs.path(location) + .type(MediaType.APPLICATION_JSON_TYPE) + .delete(ClientResponse.class); + assertThat(deleteResponse.getStatus(), + is(HttpURLConnection.HTTP_NO_CONTENT)); + } +} diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java index 271904cc..36014ec5 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java @@ -39,10 +39,12 @@ import org.junit.Test; import org.onlab.osgi.ServiceDirectory; import org.onlab.osgi.TestServiceDirectory; import org.onlab.rest.BaseResource; +import org.onosproject.codec.CodecService; import org.onosproject.vtnrsc.PortPair; import org.onosproject.vtnrsc.PortPairId; import org.onosproject.vtnrsc.TenantId; import org.onosproject.vtnrsc.portpair.PortPairService; +import org.onosproject.vtnweb.web.SfcCodecContext; import com.eclipsesource.json.JsonObject; import com.sun.jersey.api.client.ClientResponse; @@ -129,7 +131,10 @@ public class PortPairResourceTest extends VtnResourceTest { */ @Before public void setUpTest() { - ServiceDirectory testDirectory = new TestServiceDirectory().add(PortPairService.class, portPairService); + + SfcCodecContext context = new SfcCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory().add(PortPairService.class, portPairService) + .add(CodecService.class, context.codecManager()); BaseResource.setServiceDirectory(testDirectory); } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java index fe9d7995..c56a4fcb 100644 --- a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java @@ -15,15 +15,10 @@ */ package org.onosproject.vtnweb.web; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.onosproject.codec.CodecContext; +import org.onosproject.codec.CodecService; import org.onosproject.codec.JsonCodec; -import org.onosproject.vtnrsc.FlowClassifier; -import org.onosproject.vtnrsc.PortChain; -import org.onosproject.vtnrsc.PortPair; -import org.onosproject.vtnrsc.PortPairGroup; +import org.onosproject.codec.impl.CodecManager; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,17 +28,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; public class SfcCodecContext implements CodecContext { private final ObjectMapper mapper = new ObjectMapper(); - private final Map, JsonCodec> codecs = new ConcurrentHashMap<>(); + private final CodecManager codecManager = new CodecManager(); + private final VtnCodecRegistrator manager = new VtnCodecRegistrator(); /** * Constructs a new mock codec context. */ public SfcCodecContext() { - codecs.clear(); - registerCodec(PortPair.class, new PortPairCodec()); - registerCodec(PortChain.class, new PortChainCodec()); - registerCodec(PortPairGroup.class, new PortPairGroupCodec()); - registerCodec(FlowClassifier.class, new FlowClassifierCodec()); + codecManager.activate(); + manager.codecService = codecManager; + manager.activate(); } @Override @@ -58,20 +52,17 @@ public class SfcCodecContext implements CodecContext { return null; } + @Override + public JsonCodec codec(Class entityClass) { + return codecManager.getCodec(entityClass); + } + /** - * Registers the specified JSON codec for the given entity class. + * Get the codec manager. * - * @param entityClass entity class - * @param codec JSON codec - * @param entity type + * @return instance of codec manager */ - public void registerCodec(Class entityClass, JsonCodec codec) { - codecs.putIfAbsent(entityClass, codec); - } - - @SuppressWarnings("unchecked") - @Override - public JsonCodec codec(Class entityClass) { - return codecs.get(entityClass); + public CodecService codecManager() { + return codecManager; } } diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortChain.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortChain.json new file mode 100644 index 00000000..488e290f --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortChain.json @@ -0,0 +1,15 @@ +{"port_pair": { + "id": "1278dcd4-459f-62ed-754b-87fc5e4a6751", + "name": "PC2", + "tenant_id": "d382007aa9904763a801f68ecf065cf5", + "description": "Two flows and two port-pair-groups", + "flow_classifiers": [ + "456a4a34-2e9c-14ae-37fb-765feae2eb05", + "4a334cd4-fe9c-4fae-af4b-321c5e2eb051" + ], + "port_pair_groups": [ + "4512d643-24fc-4fae-af4b-321c5e2eb3d1", + "4a634d49-76dc-4fae-af4b-321c5e23d651" + ] + } +} diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPairGroup.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPairGroup.json new file mode 100644 index 00000000..f6a888d9 --- /dev/null +++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPairGroup.json @@ -0,0 +1,11 @@ +{"port_pair_group": { + "id": "4512d643-24fc-4fae-af4b-321c5e2eb3d1", + "name": "portPairGroup1", + "tenant_id": "d382007aa9904763a801f68ecf065cf5", + "description": "Mock port pair group", + "port_pairs": [ + "875dfeda-43ed-23fe-454b-764feab2c342", + "78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae" + ] +} +} diff --git a/framework/src/onos/bgp/api/pom.xml b/framework/src/onos/bgp/api/pom.xml deleted file mode 100755 index 6fa1cc7b..00000000 --- a/framework/src/onos/bgp/api/pom.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - 4.0.0 - - - org.onosproject - onos-bgp - 1.4.0-SNAPSHOT - ../pom.xml - - - onos-bgp-api - bundle - - ONOS BGP controller subsystem API - - - - org.onosproject - onos-bgpio - - - io.netty - netty - - - org.onosproject - onos-api - - - org.onosproject - onlab-misc - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.3 - - - - io.netty:netty - com.google.guava:guava - org.slf4j:slfj-api - ch.qos.logback:logback-core - ch.qos.logback:logback-classic - com.google.code.findbugs:annotations - - - - - - package - - shade - - - - - - org.apache.felix - maven-bundle-plugin - - - - org.onosproject.bgp.*,org.onosproject.bgpio.*,org.onosproject.bgp.controller - - - - - - - - diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java deleted file mode 100755 index 6f64d2bb..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller; - -import java.util.TreeMap; - -/** - * Abstraction of an BGP configuration. Manages the BGP configuration from CLI to the BGP controller. - */ -public interface BgpCfg { - - enum State { - /** - * Signifies that its just created. - */ - INIT, - - /** - * Signifies that only IP Address is configured. - */ - IP_CONFIGURED, - - /** - * Signifies that only Autonomous System is configured. - */ - AS_CONFIGURED, - - /** - * Signifies that both IP and Autonomous System is configured. - */ - IP_AS_CONFIGURED - } - - /** - * Returns the status of the configuration based on this state certain operations like connection is handled. - * - * @return State of the configuration - */ - State getState(); - - /** - * To set the current state of the configuration. - * - * @param state Configuration State enum - */ - void setState(State state); - - /** - * Get the status of the link state support for this BGP speaker. - * - * @return true if the link state is supported else false - */ - boolean getLsCapability(); - - /** - * Set the link state support to this BGP speaker. - * - * @param lscapability true value if link state is supported else false - */ - void setLsCapability(boolean lscapability); - - /** - * Get the status of the 32 bit AS support for this BGP speaker. - * - * @return true if the 32 bit AS number is supported else false - */ - boolean getLargeASCapability(); - - /** - * Set the 32 bit AS support capability to this BGP speaker. - * - * @param largeAs true value if the 32 bit AS is supported else false - */ - void setLargeASCapability(boolean largeAs); - - /** - * Set the AS number to which this BGP speaker belongs. - * - * @param localAs 16 or 32 bit AS number, length is dependent on the capability - */ - void setAsNumber(int localAs); - - /** - * Get the AS number to which this BGP speaker belongs. - * - * @return 16 or 32 bit AS number, length is dependent on the capability - */ - int getAsNumber(); - - /** - * Get the connection retry count number. - * - * @return connection retry count if there is a connection error - */ - int getMaxConnRetryCount(); - - /** - * Set the connection retry count. - * - * @param retryCount number of times to try to connect if there is any error - */ - void setMaxConnRetryCout(int retryCount); - - /** - * Get the connection retry time in seconds. - * - * @return connection retry time in seconds - */ - int getMaxConnRetryTime(); - - /** - * Set the connection retry time in seconds. - * - * @param retryTime connection retry times in seconds - */ - void setMaxConnRetryTime(int retryTime); - - /** - * Set the keep alive timer for the connection. - * - * @param holdTime connection hold timer in seconds - */ - void setHoldTime(short holdTime); - - /** - * Returns the connection hold timer in seconds. - * - * @return connection hold timer in seconds - */ - short getHoldTime(); - - /** - * Returns the maximum number of session supported. - * - * @return maximum number of session supported - */ - int getMaxSession(); - - /** - * Set the maximum number of sessions to support. - * - * @param maxsession maximum number of session - */ - void setMaxSession(int maxsession); - - /** - * Returns the Router ID of this BGP speaker. - * - * @return IP address in string format - */ - String getRouterId(); - - /** - * Set the Router ID of this BGP speaker. - * - * @param routerid IP address in string format - */ - void setRouterId(String routerid); - - /** - * Add the BGP peer IP address and the AS number to which it belongs. - * - * @param routerid IP address in string format - * @param remoteAs AS number to which it belongs - * - * @return true if added successfully else false - */ - boolean addPeer(String routerid, int remoteAs); - - /** - * Add the BGP peer IP address and the keep alive time. - * - * @param routerid IP address in string format - * @param holdTime keep alive time for the connection - * - * @return true if added successfully else false - */ - boolean addPeer(String routerid, short holdTime); - - /** - * Add the BGP peer IP address, the AS number to which it belongs and keep alive time. - * - * @param routerid IP address in string format - * @param remoteAs AS number to which it belongs - * @param holdTime keep alive time for the connection - * - * @return true if added successfully else false - */ - boolean addPeer(String routerid, int remoteAs, short holdTime); - - /** - * Remove the BGP peer with this IP address. - * - * @param routerid router IP address - * - * @return true if removed successfully else false - */ - boolean removePeer(String routerid); - - /** - * Connect to BGP peer with this IP address. - * - * @param routerid router IP address - * - * @return true of the configuration is found and able to connect else false - */ - boolean connectPeer(String routerid); - - /** - * Disconnect this BGP peer with this IP address. - * - * @param routerid router IP address in string format - * - * @return true if the configuration is found and able to disconnect else false - */ - boolean disconnectPeer(String routerid); - - /** - * Returns the peer tree information. - * - * @return return the tree map with IP as key and BGPPeerCfg as object - */ - TreeMap displayPeers(); - - /** - * Return the BGP Peer information with this matching IP. - * - * @param routerid router IP address in string format - * - * @return BGPPeerCfg object - */ - BgpPeerCfg displayPeers(String routerid); - - /** - * Check if this BGP peer is configured. - * - * @param routerid router IP address in string format - * - * @return true if configured exists else false - */ - boolean isPeerConfigured(String routerid); - - /** - * Check if this BGP speaker is having connection with the peer. - * - * @param routerid router IP address in string format - * - * @return true if the connection exists else false - */ - boolean isPeerConnected(String routerid); - - /** - * Return the peer tree map. - * - * @return return the tree map with IP as key and BGPPeerCfg as object - */ - TreeMap getPeerTree(); - - /** - * Set the current connection state information. - * - * @param routerid router IP address in string format - * @param state state information - */ - void setPeerConnState(String routerid, BgpPeerCfg.State state); - - /** - * Check if the peer can be connected or not. - * - * @param routerid router IP address in string format - * - * @return true if the peer can be connected else false - */ - boolean isPeerConnectable(String routerid); - - /** - * Get the current peer connection state information. - * - * @param routerid router IP address in string format - * - * @return state information - */ - BgpPeerCfg.State getPeerConnState(String routerid); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java deleted file mode 100755 index 8f33ee87..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgp.controller; - -/** - * Abstraction of an BGP connect peer, initiate remote connection to BGP peer on configuration. - */ -public interface BgpConnectPeer { - /** - * Initiate bgp peer connection. - */ - void connectPeer(); - - /** - * End bgp peer connection. - */ - void disconnectPeer(); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java deleted file mode 100755 index cc87eb32..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller; - -import java.util.Map; -import java.util.Set; - -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpMessage; - -/** - * Abstraction of an BGP controller. Serves as a one stop shop for obtaining BGP devices and (un)register listeners on - * bgp events - */ -public interface BgpController { - - /** - * Returns list of bgp peers connected to this BGP controller. - * - * @return Iterable of BGPPeer elements - */ - Iterable getPeers(); - - /** - * Returns the actual bgp peer for the given ip address. - * - * @param bgpId the id of the bgp peer to fetch - * @return the interface to this bgp peer - */ - BgpPeer getPeer(BgpId bgpId); - - /** - * Register a listener for BGP message events. - * - * @param listener the listener to notify - */ - void addListener(BgpNodeListener listener); - - /** - * Unregister a listener. - * - * @param listener the listener to unregister - */ - void removeListener(BgpNodeListener listener); - - /** - * Send a message to a particular bgp peer. - * - * @param bgpId the id of the peer to send message. - * @param msg the message to send - */ - void writeMsg(BgpId bgpId, BgpMessage msg); - - /** - * Process a message and notify the appropriate listeners. - * - * @param bgpId id of the peer the message arrived on - * @param msg the message to process. - * @throws BgpParseException on data processing error - */ - void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException; - - /** - * Close all connected BGP peers. - * - */ - void closeConnectedPeers(); - - /** - * Get the BGPConfig class to the caller. - * - * @return configuration object - */ - BgpCfg getConfig(); - - /** - * Get the BGP connected peers to this controller. - * - * @return the integer number - */ - int connectedPeerCount(); - - /** - * Return BGP peer manager. - * - * @return BGPPeerManager peer manager instance - */ - BgpPeerManager peerManager(); - - /** - * Return BGP connected peers. - * - * @return connectedPeers connected peers - */ - Map connectedPeers(); - - /** - * Return BGP node listener. - * - * @return node listener - */ - Set listener(); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java deleted file mode 100755 index ed04dc94..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.onosproject.bgp.controller; - -import static com.google.common.base.Preconditions.checkArgument; - -import java.net.URI; -import java.net.URISyntaxException; - -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The class representing a network bgp device id. This class is immutable. - */ -public final class BgpDpid { - private static final Logger log = LoggerFactory.getLogger(BgpDpid.class); - - private static final String SCHEME = "bgp"; - private static final long UNKNOWN = 0; - private StringBuilder stringBuilder; - public static final int NODE_DESCRIPTOR_LOCAL = 1; - public static final int NODE_DESCRIPTOR_REMOTE = 2; - - /** - * Initialize bgp id to generate URI. - * - * @param linkNlri node Nlri. - * @param nodeDescriptorType node descriptor type, local/remote - */ - public BgpDpid(final BgpLinkLsNlriVer4 linkNlri, int nodeDescriptorType) { - this.stringBuilder = new StringBuilder("bgpls://"); - - if (linkNlri.getRouteDistinguisher() != null) { - this.stringBuilder.append(linkNlri.getRouteDistinguisher().getRouteDistinguisher()).append(':'); - } - - try { - this.stringBuilder.append(linkNlri.getProtocolId()).append(':').append(linkNlri.getIdentifier()) - .append('/'); - - if (nodeDescriptorType == NODE_DESCRIPTOR_LOCAL) { - add(linkNlri.localNodeDescriptors()); - } else if (nodeDescriptorType == NODE_DESCRIPTOR_REMOTE) { - add(linkNlri.remoteNodeDescriptors()); - } - } catch (BgpParseException e) { - log.info("Exception BgpId string: " + e.toString()); - } - - } - - /** - * Initialize bgp id to generate URI. - * - * @param nodeNlri node Nlri. - */ - public BgpDpid(final BgpNodeLSNlriVer4 nodeNlri) { - this.stringBuilder = new StringBuilder("bgpls://"); - - if (nodeNlri.getRouteDistinguisher() != null) { - this.stringBuilder.append(nodeNlri.getRouteDistinguisher().getRouteDistinguisher()).append(':'); - } - - try { - - this.stringBuilder.append(nodeNlri.getProtocolId()).append(':').append(nodeNlri.getIdentifier()) - .append('/'); - - add(nodeNlri.getLocalNodeDescriptors()); - - } catch (BgpParseException e) { - log.info("Exception node string: " + e.toString()); - } - } - - BgpDpid add(final Object value) { - if (value != null) { - this.stringBuilder.append('&').append('=').append(value.toString()); - } - return this; - } - - @Override - public String toString() { - return this.stringBuilder.toString(); - } - - /** - * Produces bgp URI. - * - * @param value string to get URI - * @return bgp URI, otherwise null - */ - public static URI uri(String value) { - try { - return new URI(SCHEME, value, null); - } catch (URISyntaxException e) { - log.info("Exception BgpId URI: " + e.toString()); - } - return null; - } - - /** - * Returns bgpDpid created from the given device URI. - * - * @param uri device URI - * @return object of BgpDpid - */ - public static BgpDpid bgpDpid(URI uri) { - checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme"); - - // TODO: return BgpDpid generated from uri - return null; - } -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java deleted file mode 100755 index 7a6c625d..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller; - -import org.onlab.packet.IpAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * The class representing a network peer bgp ip. - * This class is immutable. - */ -public final class BgpId { - - private static final String SCHEME = "bgp"; - private static final long UNKNOWN = 0; - private final IpAddress ipAddress; - - /** - * Private constructor. - */ - private BgpId(IpAddress ipAddress) { - this.ipAddress = ipAddress; - } - - /** - * Create a BGPId from ip address. - * - * @param ipAddress IP address - * @return object of BGPId - */ - public static BgpId bgpId(IpAddress ipAddress) { - return new BgpId(ipAddress); - } - - /** - * Returns the ip address. - * - * @return ipAddress - */ - public IpAddress ipAddress() { - return ipAddress; - } - - /** - * Convert the BGPId value to a ':' separated hexadecimal string. - * - * @return the BGPId value as a ':' separated hexadecimal string. - */ - @Override - public String toString() { - return ipAddress.toString(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof BgpId)) { - return false; - } - - BgpId otherBGPid = (BgpId) other; - return Objects.equals(ipAddress, otherBGPid.ipAddress); - } - - @Override - public int hashCode() { - return Objects.hash(ipAddress); - } - - /** - * Returns BGPId created from the given device URI. - * - * @param uri device URI - * @return object of BGPId - */ - public static BgpId bgpId(URI uri) { - checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme"); - return new BgpId(IpAddress.valueOf(uri.getSchemeSpecificPart())); - } - - /** - * Produces device URI from the given DPID. - * - * @param bgpId device bgpId - * @return device URI - */ - public static URI uri(BgpId bgpId) { - return uri(bgpId.ipAddress()); - } - - /** - * Produces device URI from the given DPID long. - * - * @param ipAddress device ip address - * @return device URI - */ - public static URI uri(IpAddress ipAddress) { - try { - return new URI(SCHEME, ipAddress.toString(), null); - } catch (URISyntaxException e) { - return null; - } - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java deleted file mode 100755 index 8b34e314..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgp.controller; - -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; - -/** - * Allows for providers interested in Link events to be notified. - */ -public interface BgpLinkListener { - - /** - * Notify that got a packet of link from network and need do processing. - * - * @param linkNlri bgp link - */ - void addLink(BgpLinkLsNlriVer4 linkNlri); - - /** - * Notify that got a packet of link from network and need do processing. - * - * @param linkNlri bgp link - */ - void deleteLink(BgpLinkLsNlriVer4 linkNlri); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java deleted file mode 100755 index 636c1c85..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.onosproject.bgp.controller; - -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; -import org.onosproject.bgpio.types.RouteDistinguisher; - -/** - * Abstraction of BGP local RIB. - */ -public interface BgpLocalRib { - - /** - * Add NLRI to local RIB. - * - * @param sessionInfo session info - * @param nlri network layer reach info - * @param details nlri details - */ - void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details); - - /** - * Removes NLRI identifier if it exists. - * - * @param nlri info - */ - void delete(BgpLSNlri nlri); - - /** - * Update NLRI identifier mapped with route distinguisher if it exists in tree otherwise add NLRI infomation mapped - * to respective route distinguisher. - * - * @param sessionInfo BGP session info - * @param nlri info - * @param details has pathattribute, protocol id and identifier - * @param routeDistinguisher unique for each VPN - */ - void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details, - RouteDistinguisher routeDistinguisher); - - /** - * Removes VPN NLRI identifier mapped to route distinguisher if it exists. - * - * @param nlri info - * @param routeDistinguisher unique for each VPN - */ - void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java deleted file mode 100755 index 726d931b..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgp.controller; - -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; - -/** - * Allows for providers interested in node events to be notified. - */ -public interface BgpNodeListener { - - /** - * Notifies that the node was added. - * - * @param nodeNlri node rechability info - */ - void addNode(BgpNodeLSNlriVer4 nodeNlri); - - /** - * Notifies that the node was removed. - * - * @param nodeNlri node rechability info - */ - void deleteNode(BgpNodeLSNlriVer4 nodeNlri); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java deleted file mode 100755 index 8fd3c688..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller; - -/** - * A representation of a packet context which allows any provider to view a packet in event, but may block the response - * to the event if blocked has been called. This packet context can be used to react to the packet in event with a - * packet out. - */ -public interface BgpPacketStats { - /** - * Returns the count for no of packets sent out. - * - * @return int value of no of packets sent - */ - int outPacketCount(); - - /** - * Returns the count for no of packets received. - * - * @return int value of no of packets sent - */ - int inPacketCount(); - - /** - * Returns the count for no of wrong packets received. - * - * @return int value of no of wrong packets received - */ - int wrongPacketCount(); - - /** - * Returns the time. - * - * @return the time - */ - long getTime(); -} \ No newline at end of file diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java deleted file mode 100644 index 9f4d47da..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller; -import java.util.List; -import org.jboss.netty.channel.Channel; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpFactory; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onosproject.bgpio.types.BgpValueType; - -/** - * Represents the peer side of an BGP peer. - * - */ -public interface BgpPeer { - - /** - * Sets the associated Netty channel for this bgp peer. - * - * @param channel the Netty channel - */ - void setChannel(Channel channel); - - /** - * Gets the associated Netty channel handler for this bgp peer. - * - * @return Channel channel connected. - */ - Channel getChannel(); - - /** - * Sets whether the bgp peer is connected. - * - * @param connected whether the bgp peer is connected - */ - void setConnected(boolean connected); - - /** - * Checks whether the handshake is complete. - * - * @return true is finished, false if not. - */ - boolean isHandshakeComplete(); - - /** - * Writes the message to the peer. - * - * @param msg the message to write - */ - void sendMessage(BgpMessage msg); - - /** - * Writes the BGPMessage list to the peer. - * - * @param msgs the messages to be written - */ - void sendMessage(List msgs); - - /** - * Provides the factory for BGP version. - * - * @return BGP version specific factory. - */ - BgpFactory factory(); - - /** - * Checks if the bgp peer is still connected. - * - * @return whether the bgp peer is still connected - */ - boolean isConnected(); - - /** - * Disconnects the bgp peer by closing the TCP connection. Results in a call to the channel handler's - * channelDisconnected method for cleanup - */ - void disconnectPeer(); - - /** - * Identifies the channel used to communicate with the bgp peer. - * - * @return string representation of the connection to the peer - */ - String channelId(); - - /** - * Maintaining Adj-RIB-In separately for each peer. - * - * @param pathAttr list of Bgp path attributes - * @throws BgpParseException while building Adj-Rib-In - */ - void buildAdjRibIn(List pathAttr) throws BgpParseException; - - /** - * Return the BGP session info. - * - * @return sessionInfo bgp session info - */ - BgpSessionInfo sessionInfo(); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java deleted file mode 100755 index 2fb970fc..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller; - -/** - * BGP Peer configuration information. - */ -public interface BgpPeerCfg { - - enum State { - - /** - * Signifies that peer connection is idle. - */ - IDLE, - - /** - * Signifies that connection is initiated. - */ - CONNECT, - - /** - * Signifies that state is active and connection can be established. - */ - ACTIVE, - - /** - * Signifies that open is sent and anticipating reply. - */ - OPENSENT, - - /** - * Signifies that peer sent the open message as reply. - */ - OPENCONFIRM, - - /** - * Signifies that all the negotiation is successful and ready to exchange other messages. - */ - ESTABLISHED, - - /** - * Signifies that invalid state. - */ - INVALID - } - - /** - * Returns the connection State information of the peer. - * - * @return - * enum state is returned - */ - State getState(); - - /** - * Set the connection state information of the peer. - * - * @param state - * enum state - */ - void setState(State state); - - /** - * Returns the connection is initiated from us or not. - * - * @return - * true if the connection is initiated by this peer, false if it has been received. - */ - boolean getSelfInnitConnection(); - - /** - * Set the connection is initiated from us or not. - * - * @param selfInit - * true if the connection is initiated by this peer, false if it has been received. - */ - void setSelfInnitConnection(boolean selfInit); - - /** - * Returns the AS number to which this peer belongs. - * - * @return - * AS number - */ - int getAsNumber(); - - /** - * Set the AS number to which this peer belongs. - * - * @param asNumber - * AS number - */ - void setAsNumber(int asNumber); - - /** - * Get the keep alive timer value configured. - * - * @return - * keep alive timer value in seconds - */ - short getHoldtime(); - - /** - * Set the keep alive timer value. - * - * @param holdTime - * keep alive timer value in seconds - */ - void setHoldtime(short holdTime); - - /** - * Return the connection type eBGP or iBGP. - * - * @return - * true if iBGP, false if it is eBGP - */ - boolean getIsIBgp(); - - /** - * Set the connection type eBGP or iBGP. - * - * @param isIBgp - * true if iBGP, false if it is eBGP - */ - void setIsIBgp(boolean isIBgp); - - /** - * Return the peer router IP address. - * - * @return - * IP address in string format - */ - String getPeerRouterId(); - - /** - * Set the peer router IP address. - * - * @param peerId - * IP address in string format - */ - void setPeerRouterId(String peerId); - - /** - * Set the peer router IP address and AS number. - * - * @param peerId - * IP address in string format - * @param asNumber - * AS number - */ - void setPeerRouterId(String peerId, int asNumber); - - /** - * Set the peer connect instance. - * - * @param connectpeer connect peer instance - */ - void setConnectPeer(BgpConnectPeer connectpeer); - - /** - * Get the peer connect instance. - * - * @return peer connect instance - */ - BgpConnectPeer connectPeer(); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java deleted file mode 100755 index 895cc145..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgp.controller; - -/** - * Responsible for keeping track of the current set BGPLS peers connected to the system. - * - */ -public interface BgpPeerManager { - - /** - * Add connected peer. - * - * @param bgpId BGP ID to add - * @param bgpPeer BGp peer instance - * - * @return false if peer already exist, otherwise true - */ - public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer); - - /** - * Validate wheather peer is connected. - * - * @param bgpId BGP ID to validate - * - * @return true if peer exist, otherwise false - */ - public boolean isPeerConnected(BgpId bgpId); - - /** - * Remove connected peer. - * - * @param bgpId BGP ID - */ - public void removeConnectedPeer(BgpId bgpId); - - /** - * Gets connected peer. - * - * @param bgpId BGP ID - * @return BGPPeer the connected peer, otherwise null - */ - public BgpPeer getPeer(BgpId bgpId); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java deleted file mode 100755 index a21a23d2..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.onosproject.bgp.controller; - -import org.onosproject.bgpio.protocol.BgpVersion; - -/** - * Abstraction of an BGP session info. Maintian session parameters obtained during session creation. - */ -public interface BgpSessionInfo { - /** - * Gets the bgp session type iBGP/eBGP. - * - * @return isiBGPSession, true if session is of type internal, otherwise false. - */ - boolean isIbgpSession(); - - /** - * Gets the negotiated hold time for the session. - * - * @return negotiated hold time. - */ - short negotiatedholdTime(); - - /** - * Gets the BGP ID of BGP peer. - * - * @return bgp ID. - */ - BgpId remoteBgpId(); - - /** - * Gets the BGP version of peer. - * - * @return bgp version. - */ - BgpVersion remoteBgpVersion(); - - /** - * Gets the BGP remote bgp AS number. - * - * @return remoteBgpASNum peer AS number. - */ - long remoteBgpASNum(); - - /** - * Gets the BGP peer hold time. - * - * @return bgp hold time. - */ - short remoteBgpHoldTime(); - - /** - * Gets the BGP version for this bgp peer. - * - * @return bgp identifier. - */ - int remoteBgpIdentifier(); -} diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java deleted file mode 100755 index 4dd775b8..00000000 --- a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * BGP controller API. - */ -package org.onosproject.bgp.controller; diff --git a/framework/src/onos/bgp/bgpio/pom.xml b/framework/src/onos/bgp/bgpio/pom.xml deleted file mode 100755 index 5d67f18c..00000000 --- a/framework/src/onos/bgp/bgpio/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 4.0.0 - - - org.onosproject - onos-bgp - 1.4.0-SNAPSHOT - ../pom.xml - - - onos-bgpio - bundle - - ONOS BGPio Protocol subsystem - - - - org.onosproject - onos-api - - - org.onosproject - onlab-osgi - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-annotations - - - - org.osgi - org.osgi.core - - - org.apache.karaf.shell - org.apache.karaf.shell.console - - - org.apache.felix - org.apache.felix.scr.annotations - - - - - - - org.apache.felix - maven-bundle-plugin - - - - - diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java deleted file mode 100755 index d0890320..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.exceptions; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Custom Exception for BGP IO. - */ -public class BgpParseException extends Exception { - - private static final long serialVersionUID = 1L; - private byte errorCode; - private byte errorSubCode; - private ChannelBuffer data; - - /** - * Default constructor to create a new exception. - */ - public BgpParseException() { - super(); - } - - /** - * Constructor to create exception from message and cause. - * - * @param message the detail of exception in string - * @param cause underlying cause of the error - */ - public BgpParseException(final String message, final Throwable cause) { - super(message, cause); - } - - /** - * Constructor to create exception from message. - * - * @param message the detail of exception in string - */ - public BgpParseException(final String message) { - super(message); - } - - /** - * Constructor to create exception from cause. - * - * @param cause underlying cause of the error - */ - public BgpParseException(final Throwable cause) { - super(cause); - } - - /** - * Constructor to create exception from error code and error subcode. - * - * @param errorCode error code of BGP message - * @param errorSubCode error subcode of BGP message - * @param data error data of BGP message - */ - public BgpParseException(final byte errorCode, final byte errorSubCode, final ChannelBuffer data) { - super(); - this.errorCode = errorCode; - this.errorSubCode = errorSubCode; - this.data = data; - } - - /** - * Returns errorcode for this exception. - * - * @return errorcode for this exception - */ - public byte getErrorCode() { - return this.errorCode; - } - - /** - * Returns error Subcode for this exception. - * - * @return error Subcode for this exception - */ - public byte getErrorSubCode() { - return this.errorSubCode; - } - - /** - * Returns error data for this exception. - * - * @return error data for this exception - */ - public ChannelBuffer getData() { - return this.data; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java deleted file mode 100755 index 78b28072..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * BGP custom exceptions. - */ -package org.onosproject.bgpio.exceptions; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java deleted file mode 100755 index eb18c7d1..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.ver4.BgpFactoryVer4; -import org.onosproject.bgpio.types.BgpHeader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstraction to provide the version for BGP. - */ -public final class BgpFactories { - - protected static final Logger log = LoggerFactory.getLogger(BgpFactories.class); - - private static final GenericReader GENERIC_READER = new GenericReader(); - - private BgpFactories() { - } - - /** - * Returns the instance of BGP Version. - * - * @param version BGP version - * @return BGP version - */ - public static BgpFactory getFactory(BgpVersion version) { - switch (version) { - case BGP_4: - return BgpFactoryVer4.INSTANCE; - default: - throw new IllegalArgumentException("[BgpFactory:]Unknown version: " + version); - } - } - - /** - * Reader class for reading BGP messages from channel buffer. - * - */ - private static class GenericReader implements BgpMessageReader { - - @Override - public BgpMessage readFrom(ChannelBuffer bb, BgpHeader bgpHeader) - throws BgpParseException { - BgpFactory factory; - - if (!bb.readable()) { - log.error("Empty message received"); - throw new BgpParseException("Empty message received"); - } - // TODO: Currently only BGP version 4 is supported - factory = org.onosproject.bgpio.protocol.ver4.BgpFactoryVer4.INSTANCE; - return factory.getReader().readFrom(bb, bgpHeader); - } - } - - /** - * Returns BGP messsage generic reader. - * - * @return bgp message generic reader - */ - public static BgpMessageReader getGenericReader() { - return GENERIC_READER; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java deleted file mode 100755 index 11a85ff8..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -/** - * Abstraction of an message factory providing builder functions to BGP messages - * and objects. - * - */ -public interface BgpFactory { - - /** - * Gets the builder object for a open message. - * - * @return builder object for open message - */ - BgpOpenMsg.Builder openMessageBuilder(); - - /** - * Gets the builder object for a keepalive message. - * - * @return builder object for keepalive message - */ - BgpKeepaliveMsg.Builder keepaliveMessageBuilder(); - - /** - * Gets the builder object for a notification message. - * - * @return builder object for notification message. - */ - BgpNotificationMsg.Builder notificationMessageBuilder(); - - /** - * Gets the BGP message reader. - * - * @return BGP message reader - */ - BgpMessageReader getReader(); - - /** - * Returns BGP version. - * - * @return BGP version - */ - BgpVersion getVersion(); -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java deleted file mode 100644 index 0cb776a0..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.types.BgpHeader; - -/** - * Abstraction of an entity providing BGP Keepalive Message. - */ -public interface BgpKeepaliveMsg extends BgpMessage { - - @Override - BgpVersion getVersion(); - - @Override - BgpType getType(); - - @Override - void writeTo(ChannelBuffer channelBuffer); - - @Override - BgpHeader getHeader(); - - /** - * Builder interface with get and set functions to build Keepalive message. - */ - interface Builder extends BgpMessage.Builder { - @Override - BgpKeepaliveMsg build(); - - @Override - Builder setHeader(BgpHeader bgpMsgHeader); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java deleted file mode 100644 index dd8857a7..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; -import org.onosproject.bgpio.types.RouteDistinguisher; - -/** - * Abstraction of an entity providing BGP-LS NLRI. - */ -public interface BgpLSNlri { - /** - * Returns NlriType of BGP-LS NLRI. - * - * @return NlriType of BGP-LS NLRI - */ - NlriType getNlriType(); - - /** - * Returns Identifier in Nlri. - * - * @return Identifier in Nlri - */ - long getIdentifier(); - - /** - * Returns Protocol Id in Nlri. - * - * @return Protocol Id in Nlri - * @throws BgpParseException while getting protocol ID - */ - ProtocolType getProtocolId() throws BgpParseException; - - /** - * Returns Route distinguisher in Nlri. - * - * @return Route distinguisher in Nlri - */ - RouteDistinguisher getRouteDistinguisher(); -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java deleted file mode 100644 index 3924a13b..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import java.util.List; - -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors; - -/** - * Abstraction of an entity providing BGP-LS Link NLRI. - */ -public interface BgpLinkLsNlri extends BgpLSNlri { - /** - * Returns local node descriptors. - * - * @return local node descriptors - */ - NodeDescriptors localNodeDescriptors(); - - /** - * Returns remote node descriptors. - * - * @return remote node descriptors - */ - NodeDescriptors remoteNodeDescriptors(); - - /** - * Returns link descriptors. - * - * @return link descriptors - */ - List linkDescriptors(); -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java deleted file mode 100644 index f1e1b96f..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; - -/** - * Abstraction of an entity providing BGP Messages. - */ -public interface BgpMessage extends Writeable { - /** - * Returns BGP Header of BGP Message. - * - * @return BGP Header of BGP Message - */ - BgpHeader getHeader(); - - /** - * Returns version of BGP Message. - * - * @return version of BGP Message - */ - BgpVersion getVersion(); - - /** - * Returns BGP Type of BGP Message. - * - * @return BGP Type of BGP Message - */ - BgpType getType(); - - @Override - void writeTo(ChannelBuffer cb) throws BgpParseException; - - /** - * Builder interface with get and set functions to build BGP Message. - */ - interface Builder { - /** - * Builds BGP Message. - * - * @return BGP Message - * @throws BgpParseException while building bgp message - */ - BgpMessage build() throws BgpParseException; - - /** - * Sets BgpHeader and return its builder. - * - * @param bgpMsgHeader BGP Message Header - * @return builder by setting BGP message header - */ - Builder setHeader(BgpHeader bgpMsgHeader); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java deleted file mode 100755 index b8318b29..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; - -/** - * Abstraction of an entity providing BGP Message Reader. - */ -public interface BgpMessageReader { - - /** - * Reads the Objects in the BGP Message and Returns BGP Message. - * - * @param cb Channel Buffer - * @param bgpHeader BGP message header - * @return BGP Message - * @throws BgpParseException while parsing BGP message. - */ - T readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException; -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java deleted file mode 100644 index bb75b5ea..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; - -/** - * Abstraction of an entity providing BGP Message Writer. - */ -public interface BgpMessageWriter { - - /** - * Writes the Objects of the BGP Message into Channel Buffer. - * - * @param cb Channel Buffer - * @param message BGP Message - * @throws BgpParseException - * While writing message - */ - void write(ChannelBuffer cb, T message) throws BgpParseException; -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java deleted file mode 100644 index 13ef5cc5..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; - -/** - * Abstraction of an entity providing BGP-LS Node NLRI. - */ -public interface BgpNodeLSNlri extends BgpLSNlri { - /** - * Returns local node descriptors. - * - * @return local node descriptors - */ - BgpNodeLSIdentifier getLocalNodeDescriptors(); -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java deleted file mode 100644 index e3361aa7..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.onosproject.bgpio.exceptions.BgpParseException; - -/** - * Abstraction of an entity providing BGP notification message. - */ -public interface BgpNotificationMsg extends BgpMessage { - /** - * Returns errorCode in notification message. - * - * @return errorCode in notification message - */ - byte getErrorCode(); - - /** - * Returns error subCode in notification message. - * - * @return error subCode in notification message - */ - byte getErrorSubCode(); - - /** - * Returns error data in notification message. - * - * @return error data in notification message - */ - byte[] getData(); - - /** - * Builder interface with get and set functions to build notification message. - */ - public interface Builder extends BgpMessage.Builder { - - @Override - BgpNotificationMsg build() throws BgpParseException; - - /** - * Sets errorCode in notification message and return its builder. - * - * @param errorCode in notification message - * @return builder by setting errorCode in notification message - */ - Builder setErrorCode(byte errorCode); - - /** - * Sets error subCode in notification message and return its builder. - * - * @param errorSubCode in notification message - * @return builder by setting error subCode in notification message - */ - Builder setErrorSubCode(byte errorSubCode); - - /** - * Sets error data in notification message and return its builder. - * - * @param data in notification message - * @return builder by setting Data in notification message - */ - Builder setData(byte[] data); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java deleted file mode 100644 index 94ec2235..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import java.util.LinkedList; - -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.types.BgpValueType; - -/** - * Abstraction of an entity providing BGP Open Message. - */ -public interface BgpOpenMsg extends BgpMessage { - - @Override - BgpHeader getHeader(); - - @Override - BgpVersion getVersion(); - - @Override - BgpType getType(); - - /** - * Returns hold time of Open Message. - * - * @return hold time of Open Message - */ - short getHoldTime(); - - /** - * Returns AS Number of Open Message. - * - * @return AS Number of Open Message - */ - short getAsNumber(); - - /** - * Returns BGP Identifier of Open Message. - * - * @return BGP Identifier of Open Message - */ - int getBgpId(); - - /** - * Returns capabilities of Open Message. - * - * @return capabilities of Open Message - */ - LinkedList getCapabilityTlv(); - - /** - * Builder interface with get and set functions to build Open message. - */ - interface Builder extends BgpMessage.Builder { - - @Override - BgpOpenMsg build() throws BgpParseException; - - /** - * Sets hold time in Open Message and return its builder. - * - * @param holdtime hold timer value in open message - * @return builder by setting hold time - */ - Builder setHoldTime(short holdtime); - - /** - * Sets AS number in Open Message and return its builder. - * - * @param asNumber as number in open message - * @return builder by setting asNumber - */ - Builder setAsNumber(short asNumber); - - /** - * Sets BGP Identifier in Open Message and return its builder. - * - * @param bgpId BGP Identifier in open message - * @return builder by setting BGP Identifier - */ - Builder setBgpId(int bgpId); - - /** - * Sets capabilities in Open Message and return its builder. - * - * @param capabilityTlv capabilities in open message - * @return builder by setting capabilities - */ - Builder setCapabilityTlv(LinkedList capabilityTlv); - - /** - * Sets isLargeAsCapabilityTlvSet and return its builder. - * - * @param isLargeAsCapabilitySet - * boolean value to know whether large AS capability is set or not - * @return builder by setting capabilities - */ - Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet); - - /** - * Sets isLsCapabilityTlvSet and return its builder. - * - * @param isLsCapabilitySet - * boolean value to know whether LS capability is set or not - * @return builder by setting capabilities - */ - Builder setLsCapabilityTlv(boolean isLsCapabilitySet); - - @Override - Builder setHeader(BgpHeader bgpMsgHeader); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java deleted file mode 100644 index 54bcdba3..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import java.util.List; - -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors; - -/** - * Abstraction of an entity providing BGP-LS Prefix NLRI. - */ -public interface BgpPrefixLSNlri extends BgpLSNlri { - /** - * Returns local node descriptors. - * - * @return local node descriptors - */ - NodeDescriptors getLocalNodeDescriptors(); - - /** - * Returns list of Prefix descriptor. - * - * @return list of Prefix descriptor - */ - List getPrefixdescriptor(); -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java deleted file mode 100755 index b90721d5..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -/** - * Enum to Provide the Different types of BGP messages. - */ -public enum BgpType { - - NONE(0), OPEN(1), UPDATE(2), NOTIFICATION(3), KEEP_ALIVE(4); - - int value; - - /** - * Assign value with the value val as the types of BGP message. - * - * @param val type of BGP message - */ - BgpType(int val) { - value = val; - } - - /** - * Returns value as type of BGP message. - * - * @return value type of BGP message - */ - public byte getType() { - return (byte) value; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java deleted file mode 100644 index d79a4236..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -import java.util.List; - -import org.onlab.packet.IpPrefix; -import org.onosproject.bgpio.protocol.ver4.BgpPathAttributes; - -/** - * Abstraction of an entity providing BGP Update Message. - */ -public interface BgpUpdateMsg extends BgpMessage { - /** - * Returns path attributes in BGP Update Message. - * - * @return path attributes in BGP Update Message - */ - BgpPathAttributes bgpPathAttributes(); - - /** - * Returns withdrawn Routes. - * - * @return withdrawn Routes - */ - List withdrawnRoutes(); - - /** - * Returns NLRI list of prefix. - * - * @return NLRI list of prefix - */ - List nlri(); -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java deleted file mode 100755 index b1f037f4..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -/** - * Enum to provide BGP Message Version. - */ -public enum BgpVersion { - - BGP_4(4); - - public final int packetVersion; - - /** - * Assign BGP PacketVersion with specified packetVersion. - * - * @param packetVersion version of BGP - */ - BgpVersion(final int packetVersion) { - this.packetVersion = packetVersion; - } - - /** - * Returns Packet version of BGP Message. - * - * @return packetVersion - */ - public int getPacketVersion() { - return packetVersion; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java deleted file mode 100644 index 0e531d64..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -/** - * Provides Abstraction of IGP RouterID TLV. - */ -public interface IGPRouterID { -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java deleted file mode 100644 index 535ba71d..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -/** - * Enum to Provide the Different BGP-LS NLRI types. - */ -public enum NlriType { - - NODE(1), LINK(2), PREFIX_IPV4(3), PREFIX_IPV6(4); - - int value; - - /** - * Assign value with the value as the LINK-STATE NLRI type. - * - * @param value LINK-STATE NLRI type - */ - NlriType(int value) { - this.value = value; - } - - /** - * Returns value as LINK-STATE NLRI type. - * - * @return value LINK-STATE NLRI type - */ - public byte getType() { - return (byte) value; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java deleted file mode 100755 index 1c6f7fc2..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; - -/** - * Abstraction of an entity providing functionality to write byte streams of - * Messages to channel buffer. - */ -public interface Writeable { - - /** - * Writes byte streams of messages to channel buffer. - * - * @param cb channelBuffer - * @throws BgpParseException when error occurs while writing BGP message to channel buffer - */ - void writeTo(ChannelBuffer cb) throws BgpParseException; -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java deleted file mode 100644 index 3967a221..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.IPv4AddressTlv; -import org.onosproject.bgpio.types.IPv6AddressTlv; -import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv; -import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.UnSupportedAttribute; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; - -/** - * Implementation of local node descriptors, remote node descriptors and link descriptors. - */ -public class BgpLinkLSIdentifier implements Comparable { - private static final Logger log = LoggerFactory.getLogger(BgpLinkLSIdentifier.class); - public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259; - public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260; - public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261; - public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262; - - private NodeDescriptors localNodeDescriptors; - private NodeDescriptors remoteNodeDescriptors; - private List linkDescriptor; - - /** - * Initialize fields. - */ - public BgpLinkLSIdentifier() { - this.localNodeDescriptors = null; - this.remoteNodeDescriptors = null; - this.linkDescriptor = null; - } - - /** - * Constructors to initialize parameters. - * - * @param localNodeDescriptors local node descriptors - * @param remoteNodeDescriptors remote node descriptors - * @param linkDescriptor link descriptors - */ - public BgpLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors, - LinkedList linkDescriptor) { - this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors); - this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors); - this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor); - } - - /** - * Reads channel buffer and parses link identifier. - * - * @param cb ChannelBuffer - * @param protocolId in linkstate nlri - * @return object of BGPLinkLSIdentifier - * @throws BgpParseException while parsing link identifier - */ - public static BgpLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BgpParseException { - //Parse local node descriptor - NodeDescriptors localNodeDescriptors = new NodeDescriptors(); - localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId); - - //Parse remote node descriptor - NodeDescriptors remoteNodeDescriptors = new NodeDescriptors(); - remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId); - - //Parse link descriptor - LinkedList linkDescriptor = new LinkedList<>(); - linkDescriptor = parseLinkDescriptors(cb); - return new BgpLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor); - } - - /** - * Parses Local/Remote node descriptors. - * - * @param cb ChannelBuffer - * @param desType descriptor type - * @param protocolId protocol identifier - * @return object of NodeDescriptors - * @throws BgpParseException while parsing Local/Remote node descriptors - */ - public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId) - throws BgpParseException { - log.debug("parse Node descriptors"); - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT)); - } - NodeDescriptors nodeIdentifier = new NodeDescriptors(); - ChannelBuffer tempCb = cb.readBytes(length); - - if (type == desType) { - nodeIdentifier = NodeDescriptors.read(tempCb, length, desType, protocolId); - } else { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); - } - return nodeIdentifier; - } - - /** - * Parses link descriptors. - * - * @param cb ChannelBuffer - * @return list of link descriptors - * @throws BgpParseException while parsing link descriptors - */ - public static LinkedList parseLinkDescriptors(ChannelBuffer cb) throws BgpParseException { - LinkedList linkDescriptor = new LinkedList<>(); - BgpValueType tlv = null; - int count = 0; - - while (cb.readableBytes() > 0) { - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT)); - } - ChannelBuffer tempCb = cb.readBytes(length); - switch (type) { - case LinkLocalRemoteIdentifiersTlv.TYPE: - tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb); - break; - case IPV4_INTERFACE_ADDRESS_TYPE: - tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE); - break; - case IPV4_NEIGHBOR_ADDRESS_TYPE: - tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE); - break; - case IPV6_INTERFACE_ADDRESS_TYPE: - tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE); - break; - case IPV6_NEIGHBOR_ADDRESS_TYPE: - tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE); - break; - case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: - tlv = BgpAttrNodeMultiTopologyId.read(tempCb); - count = count++; - //MultiTopologyId TLV cannot repeat more than once - if (count > 1) { - //length + 4 implies data contains type, length and value - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length - + Constants.TYPE_AND_LEN_AS_SHORT)); - } - break; - default: - UnSupportedAttribute.skipBytes(tempCb, length); - } - linkDescriptor.add(tlv); - } - return linkDescriptor; - } - - /** - * Returns local node descriptors. - * - * @return local node descriptors - */ - public NodeDescriptors localNodeDescriptors() { - return this.localNodeDescriptors; - } - - /** - * Returns remote node descriptors. - * - * @return remote node descriptors - */ - public NodeDescriptors remoteNodeDescriptors() { - return this.remoteNodeDescriptors; - } - - /** - * Returns link descriptors. - * - * @return link descriptors - */ - public List linkDescriptors() { - return this.linkDescriptor; - } - - @Override - public int hashCode() { - return Objects.hash(linkDescriptor, localNodeDescriptors, remoteNodeDescriptors); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof BgpLinkLSIdentifier) { - int countObjSubTlv = 0; - int countOtherSubTlv = 0; - boolean isCommonSubTlv = true; - BgpLinkLSIdentifier other = (BgpLinkLSIdentifier) obj; - Iterator objListIterator = other.linkDescriptor.iterator(); - countOtherSubTlv = other.linkDescriptor.size(); - countObjSubTlv = linkDescriptor.size(); - if (countObjSubTlv != countOtherSubTlv) { - return false; - } else { - while (objListIterator.hasNext() && isCommonSubTlv) { - BgpValueType subTlv = objListIterator.next(); - if (linkDescriptor.contains(subTlv) && other.linkDescriptor.contains(subTlv)) { - isCommonSubTlv = Objects.equals(linkDescriptor.get(linkDescriptor.indexOf(subTlv)), - other.linkDescriptor.get(other.linkDescriptor.indexOf(subTlv))); - } else { - isCommonSubTlv = false; - } - } - return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors) - && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors); - } - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("localNodeDescriptors", localNodeDescriptors) - .add("remoteNodeDescriptors", remoteNodeDescriptors) - .add("linkDescriptor", linkDescriptor) - .toString(); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - int result = this.localNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).localNodeDescriptors); - if (result != 0) { - return result; - } else if (this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors) != 0) { - return this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors); - } else { - int countOtherSubTlv = ((BgpLinkLSIdentifier) o).linkDescriptor.size(); - int countObjSubTlv = linkDescriptor.size(); - if (countOtherSubTlv != countObjSubTlv) { - if (countOtherSubTlv > countObjSubTlv) { - return 1; - } else { - return -1; - } - } - ListIterator listIterator = linkDescriptor.listIterator(); - ListIterator listIteratorOther = ((BgpLinkLSIdentifier) o).linkDescriptor.listIterator(); - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - BgpValueType tlv1 = listIteratorOther.next(); - if (linkDescriptor.contains(tlv) && ((BgpLinkLSIdentifier) o).linkDescriptor.contains(tlv1)) { - int res = linkDescriptor.get(linkDescriptor.indexOf(tlv)).compareTo( - ((BgpLinkLSIdentifier) o).linkDescriptor.get(((BgpLinkLSIdentifier) o).linkDescriptor - .indexOf(tlv1))); - if (res != 0) { - return res; - } - } - } - } - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java deleted file mode 100755 index 01d369e4..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpLinkLsNlri; -import org.onosproject.bgpio.protocol.NlriType; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.RouteDistinguisher; -import org.onosproject.bgpio.util.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Link LS NLRI. - */ -public class BgpLinkLsNlriVer4 implements BgpLinkLsNlri { - - /* - * REFERENCE : draft-ietf-idr-ls-distribution-11 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+ - | Protocol-ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | - | (64 bits) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Local Node Descriptors (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Remote Node Descriptors (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Link Descriptors (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure : The Link NLRI format - */ - private static final Logger log = LoggerFactory.getLogger(BgpLinkLsNlriVer4.class); - public static final int LINK_NLRITYPE = 2; - - private BgpLinkLSIdentifier linkLSIdentifier; - private byte protocolId; - private long identifier; - private RouteDistinguisher routeDistinguisher; - private boolean isVpn; - - /** - * Initialize fields. - */ - public BgpLinkLsNlriVer4() { - this.protocolId = 0; - this.identifier = 0; - this.linkLSIdentifier = null; - this.routeDistinguisher = null; - this.isVpn = false; - } - - /** - * Constructor to initialize parameters for BGP LinkLSNlri. - * - * @param protocolId protocol Id - * @param identifier field in BGP LinkLSNlri - * @param linkLSIdentifier link LS identifier - * @param routeDistinguisher route distinguisher from message - * @param isVpn vpn info availability in message - */ - public BgpLinkLsNlriVer4(byte protocolId, long identifier, BgpLinkLSIdentifier linkLSIdentifier, - RouteDistinguisher routeDistinguisher, boolean isVpn) { - this.protocolId = protocolId; - this.identifier = identifier; - this.linkLSIdentifier = linkLSIdentifier; - this.routeDistinguisher = routeDistinguisher; - this.isVpn = isVpn; - } - - /** - * Reads from channelBuffer and parses Link LS Nlri. - * - * @param cb ChannelBuffer - * @param afi Address Family Identifier - * @param safi Subsequent Address Family Identifier - * @return object of this class - * @throws BgpParseException while parsing Link LS NLRI - */ - public static BgpLinkLsNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { - boolean isVpn = false; - RouteDistinguisher routeDistinguisher = null; - if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { - routeDistinguisher = new RouteDistinguisher(); - routeDistinguisher = RouteDistinguisher.read(cb); - isVpn = true; - } else { - isVpn = false; - } - byte protocolId = cb.readByte(); - long identifier = cb.readLong(); - - BgpLinkLSIdentifier linkLSIdentifier = new BgpLinkLSIdentifier(); - linkLSIdentifier = BgpLinkLSIdentifier.parseLinkIdendifier(cb, protocolId); - return new BgpLinkLsNlriVer4(protocolId, identifier, linkLSIdentifier, routeDistinguisher, isVpn); - } - - @Override - public NlriType getNlriType() { - return NlriType.LINK; - } - - @Override - public long getIdentifier() { - return this.identifier; - } - - /** - * Set the link LS identifier. - * - * @param linkLSIdentifier link LS identifier to set - */ - public void setLinkLSIdentifier(BgpLinkLSIdentifier linkLSIdentifier) { - this.linkLSIdentifier = linkLSIdentifier; - } - - @Override - public ProtocolType getProtocolId() throws BgpParseException { - switch (protocolId) { - case Constants.ISIS_LEVELONE: - return ProtocolType.ISIS_LEVEL_ONE; - case Constants.ISIS_LEVELTWO: - return ProtocolType.ISIS_LEVEL_TWO; - case Constants.OSPFV2: - return ProtocolType.OSPF_V2; - case Constants.DIRECT: - return ProtocolType.DIRECT; - case Constants.STATIC_CONFIGURATION: - return ProtocolType.STATIC_CONFIGURATION; - case Constants.OSPFV3: - return ProtocolType.OSPF_V3; - default: - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); - } - } - - @Override - public NodeDescriptors localNodeDescriptors() { - return this.linkLSIdentifier.localNodeDescriptors(); - } - - @Override - public NodeDescriptors remoteNodeDescriptors() { - return this.linkLSIdentifier.remoteNodeDescriptors(); - } - - /** - * Returns whether VPN is present or not. - * - * @return whether VPN is present or not - */ - public boolean isVpnPresent() { - return this.isVpn; - } - - @Override - public RouteDistinguisher getRouteDistinguisher() { - return this.routeDistinguisher; - } - - /** - * Returns link identifier. - * - * @return link identifier - */ - public BgpLinkLSIdentifier getLinkIdentifier() { - return this.linkLSIdentifier; - } - - @Override - public List linkDescriptors() { - return this.linkLSIdentifier.linkDescriptors(); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("protocolId", protocolId) - .add("identifier", identifier) - .add("RouteDistinguisher ", routeDistinguisher) - .add("linkLSIdentifier", linkLSIdentifier) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java deleted file mode 100644 index 6c2c96d9..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.util.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Node Identifier which includes local node descriptor/remote node descriptors. - */ -public class BgpNodeLSIdentifier implements Comparable { - - private static final Logger log = LoggerFactory.getLogger(BgpNodeLSIdentifier.class); - private NodeDescriptors nodeDescriptors; - - /** - * Resets fields. - */ - public BgpNodeLSIdentifier() { - this.nodeDescriptors = null; - } - - /** - * Constructor to initialize fields. - * - * @param nodeDescriptors local/remote node descriptor - */ - public BgpNodeLSIdentifier(NodeDescriptors nodeDescriptors) { - this.nodeDescriptors = nodeDescriptors; - } - - /** - * Parse local node descriptors. - * - * @param cb ChannelBuffer - * @param protocolId protocol identifier - * @return object of this BGPNodeLSIdentifier - * @throws BgpParseException while parsing local node descriptors - */ - public static BgpNodeLSIdentifier parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId) - throws BgpParseException { - log.debug("parse Local node descriptor"); - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN)); - } - NodeDescriptors nodeDescriptors = new NodeDescriptors(); - ChannelBuffer tempCb = cb.readBytes(length); - - if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) { - nodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId); - } else { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); - } - return new BgpNodeLSIdentifier(nodeDescriptors); - } - - /** - * Returns node descriptors. - * - * @return node descriptors - */ - public NodeDescriptors getNodedescriptors() { - return this.nodeDescriptors; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof BgpNodeLSIdentifier) { - BgpNodeLSIdentifier other = (BgpNodeLSIdentifier) obj; - return Objects.equals(nodeDescriptors, other.nodeDescriptors); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(nodeDescriptors); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("NodeDescriptors", nodeDescriptors) - .toString(); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return this.nodeDescriptors.compareTo(((BgpNodeLSIdentifier) o).nodeDescriptors); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java deleted file mode 100644 index b27096cf..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpNodeLSNlri; -import org.onosproject.bgpio.protocol.NlriType; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.RouteDistinguisher; -import org.onosproject.bgpio.util.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Node LS NLRI. - */ -public class BgpNodeLSNlriVer4 implements BgpNodeLSNlri { - - /* - *REFERENCE : draft-ietf-idr-ls-distribution-11 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+ - | Protocol-ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | - | (64 bits) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Local Node Descriptors (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure : The Node NLRI format - */ - - protected static final Logger log = LoggerFactory.getLogger(BgpNodeLSNlriVer4.class); - - public static final int NODE_NLRITYPE = 1; - public static final int IDENTIFIER_LENGTH = 16; - private long identifier; - private byte protocolId; - private BgpNodeLSIdentifier localNodeDescriptors; - private RouteDistinguisher routeDistinguisher; - private boolean isVpn; - - /** - * Enum to provide PROTOCOLTYPE. - */ - public enum ProtocolType { - ISIS_LEVEL_ONE(1), ISIS_LEVEL_TWO(2), OSPF_V2(3), DIRECT(4), STATIC_CONFIGURATION(5), OSPF_V3(6); - int value; - - /** - * Assign val with the value as the protocol type. - * - * @param val protocol type - */ - ProtocolType(int val) { - value = val; - } - - /** - * Returns value of protocol type. - * - * @return protocol type - */ - public byte getType() { - return (byte) value; - } - } - - /** - * Reset fields. - */ - public BgpNodeLSNlriVer4() { - this.identifier = 0; - this.protocolId = 0; - this.localNodeDescriptors = null; - this.routeDistinguisher = null; - this.isVpn = false; - } - - /** - * Constructors to initialize its parameters. - * - * @param identifier of LinkState Nlri - * @param protocolId of LinkState Nlri - * @param localNodeDescriptors local node descriptors - * @param isVpn true if VPN info is present - * @param routeDistinguisher unique for each VPN - */ - public BgpNodeLSNlriVer4(long identifier, byte protocolId, BgpNodeLSIdentifier localNodeDescriptors, boolean isVpn, - RouteDistinguisher routeDistinguisher) { - this.identifier = identifier; - this.protocolId = protocolId; - this.localNodeDescriptors = localNodeDescriptors; - this.routeDistinguisher = routeDistinguisher; - this.isVpn = isVpn; - } - - /** - * Reads from channelBuffer and parses Node LS Nlri. - * - * @param cb ChannelBuffer - * @param afi Address Family Identifier - * @param safi Subsequent Address Family Identifier - * @return object of this class - * @throws BgpParseException while parsing node descriptors - */ - public static BgpNodeLSNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { - boolean isVpn = false; - RouteDistinguisher routeDistinguisher = null; - if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { - routeDistinguisher = new RouteDistinguisher(); - routeDistinguisher = RouteDistinguisher.read(cb); - isVpn = true; - } else { - isVpn = false; - } - byte protocolId = cb.readByte(); - long identifier = cb.readLong(); - - // Parse Local Node Descriptors - BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(); - localNodeDescriptors = BgpNodeLSIdentifier.parseLocalNodeDescriptors(cb, protocolId); - return new BgpNodeLSNlriVer4(identifier, protocolId, localNodeDescriptors, isVpn, routeDistinguisher); - } - - @Override - public NlriType getNlriType() { - return NlriType.NODE; - } - - @Override - public BgpNodeLSIdentifier getLocalNodeDescriptors() { - return this.localNodeDescriptors; - } - - /** - * Returns whether VPN is present or not. - * - * @return whether VPN is present or not - */ - public boolean isVpnPresent() { - return this.isVpn; - } - - @Override - public RouteDistinguisher getRouteDistinguisher() { - return this.routeDistinguisher; - } - - @Override - public long getIdentifier() { - return this.identifier; - } - - /** - * Set the node LS identifier. - * - * @param localNodeDescriptors node LS identifier to set - */ - public void setNodeLSIdentifier(BgpNodeLSIdentifier localNodeDescriptors) { - this.localNodeDescriptors = localNodeDescriptors; - } - - @Override - public ProtocolType getProtocolId() throws BgpParseException { - switch (protocolId) { - case Constants.ISIS_LEVELONE: - return ProtocolType.ISIS_LEVEL_ONE; - case Constants.ISIS_LEVELTWO: - return ProtocolType.ISIS_LEVEL_TWO; - case Constants.OSPFV2: - return ProtocolType.OSPF_V2; - case Constants.DIRECT: - return ProtocolType.DIRECT; - case Constants.STATIC_CONFIGURATION: - return ProtocolType.STATIC_CONFIGURATION; - case Constants.OSPFV3: - return ProtocolType.OSPF_V3; - default: - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); - } - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("protocolId", protocolId) - .add("identifier", identifier) - .add("RouteDistinguisher ", routeDistinguisher) - .add("localNodeDescriptors", localNodeDescriptors) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java deleted file mode 100644 index 49cb74bd..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpPrefixLSNlri; -import org.onosproject.bgpio.protocol.NlriType; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.RouteDistinguisher; -import org.onosproject.bgpio.util.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Prefix IPV4 LS NLRI. - */ -public class BgpPrefixIPv4LSNlriVer4 implements BgpPrefixLSNlri { - - /* - * REFERENCE : draft-ietf-idr-ls-distribution-11 - * 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+ - | Protocol-ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | - | (64 bits) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Local Node Descriptor (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // Prefix Descriptors (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure : The IPv4/IPv6 Topology Prefix NLRI format - */ - - protected static final Logger log = LoggerFactory.getLogger(BgpPrefixIPv4LSNlriVer4.class); - - public static final int PREFIX_IPV4_NLRITYPE = 3; - public static final int IDENTIFIER_LENGTH = 16; - private long identifier; - private byte protocolId; - private RouteDistinguisher routeDistinguisher; - private boolean isVpn; - private BgpPrefixLSIdentifier bgpPrefixLSIdentifier; - - /** - * Resets parameters. - */ - public BgpPrefixIPv4LSNlriVer4() { - this.identifier = 0; - this.protocolId = 0; - this.bgpPrefixLSIdentifier = null; - this.routeDistinguisher = null; - this.isVpn = false; - } - - /** - * Constructor to initialize parameters for BGP PrefixLSNlri. - * - * @param identifier field in BGP PrefixLSNlri - * @param protocolId protocol Id - * @param bgpPrefixLSIdentifier prefix LS Identifier - * @param routeDistinguisher RouteDistinguisher - * @param isVpn vpn availability in message - */ - public BgpPrefixIPv4LSNlriVer4(long identifier, byte protocolId, BgpPrefixLSIdentifier bgpPrefixLSIdentifier, - RouteDistinguisher routeDistinguisher, boolean isVpn) { - this.identifier = identifier; - this.protocolId = protocolId; - this.bgpPrefixLSIdentifier = bgpPrefixLSIdentifier; - this.routeDistinguisher = routeDistinguisher; - this.isVpn = isVpn; - } - - /** - * Reads from channelBuffer and parses Prefix LS Nlri. - * - * @param cb ChannelBuffer - * @param afi Address family identifier - * @param safi Subsequent address family identifier - * @return object of BGPPrefixIPv4LSNlriVer4 - * @throws BgpParseException while parsing Prefix LS Nlri - */ - public static BgpPrefixIPv4LSNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { - - boolean isVpn = false; - RouteDistinguisher routeDistinguisher = null; - if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { - routeDistinguisher = new RouteDistinguisher(); - routeDistinguisher = RouteDistinguisher.read(cb); - isVpn = true; - } else { - isVpn = false; - } - byte protocolId = cb.readByte(); - long identifier = cb.readLong(); - - BgpPrefixLSIdentifier bgpPrefixLSIdentifier = new BgpPrefixLSIdentifier(); - bgpPrefixLSIdentifier = BgpPrefixLSIdentifier.parsePrefixIdendifier(cb, protocolId); - return new BgpPrefixIPv4LSNlriVer4(identifier, protocolId, bgpPrefixLSIdentifier, routeDistinguisher, isVpn); - } - - @Override - public NlriType getNlriType() { - return NlriType.PREFIX_IPV4; - } - - @Override - public NodeDescriptors getLocalNodeDescriptors() { - return this.bgpPrefixLSIdentifier.getLocalNodeDescriptors(); - } - - @Override - public long getIdentifier() { - return this.identifier; - } - - /** - * Set the prefix LS identifier. - * - * @param bgpPrefixLSIdentifier prefix identifier to set - */ - public void setPrefixLSIdentifier(BgpPrefixLSIdentifier bgpPrefixLSIdentifier) { - this.bgpPrefixLSIdentifier = bgpPrefixLSIdentifier; - } - - @Override - public ProtocolType getProtocolId() throws BgpParseException { - switch (protocolId) { - case Constants.ISIS_LEVELONE: - return ProtocolType.ISIS_LEVEL_ONE; - case Constants.ISIS_LEVELTWO: - return ProtocolType.ISIS_LEVEL_TWO; - case Constants.OSPFV2: - return ProtocolType.OSPF_V2; - case Constants.DIRECT: - return ProtocolType.DIRECT; - case Constants.STATIC_CONFIGURATION: - return ProtocolType.STATIC_CONFIGURATION; - case Constants.OSPFV3: - return ProtocolType.OSPF_V3; - default: - throw new BgpParseException("protocol id not valid"); - } - } - - /** - * Returns whether VPN is present or not. - * - * @return whether VPN is present or not - */ - public boolean isVpnPresent() { - return this.isVpn; - } - - /** - * Returns Prefix Identifier. - * - * @return Prefix Identifier - */ - public BgpPrefixLSIdentifier getPrefixIdentifier() { - return this.bgpPrefixLSIdentifier; - } - - @Override - public RouteDistinguisher getRouteDistinguisher() { - return this.routeDistinguisher; - } - - @Override - public List getPrefixdescriptor() { - return this.bgpPrefixLSIdentifier.getPrefixdescriptor(); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("protocolId", protocolId) - .add("identifier", identifier) - .add("RouteDistinguisher ", routeDistinguisher) - .add("bgpPrefixLSIdentifier", bgpPrefixLSIdentifier) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java deleted file mode 100644 index d3beaaee..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.IPReachabilityInformationTlv; -import org.onosproject.bgpio.types.OSPFRouteTypeTlv; -import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; -import org.onosproject.bgpio.util.UnSupportedAttribute; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of Local node descriptors and prefix descriptors. - */ -public class BgpPrefixLSIdentifier implements Comparable { - - protected static final Logger log = LoggerFactory.getLogger(BgpPrefixLSIdentifier.class); - public static final int TYPE_AND_LEN = 4; - private NodeDescriptors localNodeDescriptors; - private List prefixDescriptor; - - /** - * Resets parameters. - */ - public BgpPrefixLSIdentifier() { - this.localNodeDescriptors = null; - this.prefixDescriptor = null; - } - - /** - * Constructor to initialize parameters. - * - * @param localNodeDescriptors Local node descriptors - * @param prefixDescriptor Prefix Descriptors - */ - public BgpPrefixLSIdentifier(NodeDescriptors localNodeDescriptors, List prefixDescriptor) { - this.localNodeDescriptors = localNodeDescriptors; - this.prefixDescriptor = prefixDescriptor; - } - - /** - * Reads the channel buffer and parses Prefix Identifier. - * - * @param cb ChannelBuffer - * @param protocolId protocol ID - * @return object of this class - * @throws BgpParseException while parsing Prefix Identifier - */ - public static BgpPrefixLSIdentifier parsePrefixIdendifier(ChannelBuffer cb, byte protocolId) - throws BgpParseException { - //Parse Local Node descriptor - NodeDescriptors localNodeDescriptors = new NodeDescriptors(); - localNodeDescriptors = parseLocalNodeDescriptors(cb, protocolId); - - //Parse Prefix descriptor - List prefixDescriptor = new LinkedList<>(); - prefixDescriptor = parsePrefixDescriptors(cb); - return new BgpPrefixLSIdentifier(localNodeDescriptors, prefixDescriptor); - } - - /** - * Parse local node descriptors. - * - * @param cb ChannelBuffer - * @param protocolId protocol identifier - * @return LocalNodeDescriptors - * @throws BgpParseException while parsing local node descriptors - */ - public static NodeDescriptors parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId) - throws BgpParseException { - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - //length + 4 implies data contains type, length and value - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); - } - NodeDescriptors localNodeDescriptors = new NodeDescriptors(); - ChannelBuffer tempCb = cb.readBytes(length); - - if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) { - localNodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId); - } else { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); - } - return localNodeDescriptors; - } - - /** - * Parse list of prefix descriptors. - * - * @param cb ChannelBuffer - * @return list of prefix descriptors - * @throws BgpParseException while parsing list of prefix descriptors - */ - public static List parsePrefixDescriptors(ChannelBuffer cb) throws BgpParseException { - LinkedList prefixDescriptor = new LinkedList<>(); - BgpValueType tlv = null; - boolean isIpReachInfo = false; - ChannelBuffer tempCb; - int count = 0; - - while (cb.readableBytes() > 0) { - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - //length + 4 implies data contains type, length and value - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); - } - tempCb = cb.readBytes(length); - switch (type) { - case OSPFRouteTypeTlv.TYPE: - tlv = OSPFRouteTypeTlv.read(tempCb); - break; - case IPReachabilityInformationTlv.TYPE: - tlv = IPReachabilityInformationTlv.read(tempCb, length); - isIpReachInfo = true; - break; - case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: - tlv = BgpAttrNodeMultiTopologyId.read(tempCb); - count = count + 1; - if (count > 1) { - //length + 4 implies data contains type, length and value - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length + TYPE_AND_LEN)); - } - break; - default: - UnSupportedAttribute.skipBytes(tempCb, length); - } - prefixDescriptor.add(tlv); - } - - if (!isIpReachInfo) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - null); - } - return prefixDescriptor; - } - - /** - * Returns local node descriptors. - * - * @return local node descriptors - */ - public NodeDescriptors getLocalNodeDescriptors() { - return this.localNodeDescriptors; - } - - /** - * Returns Prefix descriptors. - * - * @return Prefix descriptors - */ - public List getPrefixdescriptor() { - return this.prefixDescriptor; - } - - @Override - public int hashCode() { - return Objects.hash(prefixDescriptor.hashCode(), localNodeDescriptors); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixLSIdentifier) { - int countObjSubTlv = 0; - int countOtherSubTlv = 0; - boolean isCommonSubTlv = true; - BgpPrefixLSIdentifier other = (BgpPrefixLSIdentifier) obj; - - Iterator objListIterator = other.prefixDescriptor.iterator(); - countOtherSubTlv = other.prefixDescriptor.size(); - countObjSubTlv = prefixDescriptor.size(); - if (countObjSubTlv != countOtherSubTlv) { - return false; - } else { - while (objListIterator.hasNext() && isCommonSubTlv) { - BgpValueType subTlv = objListIterator.next(); - if (prefixDescriptor.contains(subTlv) && other.prefixDescriptor.contains(subTlv)) { - isCommonSubTlv = Objects.equals(prefixDescriptor.get(prefixDescriptor.indexOf(subTlv)), - other.prefixDescriptor.get(other.prefixDescriptor.indexOf(subTlv))); - } else { - isCommonSubTlv = false; - } - } - return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors); - } - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("localNodeDescriptors", localNodeDescriptors) - .add("prefixDescriptor", prefixDescriptor) - .toString(); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - int result = this.localNodeDescriptors.compareTo(((BgpPrefixLSIdentifier) o).localNodeDescriptors); - if (result != 0) { - return result; - } else { - int countOtherSubTlv = ((BgpPrefixLSIdentifier) o).prefixDescriptor.size(); - int countObjSubTlv = prefixDescriptor.size(); - if (countOtherSubTlv != countObjSubTlv) { - if (countOtherSubTlv > countObjSubTlv) { - return 1; - } else { - return -1; - } - } - - ListIterator listIterator = prefixDescriptor.listIterator(); - ListIterator listIteratorOther = ((BgpPrefixLSIdentifier) o).prefixDescriptor.listIterator(); - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - BgpValueType tlv1 = listIteratorOther.next(); - if (prefixDescriptor.contains(tlv) && ((BgpPrefixLSIdentifier) o).prefixDescriptor.contains(tlv1)) { - int res = prefixDescriptor.get(prefixDescriptor.indexOf(tlv)).compareTo( - ((BgpPrefixLSIdentifier) o).prefixDescriptor - .get(((BgpPrefixLSIdentifier) o).prefixDescriptor.indexOf(tlv1))); - if (res != 0) { - return res; - } - } - } - } - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java deleted file mode 100644 index 7fb1b316..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.AreaIDTlv; -import org.onosproject.bgpio.types.AutonomousSystemTlv; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpLSIdentifierTlv; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.IsIsNonPseudonode; -import org.onosproject.bgpio.types.IsIsPseudonode; -import org.onosproject.bgpio.types.OSPFNonPseudonode; -import org.onosproject.bgpio.types.OSPFPseudonode; -import org.onosproject.bgpio.util.UnSupportedAttribute; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Local and Remote NodeDescriptors which contains Node Descriptor Sub-TLVs. - */ -public class NodeDescriptors { - - /* - *Reference :draft-ietf-idr-ls-distribution-11 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - // Node Descriptor Sub-TLVs (variable) // - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure : Local or Remote Node Descriptors TLV format - */ - - private static final Logger log = LoggerFactory.getLogger(NodeDescriptors.class); - - public static final short LOCAL_NODE_DES_TYPE = 256; - public static final short REMOTE_NODE_DES_TYPE = 257; - public static final short IGP_ROUTERID_TYPE = 515; - public static final short IS_IS_LEVEL_1_PROTOCOL_ID = 1; - public static final short IS_IS_LEVEL_2_PROTOCOL_ID = 2; - public static final short OSPF_V2_PROTOCOL_ID = 3; - public static final short OSPF_V3_PROTOCOL_ID = 6; - public static final int TYPE_AND_LEN = 4; - public static final int ISISNONPSEUDONODE_LEN = 6; - public static final int ISISPSEUDONODE_LEN = 7; - public static final int OSPFNONPSEUDONODE_LEN = 4; - public static final int OSPFPSEUDONODE_LEN = 8; - private List subTlvs; - private short deslength; - private short desType; - - /** - * Resets parameters. - */ - public NodeDescriptors() { - this.subTlvs = null; - this.deslength = 0; - this.desType = 0; - } - - /** - * Constructor to initialize parameters. - * - * @param subTlvs list of subTlvs - * @param deslength Descriptors length - * @param desType local node descriptor or remote node descriptor type - */ - public NodeDescriptors(List subTlvs, short deslength, short desType) { - this.subTlvs = subTlvs; - this.deslength = deslength; - this.desType = desType; - } - - /** - * Returns list of subTlvs. - * - * @return subTlvs list of subTlvs - */ - public List getSubTlvs() { - return subTlvs; - } - - @Override - public int hashCode() { - return Objects.hash(subTlvs.hashCode()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof NodeDescriptors) { - int countObjSubTlv = 0; - int countOtherSubTlv = 0; - boolean isCommonSubTlv = true; - NodeDescriptors other = (NodeDescriptors) obj; - Iterator objListIterator = other.subTlvs.iterator(); - countOtherSubTlv = other.subTlvs.size(); - countObjSubTlv = subTlvs.size(); - if (countObjSubTlv != countOtherSubTlv) { - return false; - } else { - while (objListIterator.hasNext() && isCommonSubTlv) { - BgpValueType subTlv = objListIterator.next(); - if (subTlvs.contains(subTlv) && other.subTlvs.contains(subTlv)) { - isCommonSubTlv = Objects.equals(subTlvs.get(subTlvs.indexOf(subTlv)), - other.subTlvs.get(other.subTlvs.indexOf(subTlv))); - } else { - isCommonSubTlv = false; - } - } - return isCommonSubTlv; - } - } - return false; - } - - /** - * Reads node descriptors Sub-TLVs. - * - * @param cb ChannelBuffer - * @param desLength node descriptor length - * @param desType local node descriptor or remote node descriptor type - * @param protocolId protocol ID - * @return object of NodeDescriptors - * @throws BgpParseException while parsing node descriptors - */ - public static NodeDescriptors read(ChannelBuffer cb, short desLength, short desType, byte protocolId) - throws BgpParseException { - log.debug("Read NodeDescriptor"); - List subTlvs = new LinkedList<>(); - BgpValueType tlv = null; - - while (cb.readableBytes() > 0) { - ChannelBuffer tempBuf = cb.copy(); - short type = cb.readShort(); - short length = cb.readShort(); - if (cb.readableBytes() < length) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, - tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); - } - ChannelBuffer tempCb = cb.readBytes(length); - switch (type) { - case AutonomousSystemTlv.TYPE: - tlv = AutonomousSystemTlv.read(tempCb); - break; - case BgpLSIdentifierTlv.TYPE: - tlv = BgpLSIdentifierTlv.read(tempCb); - break; - case AreaIDTlv.TYPE: - tlv = AreaIDTlv.read(tempCb); - break; - case IGP_ROUTERID_TYPE: - if (protocolId == IS_IS_LEVEL_1_PROTOCOL_ID || protocolId == IS_IS_LEVEL_2_PROTOCOL_ID) { - if (length == ISISNONPSEUDONODE_LEN) { - tlv = IsIsNonPseudonode.read(tempCb); - } else if (length == ISISPSEUDONODE_LEN) { - tlv = IsIsPseudonode.read(tempCb); - } - } else if (protocolId == OSPF_V2_PROTOCOL_ID || protocolId == OSPF_V3_PROTOCOL_ID) { - if (length == OSPFNONPSEUDONODE_LEN) { - tlv = OSPFNonPseudonode.read(tempCb); - } else if (length == OSPFPSEUDONODE_LEN) { - tlv = OSPFPseudonode.read(tempCb); - } - } - break; - default: - UnSupportedAttribute.skipBytes(tempCb, length); - } - subTlvs.add(tlv); - } - return new NodeDescriptors(subTlvs, desLength, desType); - } - - /** - * Returns node descriptors length. - * - * @return node descriptors length - */ - public short getLength() { - return this.deslength; - } - - /** - * Returns node descriptors type. - * - * @return node descriptors type - */ - public short getType() { - return this.desType; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("desType", desType) - .add("deslength", deslength) - .add("subTlvs", subTlvs) - .toString(); - } - - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - ListIterator listIterator = subTlvs.listIterator(); - ListIterator listIteratorOther = ((NodeDescriptors) o).subTlvs.listIterator(); - int countOtherSubTlv = ((NodeDescriptors) o).subTlvs.size(); - int countObjSubTlv = subTlvs.size(); - if (countOtherSubTlv != countObjSubTlv) { - if (countOtherSubTlv > countObjSubTlv) { - return 1; - } else { - return -1; - } - } else { - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - BgpValueType tlv1 = listIteratorOther.next(); - if (subTlvs.contains(tlv) && ((NodeDescriptors) o).subTlvs.contains(tlv1)) { - int result = subTlvs.get(subTlvs.indexOf(tlv)).compareTo( - ((NodeDescriptors) o).subTlvs.get(((NodeDescriptors) o).subTlvs.indexOf(tlv1))); - if (result != 0) { - return result; - } - } - } - } - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java deleted file mode 100755 index 9578ccfe..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; -import org.onosproject.bgpio.types.BgpValueType; - -import com.google.common.base.MoreObjects; - -/** - * This Class stores path Attributes, protocol ID and Identifier of LinkState NLRI. - */ -public class PathAttrNlriDetails { - private List pathAttributes; - private ProtocolType protocolID; - private long identifier; - - /** - * Sets path attribute with specified path attribute. - * - * @param pathAttributes in update message - */ - public void setPathAttribute(List pathAttributes) { - this.pathAttributes = pathAttributes; - } - - /** - * Returns path attributes. - * - * @return path attributes - */ - public List pathAttributes() { - return this.pathAttributes; - } - - /** - * Sets protocolID with specified protocolID. - * - * @param protocolID in linkstate nlri - */ - public void setProtocolID(ProtocolType protocolID) { - this.protocolID = protocolID; - } - - /** - * Returns protocolID. - * - * @return protocolID - */ - public ProtocolType protocolID() { - return this.protocolID; - } - - /** - * Sets identifier with specified identifier. - * - * @param identifier in linkstate nlri - */ - public void setIdentifier(long identifier) { - this.identifier = identifier; - } - - /** - * Returns Identifier. - * - * @return Identifier - */ - public long identifier() { - return this.identifier; - } - - @Override - public int hashCode() { - return Objects.hash(pathAttributes, protocolID, identifier); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof PathAttrNlriDetails) { - int countObjSubTlv = 0; - int countOtherSubTlv = 0; - boolean isCommonSubTlv = true; - PathAttrNlriDetails other = (PathAttrNlriDetails) obj; - Iterator objListIterator = other.pathAttributes.iterator(); - countOtherSubTlv = other.pathAttributes.size(); - countObjSubTlv = pathAttributes.size(); - if (countObjSubTlv != countOtherSubTlv) { - return false; - } else { - while (objListIterator.hasNext() && isCommonSubTlv) { - BgpValueType subTlv = objListIterator.next(); - if (pathAttributes.contains(subTlv) && other.pathAttributes.contains(subTlv)) { - isCommonSubTlv = Objects.equals(pathAttributes.get(pathAttributes.indexOf(subTlv)), - other.pathAttributes.get(other.pathAttributes.indexOf(subTlv))); - } else { - isCommonSubTlv = false; - } - } - return isCommonSubTlv && Objects.equals(identifier, other.identifier) - && Objects.equals(protocolID, other.protocolID); - } - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("identifier", identifier) - .add("protocolID", protocolID) - .add("pathAttributes", pathAttributes) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java deleted file mode 100755 index 4172ae46..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgpio.protocol.linkstate; - -import java.util.Objects; - -import org.onlab.packet.IpAddress; -import com.google.common.base.MoreObjects; - -/** - * This Class stores path Attributes, protocol ID and Identifier of LinkState nlri. - */ -public class PathAttrNlriDetailsLocalRib { - - private IpAddress localRibIpAddress; - private long localRibAsNum; - private int localRibIdentifier; - private boolean isLocalRibIbgpSession; - private PathAttrNlriDetails localRibNlridetails; - - /** - * Constructor to initialize parameter. - * - * @param localRibIpAddress peer ip address - * @param localRibIdentifier peer identifier - * @param localRibAsNum peer As number - * @param isLocalRibIbgpSession flag to indicate is Ibgp session - * @param localRibNlridetails Nlri details - * - */ - public PathAttrNlriDetailsLocalRib(IpAddress localRibIpAddress, int localRibIdentifier, long localRibAsNum, - boolean isLocalRibIbgpSession, PathAttrNlriDetails localRibNlridetails) { - this.localRibIpAddress = localRibIpAddress; - this.localRibAsNum = localRibAsNum; - this.localRibIdentifier = localRibIdentifier; - this.isLocalRibIbgpSession = isLocalRibIbgpSession; - this.localRibNlridetails = localRibNlridetails; - } - - /** - * Gets the Ipaddress updated in local rib. - * - * @return localRibIpAddress ip address - */ - public IpAddress localRibIpAddress() { - return localRibIpAddress; - } - - /** - * Gets the autonomous system number updated in local rib. - * - * @return localRibAsNum autonomous system number - */ - public long localRibAsNum() { - return localRibAsNum; - } - - /** - * Gets the indetifier updated in local rib. - * - * @return localRibIdentifier identifier - */ - public int localRibIdentifier() { - return localRibIdentifier; - } - - /** - * Gets the bgp session type updated in local rib. - * - * @return isLocalRibIbgpSession session type - */ - public boolean isLocalRibIbgpSession() { - return isLocalRibIbgpSession; - } - - /** - * Returns local RIB Nlri details. - * - * @return localRibNlridetails Nlri details in local rib - */ - public PathAttrNlriDetails localRibNlridetails() { - return this.localRibNlridetails; - } - - @Override - public int hashCode() { - return Objects.hash(localRibIpAddress, localRibIdentifier, localRibAsNum, isLocalRibIbgpSession, - localRibNlridetails.hashCode()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof PathAttrNlriDetailsLocalRib) { - PathAttrNlriDetailsLocalRib other = (PathAttrNlriDetailsLocalRib) obj; - return Objects.equals(localRibIpAddress, other.localRibIpAddress) - && Objects.equals(localRibIdentifier, other.localRibIdentifier) - && Objects.equals(localRibAsNum, other.localRibAsNum) - && Objects.equals(isLocalRibIbgpSession, other.isLocalRibIbgpSession) - && Objects.equals(localRibNlridetails, other.localRibNlridetails); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).add("peerIdentifier", localRibIdentifier) - .add("localRibpathAttributes", localRibNlridetails.pathAttributes()).toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java deleted file mode 100755 index 87ba60f0..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * BGP Protocol specific link state details. - */ -package org.onosproject.bgpio.protocol.linkstate; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java deleted file mode 100755 index 723b31b1..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * BGP Protocol specific components. - */ -package org.onosproject.bgpio.protocol; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java deleted file mode 100755 index c57832b6..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol.ver4; - -import org.onosproject.bgpio.protocol.BgpFactory; -import org.onosproject.bgpio.protocol.BgpKeepaliveMsg; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.protocol.BgpNotificationMsg; -import org.onosproject.bgpio.protocol.BgpOpenMsg; -import org.onosproject.bgpio.protocol.BgpVersion; - -/** - * Provides BGP Factory and returns builder classes for all objects and messages. - */ -public class BgpFactoryVer4 implements BgpFactory { - - public static final BgpFactoryVer4 INSTANCE = new BgpFactoryVer4(); - - @Override - public BgpOpenMsg.Builder openMessageBuilder() { - return new BgpOpenMsgVer4.Builder(); - } - - @Override - public BgpKeepaliveMsg.Builder keepaliveMessageBuilder() { - return new BgpKeepaliveMsgVer4.Builder(); - } - - @Override - public BgpNotificationMsg.Builder notificationMessageBuilder() { - return new BgpNotificationMsgVer4.Builder(); - } - - @Override - public BgpMessageReader getReader() { - return BgpMessageVer4.READER; - } - - @Override - public BgpVersion getVersion() { - return BgpVersion.BGP_4; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java deleted file mode 100644 index 2c141586..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.ver4; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpKeepaliveMsg; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.protocol.BgpMessageWriter; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.protocol.BgpType; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides BGP keep alive message. - */ -public class BgpKeepaliveMsgVer4 implements BgpKeepaliveMsg { - - /* - ::= - A KEEPALIVE message consists of only the message header and has a - length of 19 octets. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | | - + + - | Marker | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Length | Type | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - REFERENCE : RFC 4271 - */ - - protected static final Logger log = LoggerFactory - .getLogger(BgpKeepaliveMsgVer4.class); - - private BgpHeader bgpMsgHeader; - public static final byte PACKET_VERSION = 4; - public static final int PACKET_MINIMUM_LENGTH = 19; - public static final int MARKER_LENGTH = 16; - public static final BgpType MSG_TYPE = BgpType.KEEP_ALIVE; - public static byte[] marker = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; - - public static final BgpKeepaliveMsgVer4.Reader READER = new Reader(); - - /** - * Reader class for reading BGP keepalive message from channel buffer. - */ - static class Reader implements BgpMessageReader { - - @Override - public BgpKeepaliveMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) - throws BgpParseException { - - /* bgpHeader is not required in case of keepalive message and - Header is already read and no other fields except header in keepalive message.*/ - return new BgpKeepaliveMsgVer4(); - } - } - - /** - * Default constructor. - */ - public BgpKeepaliveMsgVer4() { - } - - /** - * Builder class for BGP keepalive message. - */ - static class Builder implements BgpKeepaliveMsg.Builder { - BgpHeader bgpMsgHeader; - - @Override - public Builder setHeader(BgpHeader bgpMsgHeader) { - this.bgpMsgHeader = bgpMsgHeader; - return this; - } - - @Override - public BgpKeepaliveMsg build() { - return new BgpKeepaliveMsgVer4(); - } - } - - @Override - public void writeTo(ChannelBuffer cb) { - WRITER.write(cb, this); - } - - static final Writer WRITER = new Writer(); - - /** - * Writer class for writing the BGP keepalive message to channel buffer. - */ - static class Writer implements BgpMessageWriter { - - @Override - public void write(ChannelBuffer cb, BgpKeepaliveMsgVer4 message) { - - // write marker - cb.writeBytes(marker, 0, MARKER_LENGTH); - - // write length of header - cb.writeShort(PACKET_MINIMUM_LENGTH); - - // write the type of message - cb.writeByte(MSG_TYPE.getType()); - } - } - - @Override - public BgpVersion getVersion() { - return BgpVersion.BGP_4; - } - - @Override - public BgpType getType() { - return MSG_TYPE; - } - - @Override - public BgpHeader getHeader() { - return this.bgpMsgHeader; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java deleted file mode 100755 index 1c05dae4..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.protocol.ver4; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpFactories; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides BGP messages. - */ -public abstract class BgpMessageVer4 { - - protected static final Logger log = LoggerFactory.getLogger(BgpFactories.class); - - static final byte OPEN_MSG_TYPE = 0x1; - static final byte KEEPALIVE_MSG_TYPE = 0x4; - static final byte UPDATE_MSG_TYPE = 0x2; - static final byte NOTIFICATION_MSG_TYPE = 0x3; - static final int MINIMUM_COMMON_HEADER_LENGTH = 19; - static final int HEADER_AND_MSG_LEN = 18; - static final int MAXIMUM_PACKET_LENGTH = 4096; - - public static final BgpMessageVer4.Reader READER = new Reader(); - - /** - * Reader class for reading BGP messages from channel buffer. - * - */ - static class Reader implements BgpMessageReader { - @Override - public BgpMessage readFrom(ChannelBuffer cb, BgpHeader bgpHeader) - throws BgpParseException { - - if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { - log.error("Packet should have minimum length."); - Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, - cb.readableBytes()); - } - if (cb.readableBytes() > MAXIMUM_PACKET_LENGTH) { - log.error("Packet length should not exceed {}.", MAXIMUM_PACKET_LENGTH); - Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, - cb.readableBytes()); - } - try { - // fixed value property version == 4 - byte[] marker = new byte[BgpHeader.MARKER_LENGTH]; - cb.readBytes(marker, 0, BgpHeader.MARKER_LENGTH); - bgpHeader.setMarker(marker); - for (int i = 0; i < BgpHeader.MARKER_LENGTH; i++) { - if (marker[i] != (byte) 0xff) { - throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, - BgpErrorType.CONNECTION_NOT_SYNCHRONIZED, null); - } - } - short length = cb.readShort(); - if (length > cb.readableBytes() + HEADER_AND_MSG_LEN) { - Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, - BgpErrorType.BAD_MESSAGE_LENGTH, length); - } - bgpHeader.setLength(length); - byte type = cb.readByte(); - bgpHeader.setType(type); - log.debug("Reading update message of type " + type); - - int len = length - MINIMUM_COMMON_HEADER_LENGTH; - switch (type) { - case OPEN_MSG_TYPE: - log.debug("OPEN MESSAGE is received"); - return BgpOpenMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); - case KEEPALIVE_MSG_TYPE: - log.debug("KEEPALIVE MESSAGE is received"); - return BgpKeepaliveMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); - case UPDATE_MSG_TYPE: - log.debug("UPDATE MESSAGE is received"); - return BgpUpdateMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); - case NOTIFICATION_MSG_TYPE: - log.debug("NOTIFICATION MESSAGE is received"); - return BgpNotificationMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); - default: - Validation.validateType(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_TYPE, type); - return null; - } - } catch (IndexOutOfBoundsException e) { - throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, - BgpErrorType.BAD_MESSAGE_LENGTH, null); - } - } - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java deleted file mode 100644 index d25db24e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.ver4; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.protocol.BgpMessageWriter; -import org.onosproject.bgpio.protocol.BgpNotificationMsg; -import org.onosproject.bgpio.protocol.BgpType; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpHeader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * A NOTIFICATION message is sent when an error condition is detected. The BGP connection is closed immediately after it - * is sent. - */ -class BgpNotificationMsgVer4 implements BgpNotificationMsg { - - /* - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Error code | Error subcode | Data (variable) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - REFERENCE : RFC 4271 - */ - - private static final Logger log = LoggerFactory.getLogger(BgpNotificationMsgVer4.class); - - static final byte PACKET_VERSION = 4; - //BGPHeader(19) + Error code(1) + Error subcode(1) - static final int TOTAL_MESSAGE_MIN_LENGTH = 21; - static final int PACKET_MINIMUM_LENGTH = 2; - static final BgpType MSG_TYPE = BgpType.NOTIFICATION; - static final byte DEFAULT_ERRORSUBCODE = 0; - static final byte[] MARKER = {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff }; - static final byte MESSAGE_TYPE = 3; - static final BgpHeader DEFAULT_MESSAGE_HEADER = new BgpHeader(MARKER, BgpHeader.DEFAULT_HEADER_LENGTH, - MESSAGE_TYPE); - - private byte errorCode; - private byte errorSubCode; - private byte[] data; - private BgpHeader bgpHeader; - public static final BgpNotificationMsgVer4.Reader READER = new Reader(); - - /** - * Initialize fields. - */ - public BgpNotificationMsgVer4() { - this.bgpHeader = null; - this.data = null; - this.errorCode = 0; - this.errorSubCode = 0; - } - - /** - * Constructor to initialize parameters. - * - * @param bgpHeader BGP Header in notification message - * @param errorCode error code - * @param errorSubCode error subcode - * @param data field - */ - public BgpNotificationMsgVer4(BgpHeader bgpHeader, byte errorCode, byte errorSubCode, byte[] data) { - this.bgpHeader = bgpHeader; - this.data = data; - this.errorCode = errorCode; - this.errorSubCode = errorSubCode; - } - - /** - * Reader reads BGP Notification Message from the channel buffer. - */ - static class Reader implements BgpMessageReader { - @Override - public BgpNotificationMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException { - byte errorCode; - byte errorSubCode; - if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) { - throw new BgpParseException("Not enough readable bytes"); - } - errorCode = cb.readByte(); - errorSubCode = cb.readByte(); - //Message Length = 21 + Data Length - int dataLength = bgpHeader.getLength() - TOTAL_MESSAGE_MIN_LENGTH; - byte[] data = new byte[dataLength]; - cb.readBytes(data, 0, dataLength); - return new BgpNotificationMsgVer4(bgpHeader, errorCode, errorSubCode, data); - } - } - - /** - * Builder class for BGP notification message. - */ - static class Builder implements BgpNotificationMsg.Builder { - private byte errorCode; - private byte errorSubCode; - private byte[] data; - private BgpHeader bgpHeader; - private boolean isErrorCodeSet = false; - private boolean isErrorSubCodeSet = false; - private boolean isBGPHeaderSet = false; - - @Override - public BgpNotificationMsg build() throws BgpParseException { - BgpHeader bgpHeader = this.isBGPHeaderSet ? this.bgpHeader : DEFAULT_MESSAGE_HEADER; - if (!this.isErrorCodeSet) { - throw new BgpParseException("Error code must be present"); - } - - byte errorSubCode = this.isErrorSubCodeSet ? this.errorSubCode : DEFAULT_ERRORSUBCODE; - return new BgpNotificationMsgVer4(bgpHeader, this.errorCode, errorSubCode, this.data); - } - - @Override - public Builder setErrorCode(byte errorCode) { - this.errorCode = errorCode; - this.isErrorCodeSet = true; - return this; - } - - @Override - public Builder setErrorSubCode(byte errorSubCode) { - this.errorSubCode = errorSubCode; - this.isErrorSubCodeSet = true; - return this; - } - - @Override - public Builder setData(byte[] data) { - if (data != null) { - this.data = data; - } - return this; - } - - @Override - public Builder setHeader(BgpHeader bgpMsgHeader) { - this.bgpHeader = bgpMsgHeader; - return this; - } - } - - @Override - public BgpVersion getVersion() { - return BgpVersion.BGP_4; - } - - @Override - public BgpType getType() { - return BgpType.NOTIFICATION; - } - - @Override - public void writeTo(ChannelBuffer cb) throws BgpParseException { - WRITER.write(cb, this); - } - - static final Writer WRITER = new Writer(); - - /** - * Writer writes BGP notification message to channel buffer. - */ - static class Writer implements BgpMessageWriter { - @Override - public void write(ChannelBuffer cb, BgpNotificationMsgVer4 message) throws BgpParseException { - int msgStartIndex = cb.writerIndex(); - int headerLenIndex = message.bgpHeader.write(cb); - if (headerLenIndex <= 0) { - throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, (byte) 0, null); - } - cb.writeByte(message.errorCode); - cb.writeByte(message.errorSubCode); - cb.writeBytes(message.data); - - //Update message length field in notification message - int length = cb.writerIndex() - msgStartIndex; - cb.setShort(headerLenIndex, (short) length); - message.bgpHeader.setLength((short) length); - } - } - - @Override - public byte getErrorCode() { - return this.errorCode; - } - - /** - * Sets errorcode with specified errorcode. - * - * @param errorCode field - */ - public void setErrorCode(byte errorCode) { - this.errorCode = errorCode; - } - - @Override - public byte getErrorSubCode() { - return this.errorSubCode; - } - - /** - * Sets error subcode with specified errorSubCode. - * - * @param errorSubCode field - */ - public void setErrorSubCode(byte errorSubCode) { - this.errorSubCode = errorSubCode; - } - - @Override - public byte[] getData() { - return this.data; - } - - /** - * Sets error data with specified data. - * - * @param data field - */ - public void setData(byte[] data) { - this.data = data; - } - - @Override - public BgpHeader getHeader() { - return this.bgpHeader; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("bgpHeader", bgpHeader) - .add("data", data) - .add("errorCode", errorCode) - .add("errorSubCode", errorSubCode) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java deleted file mode 100644 index 359eec25..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.ver4; - -import java.util.LinkedList; -import java.util.ListIterator; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.protocol.BgpMessageWriter; -import org.onosproject.bgpio.protocol.BgpOpenMsg; -import org.onosproject.bgpio.protocol.BgpType; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; -import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides BGP open message. - */ -public class BgpOpenMsgVer4 implements BgpOpenMsg { - - /* - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+ - | Version | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | My Autonomous System | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Hold Time | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | BGP Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Opt Parm Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Optional Parameters (variable) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - OPEN Message Format - REFERENCE : RFC 4271 - */ - - protected static final Logger log = LoggerFactory.getLogger(BgpOpenMsgVer4.class); - - public static final byte PACKET_VERSION = 4; - public static final int OPEN_MSG_MINIMUM_LENGTH = 10; - public static final int MSG_HEADER_LENGTH = 19; - public static final int MARKER_LENGTH = 16; - public static final int DEFAULT_HOLD_TIME = 120; - public static final short AS_TRANS = 23456; - public static final int OPT_PARA_TYPE_CAPABILITY = 2; - public static final BgpType MSG_TYPE = BgpType.OPEN; - public static final short AFI = 16388; - public static final byte SAFI = 71; - public static final byte RES = 0; - public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65; - public static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; - public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER, - (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01); - private BgpHeader bgpMsgHeader; - private byte version; - private short asNumber; - private short holdTime; - private int bgpId; - private boolean isLargeAsCapabilitySet; - private LinkedList capabilityTlv; - - public static final BgpOpenMsgVer4.Reader READER = new Reader(); - - /** - * reset variables. - */ - public BgpOpenMsgVer4() { - this.bgpMsgHeader = null; - this.version = 0; - this.holdTime = 0; - this.asNumber = 0; - this.bgpId = 0; - this.capabilityTlv = null; - } - - /** - * Constructor to initialize all variables of BGP Open message. - * - * @param bgpMsgHeader BGP Header in open message - * @param version BGP version in open message - * @param holdTime hold time in open message - * @param asNumber AS number in open message - * @param bgpId BGP identifier in open message - * @param capabilityTlv capabilities in open message - */ - public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, short asNumber, short holdTime, - int bgpId, LinkedList capabilityTlv) { - this.bgpMsgHeader = bgpMsgHeader; - this.version = version; - this.asNumber = asNumber; - this.holdTime = holdTime; - this.bgpId = bgpId; - this.capabilityTlv = capabilityTlv; - } - - @Override - public BgpHeader getHeader() { - return this.bgpMsgHeader; - } - - @Override - public BgpVersion getVersion() { - return BgpVersion.BGP_4; - } - - @Override - public BgpType getType() { - return MSG_TYPE; - } - - @Override - public short getHoldTime() { - return this.holdTime; - } - - @Override - public short getAsNumber() { - return this.asNumber; - } - - @Override - public int getBgpId() { - return this.bgpId; - } - - @Override - public LinkedList getCapabilityTlv() { - return this.capabilityTlv; - } - - /** - * Reader class for reading BGP open message from channel buffer. - */ - public static class Reader implements BgpMessageReader { - - @Override - public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException { - - byte version; - short holdTime; - short asNumber; - int bgpId; - byte optParaLen = 0; - byte optParaType; - byte capParaLen = 0; - LinkedList capabilityTlv = new LinkedList<>(); - - if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) { - log.error("[readFrom] Invalid length: Packet size is less than the minimum length "); - Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, - cb.readableBytes()); - } - - // Read version - version = cb.readByte(); - if (version != PACKET_VERSION) { - log.error("[readFrom] Invalid version: " + version); - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, - BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null); - } - - // Read AS number - asNumber = cb.readShort(); - - // Read Hold timer - holdTime = cb.readShort(); - - // Read BGP Identifier - bgpId = cb.readInt(); - - // Read optional parameter length - optParaLen = cb.readByte(); - - // Read Capabilities if optional parameter length is greater than 0 - if (optParaLen != 0) { - // Read optional parameter type - optParaType = cb.readByte(); - - // Read optional parameter length - capParaLen = cb.readByte(); - - if (cb.readableBytes() < capParaLen) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null); - } - - ChannelBuffer capaCb = cb.readBytes(capParaLen); - - // Parse capabilities only if optional parameter type is 2 - if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) { - capabilityTlv = parseCapabilityTlv(capaCb); - } else { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, - BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null); - } - } - return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv); - } - } - - /** - * Parsing capabilities. - * - * @param cb of type channel buffer - * @return capabilityTlv of open message - * @throws BgpParseException while parsing capabilities - */ - protected static LinkedList parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException { - - LinkedList capabilityTlv = new LinkedList<>(); - - while (cb.readableBytes() > 0) { - BgpValueType tlv; - short type = cb.readByte(); - short length = cb.readByte(); - - switch (type) { - case FourOctetAsNumCapabilityTlv.TYPE: - log.debug("FourOctetAsNumCapabilityTlv"); - if (FourOctetAsNumCapabilityTlv.LENGTH != length) { - throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv."); - } - if (length > cb.readableBytes()) { - throw new BgpParseException("Four octet as num tlv length" - + " is more than readableBytes."); - } - int as4Num = cb.readInt(); - tlv = new FourOctetAsNumCapabilityTlv(as4Num); - break; - case MultiProtocolExtnCapabilityTlv.TYPE: - log.debug("MultiProtocolExtnCapabilityTlv"); - if (MultiProtocolExtnCapabilityTlv.LENGTH != length) { - throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv."); - } - if (length > cb.readableBytes()) { - throw new BgpParseException("BGP LS tlv length is more than readableBytes."); - } - short afi = cb.readShort(); - byte res = cb.readByte(); - byte safi = cb.readByte(); - tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi); - break; - default: - log.debug("Warning: Unsupported TLV: " + type); - cb.skipBytes(length); - continue; - } - capabilityTlv.add(tlv); - } - return capabilityTlv; - } - - /** - * Builder class for BGP open message. - */ - static class Builder implements BgpOpenMsg.Builder { - - private boolean isHeaderSet = false; - private BgpHeader bgpMsgHeader; - private boolean isHoldTimeSet = false; - private short holdTime; - private boolean isAsNumSet = false; - private short asNumber; - private boolean isBgpIdSet = false; - private int bgpId; - private boolean isLargeAsCapabilityTlvSet = false; - private boolean isLsCapabilityTlvSet = false; - - LinkedList capabilityTlv = new LinkedList<>(); - - @Override - public BgpOpenMsg build() throws BgpParseException { - BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER; - short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME; - - if (!this.isAsNumSet) { - throw new BgpParseException("BGP AS number is not set (mandatory)"); - } - - if (!this.isBgpIdSet) { - throw new BgpParseException("BGPID is not set (mandatory)"); - } - - if (this.isLargeAsCapabilityTlvSet) { - BgpValueType tlv; - int value = this.asNumber; - tlv = new FourOctetAsNumCapabilityTlv(value); - this.capabilityTlv.add(tlv); - } - - if (this.isLsCapabilityTlvSet) { - BgpValueType tlv; - tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI); - this.capabilityTlv.add(tlv); - } - - return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId, - this.capabilityTlv); - } - - @Override - public Builder setHeader(BgpHeader bgpMsgHeader) { - this.bgpMsgHeader = bgpMsgHeader; - return this; - } - - @Override - public Builder setHoldTime(short holdTime) { - this.holdTime = holdTime; - this.isHoldTimeSet = true; - return this; - } - - @Override - public Builder setAsNumber(short asNumber) { - this.asNumber = asNumber; - this.isAsNumSet = true; - return this; - } - - @Override - public Builder setBgpId(int bgpId) { - this.bgpId = bgpId; - this.isBgpIdSet = true; - return this; - } - - @Override - public Builder setCapabilityTlv(LinkedList capabilityTlv) { - this.capabilityTlv = capabilityTlv; - return this; - } - - @Override - public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) { - this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet; - return this; - } - - @Override - public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) { - this.isLsCapabilityTlvSet = isLsCapabilitySet; - return this; - } - } - - @Override - public void writeTo(ChannelBuffer cb) { - try { - WRITER.write(cb, this); - } catch (BgpParseException e) { - log.debug("[writeTo] Error: " + e.toString()); - } - } - - public static final Writer WRITER = new Writer(); - - /** - * Writer class for writing BGP open message to channel buffer. - */ - public static class Writer implements BgpMessageWriter { - - @Override - public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException { - - int optParaLen = 0; - int as4num = 0; - - int startIndex = cb.writerIndex(); - - // write common header and get msg length index - int msgLenIndex = message.bgpMsgHeader.write(cb); - - if (msgLenIndex <= 0) { - throw new BgpParseException("Unable to write message header."); - } - - // write version in 1-octet - cb.writeByte(message.version); - - // get as4num if LS Capability is set - if (message.isLargeAsCapabilitySet) { - LinkedList capabilityTlv = message - .getCapabilityTlv(); - ListIterator listIterator = capabilityTlv - .listIterator(); - - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { - as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); - break; - } - } - } - - if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) { - // write As number as AS_TRANS - cb.writeShort(AS_TRANS); - } else { - // write AS number in next 2-octet - cb.writeShort(message.asNumber); - } - - // write HoldTime in next 2-octet - cb.writeShort(message.holdTime); - - // write BGP Identifier in next 4-octet - cb.writeInt(message.bgpId); - - // store the index of Optional parameter length - int optParaLenIndex = cb.writerIndex(); - - // set optional parameter length as 0 - cb.writeByte(0); - - // Pack capability TLV - optParaLen = message.packCapabilityTlv(cb, message); - - if (optParaLen != 0) { - // Update optional parameter length - cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type. - } - - // write OPEN Object Length - int length = cb.writerIndex() - startIndex; - cb.setShort(msgLenIndex, (short) length); - message.bgpMsgHeader.setLength((short) length); - } - } - - /** - * returns length of capability tlvs. - * - * @param cb of type channel buffer - * @param message of type BGPOpenMsgVer4 - * @return capParaLen of open message - */ - protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) { - int startIndex = cb.writerIndex(); - int capParaLen = 0; - int capParaLenIndex = 0; - - LinkedList capabilityTlv = message.capabilityTlv; - ListIterator listIterator = capabilityTlv.listIterator(); - - if (listIterator.hasNext()) { - // Set optional parameter type as 2 - cb.writeByte(OPT_PARA_TYPE_CAPABILITY); - - // Store the index of capability parameter length and update length at the end - capParaLenIndex = cb.writerIndex(); - - // Set capability parameter length as 0 - cb.writeByte(0); - - // Update the startIndex to know the length of capability tlv - startIndex = cb.writerIndex(); - } - - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - if (tlv == null) { - log.debug("Warning: tlv is null from CapabilityTlv list"); - continue; - } - tlv.write(cb); - } - - capParaLen = cb.writerIndex() - startIndex; - - if (capParaLen != 0) { - // Update capability parameter length - cb.setByte(capParaLenIndex, (byte) capParaLen); - } - return capParaLen; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("bgpMsgHeader", bgpMsgHeader) - .add("version", version) - .add("holdTime", holdTime) - .add("asNumber", asNumber) - .add("bgpId", bgpId) - .add("capabilityTlv", capabilityTlv) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java deleted file mode 100644 index 9ffddf68..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.ver4; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.As4Path; -import org.onosproject.bgpio.types.AsPath; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.LocalPref; -import org.onosproject.bgpio.types.Med; -import org.onosproject.bgpio.types.NextHop; -import org.onosproject.bgpio.types.Origin; -import org.onosproject.bgpio.types.MpReachNlri; -import org.onosproject.bgpio.types.MpUnReachNlri; -import org.onosproject.bgpio.util.UnSupportedAttribute; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of BGP Path Attribute. - */ -public class BgpPathAttributes { - - /* Path attribute: - - - 0 1 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Attr. Flags |Attr. Type Code| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - REFERENCE : RFC 4271 - */ - protected static final Logger log = LoggerFactory.getLogger(BgpPathAttributes.class); - - public static final int LINK_STATE_ATTRIBUTE_TYPE = 50; - public static final int MPREACHNLRI_TYPE = 14; - public static final int MPUNREACHNLRI_TYPE = 15; - - private final List pathAttribute; - - /** - * Initialize parameter. - */ - public BgpPathAttributes() { - this.pathAttribute = null; - } - - /** - * Constructor to initialize parameters for BGP path attributes. - * - * @param pathAttribute list of path attributes - */ - public BgpPathAttributes(List pathAttribute) { - this.pathAttribute = pathAttribute; - } - - /** - * Returns list of path attributes. - * - * @return list of path attributes - */ - public List pathAttributes() { - return this.pathAttribute; - } - - /** - * Reads from channelBuffer and parses BGP path attributes. - * - * @param cb channelBuffer - * @return object of BgpPathAttributes - * @throws BgpParseException while parsing BGP path attributes - */ - public static BgpPathAttributes read(ChannelBuffer cb) - throws BgpParseException { - - BgpValueType pathAttribute = null; - List pathAttributeList = new LinkedList<>(); - boolean isOrigin = false; - boolean isAsPath = false; - boolean isNextHop = false; - boolean isMpReach = false; - boolean isMpUnReach = false; - while (cb.readableBytes() > 0) { - cb.markReaderIndex(); - byte flags = cb.readByte(); - byte typeCode = cb.readByte(); - cb.resetReaderIndex(); - switch (typeCode) { - case Origin.ORIGIN_TYPE: - pathAttribute = Origin.read(cb); - isOrigin = ((Origin) pathAttribute).isOriginSet(); - break; - case AsPath.ASPATH_TYPE: - pathAttribute = AsPath.read(cb); - isAsPath = ((AsPath) pathAttribute).isaspathSet(); - break; - case As4Path.AS4PATH_TYPE: - pathAttribute = As4Path.read(cb); - break; - case NextHop.NEXTHOP_TYPE: - pathAttribute = NextHop.read(cb); - isNextHop = ((NextHop) pathAttribute).isNextHopSet(); - break; - case Med.MED_TYPE: - pathAttribute = Med.read(cb); - break; - case LocalPref.LOCAL_PREF_TYPE: - pathAttribute = LocalPref.read(cb); - break; - case MpReachNlri.MPREACHNLRI_TYPE: - pathAttribute = MpReachNlri.read(cb); - isMpReach = ((MpReachNlri) pathAttribute).isMpReachNlriSet(); - break; - case MpUnReachNlri.MPUNREACHNLRI_TYPE: - pathAttribute = MpUnReachNlri.read(cb); - isMpUnReach = ((MpUnReachNlri) pathAttribute) - .isMpUnReachNlriSet(); - break; - case LINK_STATE_ATTRIBUTE_TYPE: - //TODO: To be merged later - break; - default: - //skip bytes for unsupported attribute types - UnSupportedAttribute.read(cb); - } - pathAttributeList.add(pathAttribute); - } - - checkMandatoryAttr(isOrigin, isAsPath, isNextHop, isMpReach, isMpUnReach); - //TODO:if mp_reach or mp_unreach not present ignore the packet - return new BgpPathAttributes(pathAttributeList); - } - - /** - * Checks mandatory attributes are presents, if not present throws exception. - * - * @param isOrigin say whether origin attribute is present - * @param isAsPath say whether aspath attribute is present - * @param isNextHop say whether nexthop attribute is present - * @param isMpReach say whether mpreach attribute is present - * @param isMpUnReach say whether mpunreach attribute is present - * @throws BgpParseException if mandatory path attribute is not present - */ - public static void checkMandatoryAttr(boolean isOrigin, boolean isAsPath, - boolean isNextHop, boolean isMpReach, boolean isMpUnReach) - throws BgpParseException { - if (!isOrigin) { - log.debug("Mandatory Attributes not Present"); - Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, - Origin.ORIGIN_TYPE); - } - if (!isAsPath) { - log.debug("Mandatory Attributes not Present"); - Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, - AsPath.ASPATH_TYPE); - } - if (!isMpUnReach && !isMpReach && !isNextHop) { - log.debug("Mandatory Attributes not Present"); - Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, - NextHop.NEXTHOP_TYPE); - } - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("pathAttribute", pathAttribute) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java deleted file mode 100644 index 4d6af594..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol.ver4; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.IpPrefix; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.protocol.BgpType; -import org.onosproject.bgpio.protocol.BgpUpdateMsg; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.util.Validation; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * BGP Update Message: UPDATE messages are used to transfer routing information - * between BGP peers. The information in the UPDATE message is used by core to - * construct a graph - */ -public class BgpUpdateMsgVer4 implements BgpUpdateMsg { - - /* 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | | - + + - | Marker | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Length | Type | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Withdrawn Routes Length (2 octets) | - +-----------------------------------------------------+ - | Withdrawn Routes (variable) | - +-----------------------------------------------------+ - | Total Path Attribute Length (2 octets) | - +-----------------------------------------------------+ - | Path Attributes (variable) | - +-----------------------------------------------------+ - | Network Layer Reachability Information (variable) | - +-----------------------------------------------------+ - REFERENCE : RFC 4271 - */ - - protected static final Logger log = LoggerFactory - .getLogger(BgpUpdateMsgVer4.class); - - public static final byte PACKET_VERSION = 4; - //Withdrawn Routes Length(2) + Total Path Attribute Length(2) - public static final int PACKET_MINIMUM_LENGTH = 4; - public static final int BYTE_IN_BITS = 8; - public static final int MIN_LEN_AFTER_WITHDRW_ROUTES = 2; - public static final int MINIMUM_COMMON_HEADER_LENGTH = 19; - public static final BgpType MSG_TYPE = BgpType.UPDATE; - public static final BgpUpdateMsgVer4.Reader READER = new Reader(); - - private List withdrawnRoutes; - private BgpPathAttributes bgpPathAttributes; - private BgpHeader bgpHeader; - private List nlri; - - /** - * Constructor to initialize parameters for BGP Update message. - * - * @param bgpHeader in Update message - * @param withdrawnRoutes withdrawn routes - * @param bgpPathAttributes BGP Path attributes - * @param nlri Network Layer Reachability Information - */ - public BgpUpdateMsgVer4(BgpHeader bgpHeader, List withdrawnRoutes, - BgpPathAttributes bgpPathAttributes, List nlri) { - this.bgpHeader = bgpHeader; - this.withdrawnRoutes = withdrawnRoutes; - this.bgpPathAttributes = bgpPathAttributes; - this.nlri = nlri; - } - - /** - * Reader reads BGP Update Message from the channel buffer. - */ - static class Reader implements BgpMessageReader { - - @Override - public BgpUpdateMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) - throws BgpParseException { - - if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength()); - } - - LinkedList withDrwRoutes = new LinkedList<>(); - LinkedList nlri = new LinkedList<>(); - BgpPathAttributes bgpPathAttributes = new BgpPathAttributes(); - // Reading Withdrawn Routes Length - Short withDrwLen = cb.readShort(); - - if (cb.readableBytes() < withDrwLen) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, - cb.readableBytes()); - } - ChannelBuffer tempCb = cb.readBytes(withDrwLen); - if (withDrwLen != 0) { - // Parsing WithdrawnRoutes - withDrwRoutes = parseWithdrawnRoutes(tempCb); - } - if (cb.readableBytes() < MIN_LEN_AFTER_WITHDRW_ROUTES) { - log.debug("Bgp Path Attribute len field not present"); - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); - } - - // Reading Total Path Attribute Length - short totPathAttrLen = cb.readShort(); - int len = withDrwLen + totPathAttrLen + PACKET_MINIMUM_LENGTH; - if (len > bgpHeader.getLength()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); - } - if (totPathAttrLen != 0) { - // Parsing BGPPathAttributes - if (cb.readableBytes() < totPathAttrLen) { - Validation - .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, - cb.readableBytes()); - } - tempCb = cb.readBytes(totPathAttrLen); - bgpPathAttributes = BgpPathAttributes.read(tempCb); - } - if (cb.readableBytes() > 0) { - // Parsing NLRI - nlri = parseNlri(cb); - } - return new BgpUpdateMsgVer4(bgpHeader, withDrwRoutes, - bgpPathAttributes, nlri); - } - } - - /** - * Parses NLRI from channel buffer. - * - * @param cb channelBuffer - * @return list of IP Prefix - * @throws BgpParseException while parsing NLRI - */ - public static LinkedList parseNlri(ChannelBuffer cb) - throws BgpParseException { - LinkedList nlri = new LinkedList<>(); - while (cb.readableBytes() > 0) { - int length = cb.readByte(); - IpPrefix ipPrefix; - if (length == 0) { - byte[] prefix = new byte[] {0}; - ipPrefix = Validation.bytesToPrefix(prefix, length); - nlri.add(ipPrefix); - } else { - int len = length / BYTE_IN_BITS; - int reminder = length % BYTE_IN_BITS; - if (reminder > 0) { - len = len + 1; - } - if (cb.readableBytes() < len) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, - cb.readableBytes()); - } - byte[] prefix = new byte[len]; - cb.readBytes(prefix, 0, len); - ipPrefix = Validation.bytesToPrefix(prefix, length); - nlri.add(ipPrefix); - } - } - return nlri; - } - - /** - * Parsing withdrawn routes from channel buffer. - * - * @param cb channelBuffer - * @return list of IP prefix - * @throws BgpParseException while parsing withdrawn routes - */ - public static LinkedList parseWithdrawnRoutes(ChannelBuffer cb) - throws BgpParseException { - LinkedList withDrwRoutes = new LinkedList<>(); - while (cb.readableBytes() > 0) { - int length = cb.readByte(); - IpPrefix ipPrefix; - if (length == 0) { - byte[] prefix = new byte[] {0}; - ipPrefix = Validation.bytesToPrefix(prefix, length); - withDrwRoutes.add(ipPrefix); - } else { - int len = length / BYTE_IN_BITS; - int reminder = length % BYTE_IN_BITS; - if (reminder > 0) { - len = len + 1; - } - if (cb.readableBytes() < len) { - Validation - .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.MALFORMED_ATTRIBUTE_LIST, - cb.readableBytes()); - } - byte[] prefix = new byte[len]; - cb.readBytes(prefix, 0, len); - ipPrefix = Validation.bytesToPrefix(prefix, length); - withDrwRoutes.add(ipPrefix); - } - } - return withDrwRoutes; - } - - @Override - public BgpVersion getVersion() { - return BgpVersion.BGP_4; - } - - @Override - public BgpType getType() { - return BgpType.UPDATE; - } - - @Override - public void writeTo(ChannelBuffer channelBuffer) throws BgpParseException { - //Not to be implemented as of now - } - - @Override - public BgpPathAttributes bgpPathAttributes() { - return this.bgpPathAttributes; - } - - @Override - public List withdrawnRoutes() { - return withdrawnRoutes; - } - - @Override - public List nlri() { - return nlri; - } - - @Override - public BgpHeader getHeader() { - return this.bgpHeader; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("bgpHeader", bgpHeader) - .add("withDrawnRoutes", withdrawnRoutes) - .add("nlri", nlri) - .add("bgpPathAttributes", bgpPathAttributes) - .toString(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java deleted file mode 100755 index fb8c67c0..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * BGP Protocol specific details of version 4. - */ -package org.onosproject.bgpio.protocol.ver4; \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java deleted file mode 100644 index 842c6f02..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; - -import com.google.common.base.MoreObjects; - -/** - * Provides AreaID Tlv which contains opaque value (32 Bit Area-ID). - */ -public class AreaIDTlv implements BgpValueType { - - /* Reference :draft-ietf-idr-ls-distribution-11 - * 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type= 514 | Length=4 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | opaque value (32 Bit Area-ID) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - public static final short TYPE = 514; - public static final short LENGTH = 4; - - private final int areaID; - - /** - * Constructor to initialize areaID. - * - * @param areaID of BGP AreaID Tlv - */ - public AreaIDTlv(int areaID) { - this.areaID = areaID; - } - - /** - * Returns object of this class with specified areaID. - * - * @param areaID opaque value of area id - * @return object of AreaIDTlv - */ - public static AreaIDTlv of(final int areaID) { - return new AreaIDTlv(areaID); - } - - /** - * Returns opaque value of area id. - * - * @return opaque value of area id - */ - public int getAreaID() { - return areaID; - } - - @Override - public int hashCode() { - return Objects.hash(areaID); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof AreaIDTlv) { - AreaIDTlv other = (AreaIDTlv) obj; - return Objects.equals(areaID, other.areaID); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeInt(areaID); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of AreaIDTlv. - * - * @param cb ChannelBuffer - * @return object of AreaIDTlv - */ - public static AreaIDTlv read(ChannelBuffer cb) { - return AreaIDTlv.of(cb.readInt()); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Integer) (this.areaID)).compareTo((Integer) (((AreaIDTlv) o).areaID)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("Value", areaID) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java deleted file mode 100644 index 3ceca2ce..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of As4Path BGP Path Attribute. - */ -public class As4Path implements BgpValueType { - private static final Logger log = LoggerFactory.getLogger(AsPath.class); - public static final byte AS4PATH_TYPE = 17; - public static final byte ASNUM_SIZE = 4; - - private List as4pathSet; - private List as4pathSeq; - - /** - * Initialize fields. - */ - public As4Path() { - this.as4pathSeq = null; - this.as4pathSet = null; - } - - /** - * Constructor to initialize parameters. - * - * @param as4pathSet AS4path Set - * @param as4pathSeq AS4path Sequence - */ - public As4Path(List as4pathSet, List as4pathSeq) { - this.as4pathSeq = as4pathSeq; - this.as4pathSet = as4pathSet; - } - - /** - * Reads from the channel buffer and parses As4Path. - * - * @param cb ChannelBuffer - * @return object of As4Path - * @throws BgpParseException while parsing As4Path - */ - public static As4Path read(ChannelBuffer cb) throws BgpParseException { - List as4pathSet = new ArrayList<>(); - List as4pathSeq = new ArrayList<>(); - ChannelBuffer tempCb = cb.copy(); - Validation validation = Validation.parseAttributeHeader(cb); - - if (cb.readableBytes() < validation.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - validation.getLength()); - } - //if fourth bit is set length is read as short otherwise as byte , len includes type, length and value - int len = validation.isShort() ? validation.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : validation - .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - ChannelBuffer tempBuf = cb.readBytes(validation.getLength()); - while (tempBuf.readableBytes() > 0) { - byte pathSegType = tempBuf.readByte(); - //no of ASes - byte pathSegLen = tempBuf.readByte(); - //length = no of Ases * ASnum size (4 bytes) - int length = pathSegLen * ASNUM_SIZE; - if (tempBuf.readableBytes() < length) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length); - } - ChannelBuffer aspathBuf = tempBuf.readBytes(length); - while (aspathBuf.readableBytes() > 0) { - int asNum; - asNum = aspathBuf.readInt(); - switch (pathSegType) { - case AsPath.ASPATH_SET_TYPE: - as4pathSet.add(asNum); - break; - case AsPath.ASPATH_SEQ_TYPE: - as4pathSeq.add(asNum); - break; - default: log.debug("Other type Not Supported:" + pathSegType); - } - } - } - return new As4Path(as4pathSet, as4pathSeq); - } - - @Override - public short getType() { - return AS4PATH_TYPE; - } - - /** - * Returns list of ASNum in AS4path Sequence. - * - * @return list of ASNum in AS4path Sequence - */ - public List as4PathSEQ() { - return this.as4pathSeq; - } - - /** - * Returns list of ASNum in AS4path Set. - * - * @return list of ASNum in AS4path Set - */ - public List as4PathSET() { - return this.as4pathSet; - } - - @Override - public int hashCode() { - return Objects.hash(as4pathSet, as4pathSeq); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof As4Path) { - As4Path other = (As4Path) obj; - return Objects.equals(as4pathSet, other.as4pathSet) && Objects.equals(as4pathSeq, other.as4pathSeq); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("as4pathSet", as4pathSet) - .add("as4pathSeq", as4pathSeq) - .toString(); - } - - @Override - public int write(ChannelBuffer cb) { - //Not required to Implement as of now - return 0; - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java deleted file mode 100644 index 2a050c44..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of AsPath mandatory BGP Path Attribute. - */ -public class AsPath implements BgpValueType { - /** - * Enum to provide AS types. - */ - public enum ASTYPE { - AS_SET(1), AS_SEQUENCE(2), AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4); - int value; - - /** - * Assign val with the value as the AS type. - * - * @param val AS type - */ - ASTYPE(int val) { - value = val; - } - - /** - * Returns value of AS type. - * - * @return AS type - */ - public byte type() { - return (byte) value; - } - } - - private static final Logger log = LoggerFactory.getLogger(AsPath.class); - public static final byte ASPATH_TYPE = 2; - public static final byte ASPATH_SET_TYPE = 1; - public static final byte ASPATH_SEQ_TYPE = 2; - public static final byte ASNUM_SIZE = 2; - - private boolean isAsPath = false; - private List aspathSet; - private List aspathSeq; - - /** - * Initialize Fields. - */ - public AsPath() { - this.aspathSeq = null; - this.aspathSet = null; - } - - /** - * Constructor to initialize parameters. - * - * @param aspathSet ASpath Set type - * @param aspathSeq ASpath Sequence type - */ - public AsPath(List aspathSet, List aspathSeq) { - this.aspathSeq = aspathSeq; - this.aspathSet = aspathSet; - this.isAsPath = true; - } - - /** - * Reads from the channel buffer and parses AsPath. - * - * @param cb ChannelBuffer - * @return object of AsPath - * @throws BgpParseException while parsing AsPath - */ - public static AsPath read(ChannelBuffer cb) throws BgpParseException { - List aspathSet = new ArrayList<>(); - List aspathSeq = new ArrayList<>(); - ChannelBuffer tempCb = cb.copy(); - Validation validation = Validation.parseAttributeHeader(cb); - - if (cb.readableBytes() < validation.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - validation.getLength()); - } - //if fourth bit is set, length is read as short otherwise as byte , len includes type, length and value - int len = validation.isShort() ? validation.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : validation - .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - ChannelBuffer tempBuf = cb.readBytes(validation.getLength()); - while (tempBuf.readableBytes() > 0) { - byte pathSegType = tempBuf.readByte(); - //no of ASes - byte pathSegLen = tempBuf.readByte(); - int length = pathSegLen * ASNUM_SIZE; - if (tempBuf.readableBytes() < length) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length); - } - ChannelBuffer aspathBuf = tempBuf.readBytes(length); - while (aspathBuf.readableBytes() > 0) { - short asNum; - asNum = aspathBuf.readShort(); - switch (pathSegType) { - case ASPATH_SET_TYPE: - aspathSet.add(asNum); - break; - case ASPATH_SEQ_TYPE: - aspathSeq.add(asNum); - break; - default: log.debug("Other type Not Supported:" + pathSegType); - } - } - } - return new AsPath(aspathSet, aspathSeq); - } - - @Override - public short getType() { - return ASPATH_TYPE; - } - - /** - * Returns whether ASpath path attribute is present. - * - * @return whether ASpath path attribute is present - */ - public boolean isaspathSet() { - return this.isAsPath; - } - - /** - * Returns list of ASNum in ASpath Sequence. - * - * @return list of ASNum in ASpath Sequence - */ - public List asPathSeq() { - return this.aspathSeq; - } - - /** - * Returns list of ASNum in ASpath SET. - * - * @return list of ASNum in ASpath SET - */ - public List asPathSet() { - return this.aspathSet; - } - - @Override - public int hashCode() { - return Objects.hash(aspathSet, aspathSeq); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof AsPath) { - AsPath other = (AsPath) obj; - return Objects.equals(aspathSet, other.aspathSet) && Objects.equals(aspathSeq, other.aspathSeq); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("aspathSet", aspathSet) - .add("aspathSeq", aspathSeq) - .toString(); - } - - @Override - public int write(ChannelBuffer cb) { - //Not required to Implement as of now - return 0; - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java deleted file mode 100644 index 119926c8..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; - -import com.google.common.base.MoreObjects; - -/** - * Provides Autonomous System Tlv which contains opaque value (32 Bit AS Number). - */ -public class AutonomousSystemTlv implements BgpValueType { - - /* Reference :draft-ietf-idr-ls-distribution-11 - * 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type= 512 | Length=4 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | opaque value (32 Bit AS Number) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - public static final short TYPE = 512; - public static final short LENGTH = 4; - - private final int asNum; - - /** - * Constructor to initialize asNum. - * - * @param asNum 32 Bit AS Number - */ - public AutonomousSystemTlv(int asNum) { - this.asNum = asNum; - } - - /** - * Returns object of this class with specified asNum. - * - * @param asNum 32 Bit AS Number - * @return object of AutonomousSystemTlv - */ - public static AutonomousSystemTlv of(final int asNum) { - return new AutonomousSystemTlv(asNum); - } - - /** - * Returns opaque value of AS Number. - * - * @return opaque value of AS Number - */ - public int getAsNum() { - return asNum; - } - - @Override - public int hashCode() { - return Objects.hash(asNum); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof AutonomousSystemTlv) { - AutonomousSystemTlv other = (AutonomousSystemTlv) obj; - return Objects.equals(asNum, other.asNum); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeInt(asNum); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of AutonomousSystemTlv. - * - * @param c ChannelBuffer - * @return object of AutonomousSystemTlv - */ - public static AutonomousSystemTlv read(ChannelBuffer c) { - return AutonomousSystemTlv.of(c.readInt()); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Integer) (this.asNum)).compareTo((Integer) (((AutonomousSystemTlv) o).asNum)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("asNum", asNum) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java deleted file mode 100644 index c0932ebe..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -/** - * BgpErrorType class defines all errorCodes and error Subcodes required for Notification message. - */ -public final class BgpErrorType { - private BgpErrorType() { - } - - //Error Codes - public static final byte MESSAGE_HEADER_ERROR = 1; - public static final byte OPEN_MESSAGE_ERROR = 2; - public static final byte UPDATE_MESSAGE_ERROR = 3; - public static final byte HOLD_TIMER_EXPIRED = 4; - public static final byte FINITE_STATE_MACHINE_ERROR = 5; - public static final byte CEASE = 6; - - //Message Header Error subcodes - public static final byte CONNECTION_NOT_SYNCHRONIZED = 1; - public static final byte BAD_MESSAGE_LENGTH = 2; - public static final byte BAD_MESSAGE_TYPE = 3; - - //OPEN Message Error subcodes - public static final byte UNSUPPORTED_VERSION_NUMBER = 1; - public static final byte BAD_PEER_AS = 2; - public static final byte BAD_BGP_IDENTIFIER = 3; - public static final byte UNSUPPORTED_OPTIONAL_PARAMETER = 4; - public static final byte UNACCEPTABLE_HOLD_TIME = 5; - public static final byte UNSUPPORTED_CAPABILITY = 7; - - //UPDATE Message Error subcodes - public static final byte MALFORMED_ATTRIBUTE_LIST = 1; - public static final byte UNRECOGNIZED_WELLKNOWN_ATTRIBUTE = 2; - public static final byte MISSING_WELLKNOWN_ATTRIBUTE = 3; - public static final byte ATTRIBUTE_FLAGS_ERROR = 4; - public static final byte ATTRIBUTE_LENGTH_ERROR = 5; - public static final byte INVALID_ORIGIN_ATTRIBUTE = 6; - public static final byte INVALID_NEXTHOP_ATTRIBUTE = 8; - public static final byte OPTIONAL_ATTRIBUTE_ERROR = 9; - public static final byte INVALID_NETWORK_FIELD = 10; - public static final byte MALFORMED_ASPATH = 11; - - //FSM Error subcodes - public static final byte UNSPECIFIED_ERROR = 0; - public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE = 1; - public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE = 2; - public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_ESTABLISHED_STATE = 3; - - //Cease Error subcodes - public static final byte MAXIMUM_NUMBER_OF_PREFIXES_REACHED = 1; - public static final byte ADMINISTRATIVE_SHUTDOWN = 2; - public static final byte PEER_DECONFIGURED = 3; - public static final byte ADMINISTRATIVE_RESET = 4; - public static final byte CONNECTION_REJECTED = 5; - public static final byte OTHER_CONFIGURATION_CHANGE = 6; - public static final byte CONNECTION_COLLISION_RESOLUTION = 7; - public static final byte OUT_OF_RESOURCES = 8; -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java deleted file mode 100755 index ad637753..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides BGP Message Header which is common for all the Messages. - */ - -public class BgpHeader { - - /* 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | | - + + - | Marker | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Length | Type | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - protected static final Logger log = LoggerFactory.getLogger(BgpHeader.class); - - public static final int MARKER_LENGTH = 16; - public static final short DEFAULT_HEADER_LENGTH = 19; - - private byte[] marker; - private byte type; - private short length; - - /** - * Reset fields. - */ - public BgpHeader() { - this.marker = null; - this.length = 0; - this.type = 0; - } - - /** - * Constructors to initialize parameters. - * - * @param marker field in BGP header - * @param length message length - * @param type message type - */ - public BgpHeader(byte[] marker, short length, byte type) { - this.marker = marker; - this.length = length; - this.type = type; - } - - /** - * Sets marker field. - * - * @param value marker field - */ - public void setMarker(byte[] value) { - this.marker = value; - } - - /** - * Sets message type. - * - * @param value message type - */ - public void setType(byte value) { - this.type = value; - } - - /** - * Sets message length. - * - * @param value message length - */ - public void setLength(short value) { - this.length = value; - } - - /** - * Returns message length. - * - * @return message length - */ - public short getLength() { - return this.length; - } - - /** - * Returns message marker. - * - * @return message marker - */ - public byte[] getMarker() { - return this.marker; - } - - /** - * Returns message type. - * - * @return message type - */ - public byte getType() { - return this.type; - } - - /** - * Writes Byte stream of BGP header to channel buffer. - * - * @param cb ChannelBuffer - * @return length index of message header - */ - public int write(ChannelBuffer cb) { - - cb.writeBytes(getMarker(), 0, MARKER_LENGTH); - - int headerLenIndex = cb.writerIndex(); - cb.writeShort((short) 0); - cb.writeByte(type); - - return headerLenIndex; - } - - /** - * Read from channel buffer and Returns BGP header. - * - * @param cb ChannelBuffer - * @return object of BGPHeader - */ - public static BgpHeader read(ChannelBuffer cb) { - - byte[] marker = new byte[MARKER_LENGTH]; - byte type; - short length; - cb.readBytes(marker, 0, MARKER_LENGTH); - length = cb.readShort(); - type = cb.readByte(); - return new BgpHeader(marker, length, type); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java deleted file mode 100644 index 58645d4f..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; - -import com.google.common.base.MoreObjects; - -/** - * Provides BGPLSIdentifier Tlv which contains opaque value (32 Bit BGPLS-Identifier). - */ -public class BgpLSIdentifierTlv implements BgpValueType { - - /* Reference :draft-ietf-idr-ls-distribution-11 - * 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type= 513 | Length=4 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | opaque value (32 Bit BGPLS-Identifier) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - public static final short TYPE = 513; - public static final short LENGTH = 4; - - private final int bgpLsIdentifier; - - /** - * Constructor to initialize bgpLsIdentifier. - * - * @param bgpLsIdentifier BGPLS-Identifier - */ - public BgpLSIdentifierTlv(int bgpLsIdentifier) { - this.bgpLsIdentifier = bgpLsIdentifier; - } - - /** - * Returns object of this class with specified bgpLsIdentifier. - * - * @param bgpLsIdentifier BGPLS-Identifier - * @return BGPLS-Identifier - */ - public static BgpLSIdentifierTlv of(final int bgpLsIdentifier) { - return new BgpLSIdentifierTlv(bgpLsIdentifier); - } - - /** - * Returns opaque value of BGPLS-Identifier. - * - * @return opaque value of BGPLS-Identifier - */ - public int getBgpLsIdentifier() { - return bgpLsIdentifier; - } - - @Override - public int hashCode() { - return Objects.hash(bgpLsIdentifier); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLSIdentifierTlv) { - BgpLSIdentifierTlv other = (BgpLSIdentifierTlv) obj; - return Objects.equals(bgpLsIdentifier, other.bgpLsIdentifier); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeInt(bgpLsIdentifier); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and parses BGPLS Identifier TLV. - * - * @param cb ChannelBuffer - * @return object of BGPLSIdentifierTlv - */ - public static BgpLSIdentifierTlv read(ChannelBuffer cb) { - return BgpLSIdentifierTlv.of(cb.readInt()); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Integer) (this.bgpLsIdentifier)).compareTo((Integer) (((BgpLSIdentifierTlv) o).bgpLsIdentifier)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("Value", bgpLsIdentifier) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java deleted file mode 100644 index af7f4b75..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Abstraction which Provides the BGP of TLV format. - */ -public interface BgpValueType { - /** - * Returns the Type of BGP Message. - * - * @return short value of type - */ - short getType(); - - /** - * Writes the byte Stream of BGP Message to channel buffer. - * - * @param cb channel buffer - * @return length written to channel buffer - */ - int write(ChannelBuffer cb); - - /** - * Compares two objects. - * - * @param o object - * @return result after comparing two objects - */ - int compareTo(Object o); -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java deleted file mode 100644 index 59db3318..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides FourOctetAsNumCapabilityTlv Capability Tlv. - */ -public class FourOctetAsNumCapabilityTlv implements BgpValueType { - - /** - * support to indicate its support for four-octet AS numbers -CAPABILITY TLV format. - */ - protected static final Logger log = LoggerFactory - .getLogger(FourOctetAsNumCapabilityTlv.class); - - public static final byte TYPE = 65; - public static final byte LENGTH = 4; - - private final int rawValue; - - /** - * constructor to initialize rawValue. - * @param rawValue FourOctetAsNumCapabilityTlv - */ - public FourOctetAsNumCapabilityTlv(int rawValue) { - this.rawValue = rawValue; - } - - /** - * constructor to initialize raw. - * @param raw AS number - * @return object of FourOctetAsNumCapabilityTlv - */ - public static FourOctetAsNumCapabilityTlv of(final int raw) { - return new FourOctetAsNumCapabilityTlv(raw); - } - - /** - * Returns value of TLV. - * @return int value of rawValue - */ - public int getInt() { - return rawValue; - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int hashCode() { - return Objects.hash(rawValue); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof FourOctetAsNumCapabilityTlv) { - FourOctetAsNumCapabilityTlv other = (FourOctetAsNumCapabilityTlv) obj; - return Objects.equals(rawValue, other.rawValue); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeByte(TYPE); - cb.writeByte(LENGTH); - cb.writeInt(rawValue); - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of FourOctetAsNumCapabilityTlv. - * @param cb type of channel buffer - * @return object of FourOctetAsNumCapabilityTlv - */ - public static FourOctetAsNumCapabilityTlv read(ChannelBuffer cb) { - return FourOctetAsNumCapabilityTlv.of(cb.readInt()); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("Value", rawValue).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java deleted file mode 100644 index d97537e8..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.IpPrefix; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; - -/** - * Provides IP Reachability InformationTlv Tlv which contains IP Prefix. - */ -public class IPReachabilityInformationTlv implements BgpValueType { - - /* - * Reference :draft-ietf-idr-ls-distribution-11 - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prefix Length | IP Prefix (variable) // - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Figure 14: IP Reachability Information TLV Format - */ - - public static final short TYPE = 265; - public static final int ONE_BYTE_LEN = 8; - - private byte prefixLen; - private byte[] ipPrefix; - public short length; - - /** - * Constructor to initialize parameters. - * - * @param prefixLen length of IP Prefix - * @param ipPrefix IP Prefix - * @param length length of value field - */ - public IPReachabilityInformationTlv(byte prefixLen, byte[] ipPrefix, short length) { - this.ipPrefix = ipPrefix; - this.prefixLen = prefixLen; - this.length = length; - } - - /** - * Returns IP Prefix. - * - * @return IP Prefix - */ - public IpPrefix getPrefixValue() { - IpPrefix prefix = Validation.bytesToPrefix(ipPrefix, prefixLen); - return prefix; - } - - /** - * Returns IP Prefix length. - * - * @return IP Prefix length - */ - public byte getPrefixLen() { - return this.prefixLen; - } - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(ipPrefix), prefixLen); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof IPReachabilityInformationTlv) { - IPReachabilityInformationTlv other = (IPReachabilityInformationTlv) obj; - return Objects.equals(prefixLen, other.prefixLen) && Arrays.equals(ipPrefix, other.ipPrefix); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeShort(TYPE); - cb.writeShort(length); - cb.writeByte(prefixLen); - cb.writeBytes(ipPrefix); - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of IPReachabilityInformationTlv. - * - * @param cb ChannelBuffer - * @param length of value field - * @return object of IPReachabilityInformationTlv - */ - public static IPReachabilityInformationTlv read(ChannelBuffer cb, short length) { - byte preficLen = cb.readByte(); - byte[] prefix; - if (preficLen == 0) { - prefix = new byte[] {0}; - } else { - int len = preficLen / ONE_BYTE_LEN; - int reminder = preficLen % ONE_BYTE_LEN; - if (reminder > 0) { - len = len + 1; - } - prefix = new byte[len]; - cb.readBytes(prefix, 0, len); - } - return IPReachabilityInformationTlv.of(preficLen, prefix, length); - } - - public static IPReachabilityInformationTlv of(final byte preficLen, final byte[] prefix, final short length) { - return new IPReachabilityInformationTlv(preficLen, prefix, length); - } - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - ByteBuffer value1 = ByteBuffer.wrap(this.ipPrefix); - ByteBuffer value2 = ByteBuffer.wrap(((IPReachabilityInformationTlv) o).ipPrefix); - return value1.compareTo(value2); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", length) - .add("Prefixlength", getPrefixLen()) - .add("Prefixvalue", getPrefixValue()) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java deleted file mode 100644 index 4efde70e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.net.InetAddress; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; - -/** - * Provides Implementation of IPv4AddressTlv. - */ -public class IPv4AddressTlv implements BgpValueType { - private static final int LENGTH = 4; - - private Ip4Address address; - private short type; - - /** - * Constructor to initialize parameters. - * - * @param address Ipv4 address of interface/neighbor - * @param type address type - */ - public IPv4AddressTlv(Ip4Address address, short type) { - this.address = Preconditions.checkNotNull(address); - this.type = type; - } - - /** - * Returns Ipv4 address of interface/neighbor. - * - * @return Ipv4 address of interface/neighbor - */ - public Ip4Address address() { - return address; - } - - @Override - public short getType() { - return this.type; - } - - @Override - public int hashCode() { - return Objects.hash(address); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof IPv4AddressTlv) { - IPv4AddressTlv other = (IPv4AddressTlv) obj; - return Objects.equals(this.address, other.address) && Objects.equals(this.type, other.type); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeShort(type); - cb.writeShort(LENGTH); - cb.writeInt(address.toInt()); - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of IPv4AddressTlv. - * - * @param cb channelBuffer - * @param type address type - * @return object of IPv4AddressTlv - * @throws BgpParseException while parsing IPv4AddressTlv - */ - public static IPv4AddressTlv read(ChannelBuffer cb, short type) throws BgpParseException { - InetAddress ipAddress = Validation.toInetAddress(LENGTH, cb); - if (ipAddress.isMulticastAddress()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); - } - Ip4Address address = Ip4Address.valueOf(ipAddress); - return IPv4AddressTlv.of(address, type); - } - - /** - * Returns object of this class with specified values. - * - * @param address Ipv4 interface/neighbor Address - * @param type says Ipv4 address of interface/neighbor tlv type - * @return object of this class - */ - public static IPv4AddressTlv of(final Ip4Address address , final short type) { - return new IPv4AddressTlv(address, type); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Ip4Address) (this.address)).compareTo((Ip4Address) (((IPv4AddressTlv) o).address)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("type", type) - .add("LENGTH", LENGTH) - .add("address", address) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java deleted file mode 100644 index 087cd5c6..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.net.InetAddress; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip6Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; - -/** - * Provides Implementation of IPv6AddressTlv. - */ -public class IPv6AddressTlv implements BgpValueType { - private static final int LENGTH = 16; - - private final Ip6Address address; - private short type; - - /** - * Constructor to initialize parameters. - * - * @param address Ipv6 address of interface/neighbor - * @param type address type - */ - public IPv6AddressTlv(Ip6Address address, short type) { - this.address = Preconditions.checkNotNull(address); - this.type = type; - } - - /** - * Returns Ipv6 address of interface/neighbor. - * - * @return Ipv6 address of interface/neighbor - */ - public Ip6Address address() { - return address; - } - - @Override - public short getType() { - return type; - } - - @Override - public int hashCode() { - return Objects.hash(address); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof IPv6AddressTlv) { - IPv6AddressTlv other = (IPv6AddressTlv) obj; - return Objects.equals(this.address, other.address) && Objects.equals(this.type, other.type); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeShort(type); - cb.writeShort(LENGTH); - cb.writeBytes(address.toOctets()); - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of IPv6AddressTlv. - * - * @param cb channelBuffer - * @param type address type - * @return object of IPv6AddressTlv - * @throws BgpParseException while parsing IPv6AddressTlv - */ - public static IPv6AddressTlv read(ChannelBuffer cb, short type) throws BgpParseException { - InetAddress ipAddress = Validation.toInetAddress(LENGTH, cb); - if (ipAddress.isMulticastAddress()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); - } - Ip6Address address = Ip6Address.valueOf(ipAddress); - return IPv6AddressTlv.of(address, type); - } - - /** - * Returns object of this class with specified values. - * - * @param address Ipv6 interface/neighbor address - * @param type says Ipv6 address of interface/neighbor tlv type - * @return object of this class - */ - public static IPv6AddressTlv of(final Ip6Address address , final short type) { - return new IPv6AddressTlv(address, type); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Ip6Address) (this.address)).compareTo((Ip6Address) (((IPv6AddressTlv) o).address)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("type", type) - .add("LENGTH", LENGTH) - .add("address", address) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java deleted file mode 100644 index 427aa929..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.protocol.IGPRouterID; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of IsIsNonPseudonode Tlv. - */ -public class IsIsNonPseudonode implements IGPRouterID, BgpValueType { - public static final short TYPE = 515; - public static final short LENGTH = 6; - - private final byte[] isoNodeID; - - /** - * Constructor to initialize isoNodeID. - * - * @param isoNodeID ISO system-ID - */ - public IsIsNonPseudonode(byte[] isoNodeID) { - this.isoNodeID = Arrays.copyOf(isoNodeID, isoNodeID.length); - } - - /** - * Returns object of this class with specified isoNodeID. - * - * @param isoNodeID ISO system-ID - * @return object of IsIsNonPseudonode - */ - public static IsIsNonPseudonode of(final byte[] isoNodeID) { - return new IsIsNonPseudonode(isoNodeID); - } - - /** - * Returns ISO NodeID. - * - * @return ISO NodeID - */ - public byte[] getISONodeID() { - return isoNodeID; - } - - @Override - public int hashCode() { - return Arrays.hashCode(isoNodeID); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof IsIsNonPseudonode) { - IsIsNonPseudonode other = (IsIsNonPseudonode) obj; - return Arrays.equals(isoNodeID, other.isoNodeID); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeBytes(isoNodeID); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of IsIsNonPseudonode. - * - * @param cb ChannelBuffer - * @return object of IsIsNonPseudonode - */ - public static IsIsNonPseudonode read(ChannelBuffer cb) { - byte[] isoNodeID = new byte[LENGTH]; - cb.readBytes(isoNodeID); - return IsIsNonPseudonode.of(isoNodeID); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - ByteBuffer value1 = ByteBuffer.wrap(this.isoNodeID); - ByteBuffer value2 = ByteBuffer.wrap(((IsIsNonPseudonode) o).isoNodeID); - return value1.compareTo(value2); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("ISONodeID", isoNodeID) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java deleted file mode 100644 index 094c4382..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.protocol.IGPRouterID; - -import com.google.common.base.MoreObjects; - -/** - * Provides implementation of IsIsPseudonode Tlv. - */ -public class IsIsPseudonode implements IGPRouterID, BgpValueType { - public static final short TYPE = 515; - public static final short LENGTH = 7; - - private final byte[] isoNodeID; - private byte psnIdentifier; - - /** - * Constructor to initialize isoNodeID. - * - * @param isoNodeID ISO system-ID - * @param psnIdentifier PSN identifier - */ - public IsIsPseudonode(byte[] isoNodeID, byte psnIdentifier) { - this.isoNodeID = Arrays.copyOf(isoNodeID, isoNodeID.length); - this.psnIdentifier = psnIdentifier; - } - - /** - * Returns object of this class with specified values. - * - * @param isoNodeID ISO system-ID - * @param psnIdentifier PSN identifier - * @return object of IsIsPseudonode - */ - public static IsIsPseudonode of(final byte[] isoNodeID, - final byte psnIdentifier) { - return new IsIsPseudonode(isoNodeID, psnIdentifier); - } - - /** - * Returns ISO NodeID. - * - * @return ISO NodeID - */ - public byte[] getISONodeID() { - return isoNodeID; - } - - /** - * Returns PSN Identifier. - * - * @return PSN Identifier - */ - public byte getPSNIdentifier() { - return this.psnIdentifier; - } - - @Override - public int hashCode() { - return Arrays.hashCode(isoNodeID) & Objects.hash(psnIdentifier); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof IsIsPseudonode) { - IsIsPseudonode other = (IsIsPseudonode) obj; - return Arrays.equals(isoNodeID, other.isoNodeID) - && Objects.equals(psnIdentifier, other.psnIdentifier); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeBytes(isoNodeID, 0, LENGTH - 1); - c.writeByte(psnIdentifier); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of IsIsPseudonode. - * - * @param cb ChannelBuffer - * @return object of IsIsPseudonode - */ - public static IsIsPseudonode read(ChannelBuffer cb) { - byte[] isoNodeID = new byte[LENGTH - 1]; - cb.readBytes(isoNodeID); - byte psnIdentifier = cb.readByte(); - return IsIsPseudonode.of(isoNodeID, psnIdentifier); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - ByteBuffer value1 = ByteBuffer.wrap(this.isoNodeID); - ByteBuffer value2 = ByteBuffer.wrap(((IsIsPseudonode) o).isoNodeID); - if (value1.compareTo(value2) != 0) { - return value1.compareTo(value2); - } - return ((Byte) (this.psnIdentifier)).compareTo((Byte) (((IsIsPseudonode) o).psnIdentifier)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("isoNodeID", isoNodeID) - .add("psnIdentifier", psnIdentifier) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java deleted file mode 100644 index 0c412432..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of Link Local/Remote IdentifiersTlv. - */ -public class LinkLocalRemoteIdentifiersTlv implements BgpValueType { - public static final short TYPE = 258; - private static final int LENGTH = 8; - - private final int linkLocalIdentifer; - private final int linkRemoteIdentifer; - - /** - * Constructor to initialize parameters. - * - * @param linkLocalIdentifer link local Identifer - * @param linkRemoteIdentifer link remote Identifer - */ - public LinkLocalRemoteIdentifiersTlv(int linkLocalIdentifer, int linkRemoteIdentifer) { - this.linkLocalIdentifer = linkLocalIdentifer; - this.linkRemoteIdentifer = linkRemoteIdentifer; - } - - /** - * Returns link remote Identifer. - * - * @return link remote Identifer - */ - public int getLinkRemoteIdentifier() { - return linkRemoteIdentifer; - } - - /** - * Returns link local Identifer. - * - * @return link local Identifer - */ - public int getLinkLocalIdentifier() { - return linkLocalIdentifer; - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int hashCode() { - return Objects.hash(linkLocalIdentifer, linkRemoteIdentifer); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof LinkLocalRemoteIdentifiersTlv) { - LinkLocalRemoteIdentifiersTlv other = (LinkLocalRemoteIdentifiersTlv) obj; - return Objects.equals(this.linkLocalIdentifer, other.linkLocalIdentifer) - && Objects.equals(this.linkRemoteIdentifer, other.linkRemoteIdentifer); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeShort(TYPE); - cb.writeShort(LENGTH); - cb.writeInt(linkLocalIdentifer); - cb.writeInt(linkRemoteIdentifer); - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of LinkLocalRemoteIdentifiersTlv. - * - * @param cb channelBuffer - * @return object of LinkLocalRemoteIdentifiersTlv - */ - public static LinkLocalRemoteIdentifiersTlv read(ChannelBuffer cb) { - int linkLocalIdentifer = cb.readInt(); - int linkRemoteIdentifer = cb.readInt(); - return LinkLocalRemoteIdentifiersTlv.of(linkLocalIdentifer, linkRemoteIdentifer); - } - - /** - * Returns object of this class with specified link local identifer and link remote identifer. - * - * @param linkLocalIdentifer link local identifier - * @param linkRemoteIdentifer link remote identifier - * @return object of LinkLocalRemoteIdentifiersTlv - */ - public static LinkLocalRemoteIdentifiersTlv of(final int linkLocalIdentifer, final int linkRemoteIdentifer) { - return new LinkLocalRemoteIdentifiersTlv(linkLocalIdentifer, linkRemoteIdentifer); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - int result = ((Integer) (this.linkLocalIdentifer)) - .compareTo((Integer) (((LinkLocalRemoteIdentifiersTlv) o).linkLocalIdentifer)); - if (result != 0) { - return result; - } - return ((Integer) (this.linkRemoteIdentifer)) - .compareTo((Integer) (((LinkLocalRemoteIdentifiersTlv) o).linkRemoteIdentifer)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("TYPE", TYPE) - .add("LENGTH", LENGTH) - .add("linkLocalIdentifer", linkLocalIdentifer) - .add("linkRemoteIdentifer", linkRemoteIdentifer) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java deleted file mode 100644 index cdf6ebeb..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv; -import org.onosproject.bgpio.types.attr.BgpAttrNodeIsIsAreaId; -import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; -import org.onosproject.bgpio.types.attr.BgpAttrNodeName; -import org.onosproject.bgpio.types.attr.BgpAttrOpaqueNode; -import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV4; -import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV6; -import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric; -import org.onosproject.bgpio.types.attr.BgpLinkAttrIsIsAdminstGrp; -import org.onosproject.bgpio.types.attr.BgpLinkAttrMplsProtocolMask; -import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth; -import org.onosproject.bgpio.types.attr.BgpLinkAttrName; -import org.onosproject.bgpio.types.attr.BgpLinkAttrOpaqLnkAttrib; -import org.onosproject.bgpio.types.attr.BgpLinkAttrProtectionType; -import org.onosproject.bgpio.types.attr.BgpLinkAttrSrlg; -import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric; -import org.onosproject.bgpio.types.attr.BgpLinkAttrUnRsrvdLinkBandwidth; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrExtRouteTag; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrIgpFlags; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrMetric; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrOspfFwdAddr; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrOpaqueData; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrRouteTag; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP Link state attribute. - */ -public class LinkStateAttributes implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(LinkStateAttributes.class); - - /* Node Attributes */ - public static final short ATTR_NODE_MT_TOPOLOGY_ID = 263; - public static final short ATTR_NODE_FLAG_BITS = 1024; - public static final short ATTR_NODE_OPAQUE_NODE = 1025; - public static final short ATTR_NODE_NAME = 1026; - public static final short ATTR_NODE_ISIS_AREA_ID = 1027; - public static final short ATTR_NODE_IPV4_LOCAL_ROUTER_ID = 1028; - public static final short ATTR_NODE_IPV6_LOCAL_ROUTER_ID = 1029; - - /* Link Attributes */ - public static final short ATTR_LINK_IPV4_REMOTE_ROUTER_ID = 1030; - public static final short ATTR_LINK_IPV6_REMOTE_ROUTER_ID = 1031; - public static final short ATTR_LINK_ADMINISTRATIVE_GRPS = 1088; - public static final short ATTR_LINK_MAX_BANDWIDTH = 1089; - public static final short ATTR_LINK_MAX_RES_BANDWIDTH = 1090; - public static final short ATTR_LINK_UNRES_BANDWIDTH = 1091; - public static final short ATTR_LINK_TE_DEFAULT_METRIC = 1092; - public static final short ATTR_LINK_PROTECTION_TYPE = 1093; - public static final short ATTR_LINK_MPLS_PROTOCOL_MASK = 1094; - public static final short ATTR_LINK_IGP_METRIC = 1095; - public static final short ATTR_LINK_SHR_RISK_GRP = 1096; - public static final short ATTR_LINK_OPAQUE_ATTR = 1097; - public static final short ATTR_LINK_NAME_ATTR = 1098; - - /* Prefix Attributes */ - public static final short ATTR_PREFIX_IGP_FLAG = 1152; - public static final short ATTR_PREFIX_ROUTE_TAG = 1153; - public static final short ATTR_PREFIX_EXTENDED_TAG = 1154; - public static final short ATTR_PREFIX_METRIC = 1155; - public static final short ATTR_PREFIX_OSPF_FWD_ADDR = 1156; - public static final short ATTR_PREFIX_OPAQUE_ATTR = 1157; - - public static final byte LINKSTATE_ATTRIB_TYPE = 50; - public static final byte TYPE_AND_LEN = 4; - private boolean isLinkStateAttribute = false; - private List linkStateAttribList; - - /** - * Constructor to reset parameters. - */ - LinkStateAttributes() { - this.linkStateAttribList = null; - } - - /** - * Constructor to initialize parameters. - * - * @param linkStateAttribList Linked list of Link, Node and Prefix TLVs - */ - LinkStateAttributes(List linkStateAttribList) { - this.linkStateAttribList = linkStateAttribList; - this.isLinkStateAttribute = true; - } - - /** - * Returns linked list of Link, Node and Prefix TLVs. - * - * @return linked list of Link, Node and Prefix TLVs - */ - public List linkStateAttributes() { - return this.linkStateAttribList; - } - - /** - * Returns if the Link state attributes are set or not. - * - * @return a boolean value to to check if the LS attributes are set or not - */ - public boolean isLinkStateAttributeSet() { - return this.isLinkStateAttribute; - } - - /** - * Reads the Link state attribute TLVs. - * - * @param cb ChannelBuffer - * @return constructor of LinkStateAttributes - * @throws BgpParseException while parsing link state attributes - */ - public static LinkStateAttributes read(ChannelBuffer cb) - throws BgpParseException { - - ChannelBuffer tempBuf = cb; - Validation parseFlags = Validation.parseAttributeHeader(cb); - int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN - : parseFlags.getLength() + 3; - - ChannelBuffer data = tempBuf.readBytes(len); - if (!parseFlags.getFirstBit() || parseFlags.getSecondBit() - || parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_FLAGS_ERROR, - data); - } - - if (cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.BAD_MESSAGE_LENGTH, - parseFlags.getLength()); - } - - BgpValueType bgpLSAttrib = null; - LinkedList linkStateAttribList; - linkStateAttribList = new LinkedList(); - ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); - while (tempCb.readableBytes() > 0) { - short tlvCodePoint = tempCb.readShort(); - switch (tlvCodePoint) { - - /********* 7 NODE ATTRIBUTES ********/ - case ATTR_NODE_MT_TOPOLOGY_ID: /* 263 Multi-Topology Identifier*/ - bgpLSAttrib = BgpAttrNodeMultiTopologyId.read(tempCb); - break; - - case ATTR_NODE_FLAG_BITS: /*Node flag bit TLV*/ - bgpLSAttrib = BgpAttrNodeFlagBitTlv.read(tempCb); - break; - - case ATTR_NODE_OPAQUE_NODE: /*Opaque Node Attribute*/ - bgpLSAttrib = BgpAttrOpaqueNode.read(tempCb); - break; - - case ATTR_NODE_NAME: /*Node Name*/ - bgpLSAttrib = BgpAttrNodeName.read(tempCb); - break; - - case ATTR_NODE_ISIS_AREA_ID: /*IS-IS Area Identifier TLV*/ - bgpLSAttrib = BgpAttrNodeIsIsAreaId.read(tempCb); - break; - - case ATTR_NODE_IPV4_LOCAL_ROUTER_ID: /*IPv4 Router-ID of Local Node*/ - bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) ATTR_NODE_IPV4_LOCAL_ROUTER_ID); - break; - - case ATTR_NODE_IPV6_LOCAL_ROUTER_ID: /*IPv6 Router-ID of Local Node*/ - bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) ATTR_NODE_IPV6_LOCAL_ROUTER_ID); - break; - - /********* 15 LINK ATTRIBUTES ********/ - - case ATTR_LINK_IPV4_REMOTE_ROUTER_ID: /*IPv4 Router-ID of Remote Node*/ - bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) 1030); - break; - - case ATTR_LINK_IPV6_REMOTE_ROUTER_ID: /*IPv6 Router-ID of Remote Node*/ - bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) 1031); - break; - - case ATTR_LINK_ADMINISTRATIVE_GRPS: /*ISIS Administrative group STLV 3*/ - bgpLSAttrib = BgpLinkAttrIsIsAdminstGrp.read(tempCb); - break; - - case ATTR_LINK_MAX_BANDWIDTH: /*Maximum link bandwidth*/ - bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb, - (short) 1089); - break; - - case ATTR_LINK_MAX_RES_BANDWIDTH: /* Maximum Reservable link bandwidth */ - bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb, - (short) 1090); - break; - - case ATTR_LINK_UNRES_BANDWIDTH: /* UnReserved link bandwidth */ - bgpLSAttrib = BgpLinkAttrUnRsrvdLinkBandwidth - .read(tempCb, (short) 1091); - break; - - case ATTR_LINK_TE_DEFAULT_METRIC: /* TE Default Metric */ - bgpLSAttrib = BgpLinkAttrTeDefaultMetric.read(tempCb); - break; - - case ATTR_LINK_PROTECTION_TYPE:/* Link Protection type */ - bgpLSAttrib = BgpLinkAttrProtectionType.read(tempCb); - break; - - case ATTR_LINK_MPLS_PROTOCOL_MASK: /* MPLS Protocol Mask */ - bgpLSAttrib = BgpLinkAttrMplsProtocolMask.read(tempCb); // 2 - break; - - case ATTR_LINK_IGP_METRIC: /* IGP Metric */ - bgpLSAttrib = BgpLinkAttrIgpMetric.read(tempCb); // 2 - break; - - case ATTR_LINK_SHR_RISK_GRP: /* Shared Risk Link Group */ - bgpLSAttrib = BgpLinkAttrSrlg.read(tempCb); // 3 - break; - - case ATTR_LINK_OPAQUE_ATTR: /* Opaque link attribute */ - bgpLSAttrib = BgpLinkAttrOpaqLnkAttrib.read(tempCb); - break; - - case ATTR_LINK_NAME_ATTR: /* Link Name attribute */ - bgpLSAttrib = BgpLinkAttrName.read(tempCb); - break; - - /********* 6 PREFIX ATTRIBUTES ********/ - - case ATTR_PREFIX_IGP_FLAG: /* IGP Flags */ - bgpLSAttrib = BgpPrefixAttrIgpFlags.read(tempCb); - break; - - case ATTR_PREFIX_ROUTE_TAG: /* Route Tag */ - bgpLSAttrib = BgpPrefixAttrRouteTag.read(tempCb); - break; - - case ATTR_PREFIX_EXTENDED_TAG: /* Extended Tag */ - bgpLSAttrib = BgpPrefixAttrExtRouteTag.read(tempCb); - break; - - case ATTR_PREFIX_METRIC: /* Prefix Metric */ - bgpLSAttrib = BgpPrefixAttrMetric.read(tempCb); - break; - - case ATTR_PREFIX_OSPF_FWD_ADDR: /* OSPF Forwarding Address */ - bgpLSAttrib = BgpPrefixAttrOspfFwdAddr.read(tempCb); - break; - - case ATTR_PREFIX_OPAQUE_ATTR: /* Opaque Prefix Attribute */ - bgpLSAttrib = BgpPrefixAttrOpaqueData.read(tempCb); - break; - - default: - throw new BgpParseException( - "The Bgp-LS Attribute is not supported : " - + tlvCodePoint); - } - - linkStateAttribList.add(bgpLSAttrib); - } - return new LinkStateAttributes(linkStateAttribList); - } - - @Override - public short getType() { - return LINKSTATE_ATTRIB_TYPE; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("linkStateAttribList", linkStateAttribList).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java deleted file mode 100644 index 36793c18..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; - -/** - * Provides implementation of LocalPref BGP Path Attribute. - */ -public class LocalPref implements BgpValueType { - public static final byte LOCAL_PREF_TYPE = 5; - public static final byte LOCAL_PREF_MAX_LEN = 4; - - private int localPref; - - /** - * Constructor to initialize LocalPref. - * - * @param localPref local preference - */ - public LocalPref(int localPref) { - this.localPref = localPref; - } - - /** - * Returns local preference value. - * - * @return local preference value - */ - public int localPref() { - return this.localPref; - } - - /** - * Reads the channel buffer and returns object of LocalPref. - * - * @param cb channelBuffer - * @return object of LocalPref - * @throws BgpParseException while parsing localPref attribute - */ - public static LocalPref read(ChannelBuffer cb) throws BgpParseException { - int localPref; - ChannelBuffer tempCb = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - if ((parseFlags.getLength() > LOCAL_PREF_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - parseFlags.getLength()); - } - - int len = parseFlags.isShort() ? parseFlags.getLength() + - Constants.TYPE_AND_LEN_AS_SHORT : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if (parseFlags.getFirstBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - localPref = cb.readInt(); - return new LocalPref(localPref); - } - - @Override - public short getType() { - return LOCAL_PREF_TYPE; - } - - @Override - public int hashCode() { - return Objects.hash(localPref); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof LocalPref) { - LocalPref other = (LocalPref) obj; - return Objects.equals(localPref, other.localPref); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("localPref", localPref) - .toString(); - } - - @Override - public int write(ChannelBuffer cb) { - //Not to implement as of now - return 0; - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java deleted file mode 100644 index 7f1ab53f..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of Med BGP Path Attribute. - */ -public class Med implements BgpValueType { - public static final byte MED_TYPE = 4; - public static final byte MED_MAX_LEN = 4; - - private int med; - - /** - * Constructor to initialize med. - * - * @param med MULTI_EXIT_DISC value - */ - public Med(int med) { - this.med = med; - } - - /** - * Returns Med value. - * - * @return Med value - */ - public int med() { - return this.med; - } - - /** - * Reads the channel buffer and returns object of Med. - * - * @param cb ChannelBuffer - * @return object of Med - * @throws BgpParseException while parsing Med path attribute - */ - public static Med read(ChannelBuffer cb) throws BgpParseException { - int med; - ChannelBuffer tempCb = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - - if ((parseFlags.getLength() > MED_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - parseFlags.getLength()); - } - int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags - .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - med = cb.readInt(); - return new Med(med); - } - - @Override - public short getType() { - return MED_TYPE; - } - - @Override - public int hashCode() { - return Objects.hash(med); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof Med) { - Med other = (Med) obj; - return Objects.equals(med, other.med); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("med", med) - .toString(); - } - - @Override - public int write(ChannelBuffer cb) { - //Not to implement as of now - return 0; - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java deleted file mode 100644 index 689f30ea..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import java.net.InetAddress; -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/* - * Provides Implementation of MpReach Nlri BGP Path Attribute. - */ -public class MpReachNlri implements BgpValueType { - - private static final Logger log = LoggerFactory.getLogger(MpReachNlri.class); - public static final byte MPREACHNLRI_TYPE = 14; - public static final byte LINK_NLRITYPE = 2; - - private boolean isMpReachNlri = false; - private final List mpReachNlri; - private final int length; - private final short afi; - private final byte safi; - private final Ip4Address ipNextHop; - - /** - * Constructor to initialize parameters. - * - * @param mpReachNlri MpReach Nlri attribute - * @param afi address family identifier - * @param safi subsequent address family identifier - * @param ipNextHop nexthop IpAddress - * @param length of MpReachNlri - */ - public MpReachNlri(List mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) { - this.mpReachNlri = mpReachNlri; - this.isMpReachNlri = true; - this.ipNextHop = ipNextHop; - this.afi = afi; - this.safi = safi; - this.length = length; - } - - /** - * Returns whether MpReachNlri is present. - * - * @return whether MpReachNlri is present - */ - public boolean isMpReachNlriSet() { - return this.isMpReachNlri; - } - - /** - * Returns list of MpReach Nlri. - * - * @return list of MpReach Nlri - */ - public List mpReachNlri() { - return this.mpReachNlri; - } - - /** - * Returns length of MpReachNlri. - * - * @return length of MpReachNlri - */ - public int mpReachNlriLen() { - return this.length; - } - - /** - * Reads from ChannelBuffer and parses MpReachNlri. - * - * @param cb channelBuffer - * @return object of MpReachNlri - * @throws BgpParseException while parsing MpReachNlri - */ - public static MpReachNlri read(ChannelBuffer cb) throws BgpParseException { - ChannelBuffer tempBuf = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : - parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempBuf.readBytes(len); - - if (cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - parseFlags.getLength()); - } - if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - BgpLSNlri bgpLSNlri = null; - List mpReachNlri = new LinkedList<>(); - ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); - short afi = 0; - byte safi = 0; - Ip4Address ipNextHop = null; - while (tempCb.readableBytes() > 0) { - afi = tempCb.readShort(); - safi = tempCb.readByte(); - - //Supporting for AFI 16388 / SAFI 71 and VPN AFI 16388 / SAFI 128 - if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) || (afi == Constants.AFI_VALUE) - && (safi == Constants.VPN_SAFI_VALUE)) { - byte nextHopLen = tempCb.readByte(); - InetAddress ipAddress = Validation.toInetAddress(nextHopLen, cb); - if (ipAddress.isMulticastAddress()) { - throw new BgpParseException("Multicast not supported"); - } - ipNextHop = Ip4Address.valueOf(ipAddress); - byte reserved = tempCb.readByte(); - - while (tempCb.readableBytes() > 0) { - short nlriType = tempCb.readShort(); - short totNlriLen = tempCb.readShort(); - if (tempCb.readableBytes() < totNlriLen) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen); - } - tempBuf = tempCb.readBytes(totNlriLen); - switch (nlriType) { - case BgpNodeLSNlriVer4.NODE_NLRITYPE: - bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi); - break; - case BgpLinkLsNlriVer4.LINK_NLRITYPE: - bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi); - break; - case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE: - bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi); - break; - default: - log.debug("nlriType not supported" + nlriType); - } - mpReachNlri.add(bgpLSNlri); - } - } else { - throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi); - } - } - return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength()); - } - - @Override - public short getType() { - return MPREACHNLRI_TYPE; - } - - /** - * Returns AFI. - * - * @return AFI - */ - public short afi() { - return this.afi; - } - - /** - * Returns Nexthop IpAddress. - * - * @return Nexthop IpAddress - */ - public Ip4Address nexthop4() { - return this.ipNextHop; - } - - /** - * Returns SAFI. - * - * @return SAFI - */ - public byte safi() { - return this.safi; - } - - @Override - public int write(ChannelBuffer cb) { - //Not to be Implemented as of now - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("mpReachNlri", mpReachNlri) - .add("afi", afi) - .add("safi", safi) - .add("ipNextHop", ipNextHop) - .add("length", length) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java deleted file mode 100644 index f354b3ea..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of MpUnReach Nlri BGP Path Attribute. - */ -public class MpUnReachNlri implements BgpValueType { - - private static final Logger log = LoggerFactory.getLogger(MpUnReachNlri.class); - public static final byte MPUNREACHNLRI_TYPE = 15; - public static final byte LINK_NLRITYPE = 2; - - private boolean isMpUnReachNlri = false; - private final short afi; - private final byte safi; - private final List mpUnReachNlri; - private final int length; - - /** - * Constructor to initialize parameters. - * - * @param mpUnReachNlri MpUnReach Nlri attribute - * @param afi address family identifier - * @param safi subsequent address family identifier - * @param length of MpUnReachNlri - */ - public MpUnReachNlri(List mpUnReachNlri, short afi, byte safi, - int length) { - this.mpUnReachNlri = mpUnReachNlri; - this.isMpUnReachNlri = true; - this.afi = afi; - this.safi = safi; - this.length = length; - } - - /** - * Reads from ChannelBuffer and parses MpUnReachNlri. - * - * @param cb ChannelBuffer - * @return object of MpUnReachNlri - * @throws BgpParseException while parsing MpUnReachNlri - */ - public static MpUnReachNlri read(ChannelBuffer cb) throws BgpParseException { - ChannelBuffer tempBuf = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT - : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempBuf.readBytes(len); - - if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() - && parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - if (cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, parseFlags.getLength()); - } - - LinkedList mpUnReachNlri = new LinkedList<>(); - BgpLSNlri bgpLSNlri = null; - short afi = 0; - byte safi = 0; - ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); - while (tempCb.readableBytes() > 0) { - afi = tempCb.readShort(); - safi = tempCb.readByte(); - - //Supporting only for AFI 16388 / SAFI 71 - if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) - || (afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { - while (tempCb.readableBytes() > 0) { - short nlriType = tempCb.readShort(); - short totNlriLen = tempCb.readShort(); - if (tempCb.readableBytes() < totNlriLen) { - Validation.validateLen( - BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen); - } - tempBuf = tempCb.readBytes(totNlriLen); - switch (nlriType) { - case BgpNodeLSNlriVer4.NODE_NLRITYPE: - bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi); - break; - case BgpLinkLsNlriVer4.LINK_NLRITYPE: - bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi); - break; - case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE: - bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, - safi); - break; - default: - log.debug("nlriType not supported" + nlriType); - } - mpUnReachNlri.add(bgpLSNlri); - } - } else { - //TODO: check with the values got from capability - throw new BgpParseException("Not Supporting afi " + afi - + "safi " + safi); - } - } - return new MpUnReachNlri(mpUnReachNlri, afi, safi, - parseFlags.getLength()); - } - - @Override - public short getType() { - return MPUNREACHNLRI_TYPE; - } - - /** - * Returns SAFI. - * - * @return SAFI - */ - public byte safi() { - return this.safi; - } - - /** - * Returns AFI. - * - * @return AFI - */ - public short afi() { - return this.afi; - } - - /** - * Returns list of MpUnReach Nlri. - * - * @return list of MpUnReach Nlri - */ - public List mpUnReachNlri() { - return this.mpUnReachNlri; - } - - /** - * Returns whether MpReachNlri is present. - * - * @return whether MpReachNlri is present - */ - public boolean isMpUnReachNlriSet() { - return this.isMpUnReachNlri; - } - - /** - * Returns length of MpUnReach. - * - * @return length of MpUnReach - */ - public int mpUnReachNlriLen() { - return this.length; - } - - @Override - public int write(ChannelBuffer cb) { - //Not to be Implemented as of now - return 0; - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("mpReachNlri", mpUnReachNlri) - .add("afi", afi) - .add("safi", safi) - .add("length", length) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java deleted file mode 100644 index 7082483e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; -import org.jboss.netty.buffer.ChannelBuffer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Provides MultiProtocolExtnCapabilityTlv. - */ -public class MultiProtocolExtnCapabilityTlv implements BgpValueType { - - /* - 0 7 15 23 31 - +-------+-------+-------+-------+ - | AFI | Res | SAFI | - +-------+-------+-------+-------+ - - Multiprotocol Extensions CAPABILITY TLV format - REFERENCE : RFC 4760 - */ - protected static final Logger log = LoggerFactory - .getLogger(MultiProtocolExtnCapabilityTlv.class); - - public static final byte TYPE = 1; - public static final byte LENGTH = 4; - - private final short afi; - private final byte res; - private final byte safi; - - /** - * Constructor to initialize variables. - * @param afi Address Family Identifiers - * @param res reserved field - * @param safi Subsequent Address Family Identifier - */ - public MultiProtocolExtnCapabilityTlv(short afi, byte res, byte safi) { - this.afi = afi; - this.res = res; - this.safi = safi; - } - - /** - * Returns object of MultiProtocolExtnCapabilityTlv. - * @param afi Address Family Identifiers - * @param res reserved field - * @param safi Subsequent Address Family Identifier - * @return object of MultiProtocolExtnCapabilityTlv - */ - public static MultiProtocolExtnCapabilityTlv of(short afi, byte res, - byte safi) { - return new MultiProtocolExtnCapabilityTlv(afi, res, safi); - } - - /** - * Returns afi Address Family Identifiers value. - * @return afi Address Family Identifiers value - */ - public short getAFI() { - return afi; - } - - /** - * Returns res reserved field value. - * @return res reserved field value - */ - public byte getRes() { - return res; - } - - /** - * Returns safi Subsequent Address Family Identifier value. - * @return safi Subsequent Address Family Identifier value - */ - public byte getSAFI() { - return safi; - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int hashCode() { - return Objects.hash(afi, res, safi); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof MultiProtocolExtnCapabilityTlv) { - MultiProtocolExtnCapabilityTlv other = (MultiProtocolExtnCapabilityTlv) obj; - return Objects.equals(this.afi, other.afi) - && Objects.equals(this.res, other.res) - && Objects.equals(this.safi, other.safi); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - int iLenStartIndex = cb.writerIndex(); - cb.writeByte(TYPE); - cb.writeByte(LENGTH); - - // write afi - cb.writeShort(afi); - - // write res - cb.writeByte(res); - - // write safi - cb.writeByte(safi); - - return cb.writerIndex() - iLenStartIndex; - } - - /** - * Reads from channel buffer and returns object of MultiprotocolCapabilityTlv. - * @param cb of type channel buffer - * @return object of MultiProtocolExtnCapabilityTlv - */ - public static BgpValueType read(ChannelBuffer cb) { - short afi = cb.readShort(); - byte res = cb.readByte(); - byte safi = cb.readByte(); - return new MultiProtocolExtnCapabilityTlv(afi, res, safi); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("AFI", afi) - .add("Reserved", res) - .add("SAFI", safi).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java deleted file mode 100644 index 806efe52..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.net.InetAddress; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; - -/** - * Implementation of NextHop BGP Path Attribute. - */ -public class NextHop implements BgpValueType { - public static final byte NEXTHOP_TYPE = 3; - - private boolean isNextHop = false; - private Ip4Address nextHop; - - /** - * Constructor to initialize parameters. - * - * @param nextHop nextHop address - */ - public NextHop(Ip4Address nextHop) { - this.nextHop = Preconditions.checkNotNull(nextHop); - this.isNextHop = true; - } - - /** - * Returns whether next hop is present. - * - * @return whether next hop is present - */ - public boolean isNextHopSet() { - return this.isNextHop; - } - - /** - * Reads from ChannelBuffer and parses NextHop. - * - * @param cb ChannelBuffer - * @return object of NextHop - * @throws BgpParseException while parsing nexthop attribute - */ - public static NextHop read(ChannelBuffer cb) throws BgpParseException { - Ip4Address nextHop; - ChannelBuffer tempCb = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - - if (cb.readableBytes() < parseFlags.getLength()) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - parseFlags.getLength()); - } - int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags - .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - InetAddress ipAddress = Validation.toInetAddress(parseFlags.getLength(), cb); - if (ipAddress.isMulticastAddress()) { - throw new BgpParseException("Multicast address is not supported"); - } - - nextHop = Ip4Address.valueOf(ipAddress); - return new NextHop(nextHop); - } - - /** - * Return nexthop address. - * - * @return nexthop address - */ - public Ip4Address nextHop() { - return nextHop; - } - - @Override - public short getType() { - return NEXTHOP_TYPE; - } - - @Override - public int write(ChannelBuffer cb) { - //Not required to be implemented now - return 0; - } - - @Override - public int hashCode() { - return Objects.hash(nextHop); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NextHop) { - NextHop other = (NextHop) obj; - return Objects.equals(nextHop, other.nextHop); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("nextHop", nextHop) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java deleted file mode 100644 index d281a4ef..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.protocol.IGPRouterID; - -import com.google.common.base.MoreObjects; - -/** - * Provides implementation of OSPFNonPseudonode Tlv. - */ -public class OSPFNonPseudonode implements IGPRouterID, BgpValueType { - public static final short TYPE = 515; - public static final short LENGTH = 4; - - private final int routerID; - - /** - * Constructor to initialize routerID. - * - * @param routerID routerID - */ - public OSPFNonPseudonode(int routerID) { - this.routerID = routerID; - } - - /** - * Returns object of this class with specified routerID. - * - * @param routerID routerID - * @return object of OSPFNonPseudonode - */ - public static OSPFNonPseudonode of(final int routerID) { - return new OSPFNonPseudonode(routerID); - } - - /** - * Returns RouterID. - * - * @return RouterID - */ - public int getrouterID() { - return this.routerID; - } - - @Override - public int hashCode() { - return Objects.hash(routerID); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof OSPFNonPseudonode) { - OSPFNonPseudonode other = (OSPFNonPseudonode) obj; - return Objects.equals(routerID, other.routerID); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeInt(routerID); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of OSPFNonPseudonode. - * - * @param cb ChannelBuffer - * @return object of OSPFNonPseudonode - */ - public static OSPFNonPseudonode read(ChannelBuffer cb) { - return OSPFNonPseudonode.of(cb.readInt()); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Integer) (this.routerID)).compareTo((Integer) (((OSPFNonPseudonode) o).routerID)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("RouterID", routerID) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java deleted file mode 100644 index 0d17651a..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onosproject.bgpio.protocol.IGPRouterID; - -import com.google.common.base.MoreObjects; - -/** - * Provides implementation of OSPFPseudonode Tlv. - */ -public class OSPFPseudonode implements IGPRouterID, BgpValueType { - public static final short TYPE = 515; - public static final short LENGTH = 8; - - private final int routerID; - private final Ip4Address drInterface; - - /** - * Constructor to initialize parameters. - * - * @param routerID routerID - * @param drInterface IPv4 address of the DR's interface - */ - public OSPFPseudonode(int routerID, Ip4Address drInterface) { - this.routerID = routerID; - this.drInterface = drInterface; - } - - /** - * Returns object of this class with specified values. - * - * @param routerID routerID - * @param drInterface IPv4 address of the DR's interface - * @return object of OSPFPseudonode - */ - public static OSPFPseudonode of(final int routerID, final Ip4Address drInterface) { - return new OSPFPseudonode(routerID, drInterface); - } - - /** - * Returns RouterID. - * - * @return RouterID - */ - public int getrouterID() { - return this.routerID; - } - - @Override - public int hashCode() { - return Objects.hash(routerID, drInterface); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof OSPFPseudonode) { - OSPFPseudonode other = (OSPFPseudonode) obj; - return Objects.equals(routerID, other.routerID) && Objects.equals(drInterface, other.drInterface); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeInt(routerID); - c.writeInt(drInterface.toInt()); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads the channel buffer and returns object of OSPFPseudonode. - * - * @param cb ChannelBuffer - * @return object of OSPFPseudonode - */ - public static OSPFPseudonode read(ChannelBuffer cb) { - int routerID = cb.readInt(); - Ip4Address drInterface = Ip4Address.valueOf(cb.readInt()); - return OSPFPseudonode.of(routerID, drInterface); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - int result = ((Integer) (this.routerID)).compareTo((Integer) (((OSPFPseudonode) o).routerID)); - if (result != 0) { - return this.drInterface.compareTo(((OSPFPseudonode) o).drInterface); - } - return result; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("RouterID", routerID) - .add("DRInterface", drInterface) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java deleted file mode 100644 index be321c95..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; - -import com.google.common.base.MoreObjects; - -/** - * Provides OSPF Route Type Tlv which contains route type. - */ -public class OSPFRouteTypeTlv implements BgpValueType { - - /* Reference :draft-ietf-idr-ls-distribution-11 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Route Type | - +-+-+-+-+-+-+-+-+ - - Figure : OSPF Route Type TLV Format - */ - - public static final short TYPE = 264; - public static final short LENGTH = 1; - public static final int INTRA_AREA_TYPE = 1; - public static final short INTER_AREA_TYPE = 2; - public static final short EXTERNAL_TYPE_1 = 3; - public static final short EXTERNAL_TYPE_2 = 4; - public static final short NSSA_TYPE_1 = 5; - public static final short NSSA_TYPE_2 = 6; - - private final byte routeType; - - /** - * Enum for Route Type. - */ - public enum RouteType { - Intra_Area(1), Inter_Area(2), External_1(3), External_2(4), NSSA_1(5), NSSA_2(6); - int value; - RouteType(int val) { - value = val; - } - public byte getType() { - return (byte) value; - } - } - - /** - * Constructor to initialize routeType. - * - * @param routeType Route type - */ - public OSPFRouteTypeTlv(byte routeType) { - this.routeType = routeType; - } - - /** - * Returns object of this class with specified routeType. - * - * @param routeType Route type - * @return object of OSPFRouteTypeTlv - */ - public static OSPFRouteTypeTlv of(final byte routeType) { - return new OSPFRouteTypeTlv(routeType); - } - - /** - * Returns RouteType. - * - * @return RouteType - * @throws BgpParseException if routeType is not matched - */ - public RouteType getValue() throws BgpParseException { - switch (routeType) { - case INTRA_AREA_TYPE: - return RouteType.Intra_Area; - case INTER_AREA_TYPE: - return RouteType.Inter_Area; - case EXTERNAL_TYPE_1: - return RouteType.External_1; - case EXTERNAL_TYPE_2: - return RouteType.External_2; - case NSSA_TYPE_1: - return RouteType.NSSA_1; - case NSSA_TYPE_2: - return RouteType.NSSA_2; - default: - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); - } - } - - @Override - public int hashCode() { - return Objects.hash(routeType); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof OSPFRouteTypeTlv) { - OSPFRouteTypeTlv other = (OSPFRouteTypeTlv) obj; - return Objects.equals(routeType, other.routeType); - } - return false; - } - - @Override - public int write(ChannelBuffer c) { - int iLenStartIndex = c.writerIndex(); - c.writeShort(TYPE); - c.writeShort(LENGTH); - c.writeByte(routeType); - return c.writerIndex() - iLenStartIndex; - } - - /** - * Reads from ChannelBuffer and parses OSPFRouteTypeTlv. - * - * @param cb channelBuffer - * @return object of OSPFRouteTypeTlv - */ - public static OSPFRouteTypeTlv read(ChannelBuffer cb) { - return OSPFRouteTypeTlv.of(cb.readByte()); - } - - @Override - public short getType() { - return TYPE; - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - return ((Byte) (this.routeType)).compareTo((Byte) (((OSPFRouteTypeTlv) o).routeType)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("Type", TYPE) - .add("Length", LENGTH) - .add("Value", routeType) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java deleted file mode 100644 index d642d83c..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.util.Constants; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; - -/** - * Provides Implementation of mandatory BGP Origin path attribute. - */ -public class Origin implements BgpValueType { - - /** - * Enum to provide ORIGIN types. - */ - public enum ORIGINTYPE { - IGP(0), EGP(1), INCOMPLETE(2); - int value; - /** - * Assign val with the value as the ORIGIN type. - * - * @param val ORIGIN type - */ - ORIGINTYPE(int val) { - value = val; - } - - /** - * Returns value of ORIGIN type. - * - * @return ORIGIN type - */ - public byte getType() { - return (byte) value; - } - } - - public static final byte ORIGIN_TYPE = 1; - public static final byte ORIGIN_VALUE_LEN = 1; - - private boolean isOrigin = false; - private byte origin; - - /** - * Constructor to initialize parameters. - * - * @param origin origin value - */ - public Origin(byte origin) { - this.origin = origin; - this.isOrigin = true; - } - - /** - * Returns true if origin attribute is present otherwise false. - * - * @return whether origin is present or not - */ - public boolean isOriginSet() { - return this.isOrigin; - } - - /** - * Returns type of Origin in Enum values. - * - * @return type of Origin in Enum values - */ - public ORIGINTYPE origin() { - if (this.origin == 0) { - return ORIGINTYPE.IGP; - } else if (this.origin == 1) { - return ORIGINTYPE.EGP; - } else { - return ORIGINTYPE.INCOMPLETE; - } - } - - /** - * Reads from ChannelBuffer and parses Origin. - * - * @param cb ChannelBuffer - * @return object of Origin - * @throws BgpParseException while parsing Origin path attribute - */ - public static Origin read(ChannelBuffer cb) throws BgpParseException { - ChannelBuffer tempCb = cb.copy(); - Validation parseFlags = Validation.parseAttributeHeader(cb); - - int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags - .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; - ChannelBuffer data = tempCb.readBytes(len); - if ((parseFlags.getLength() > ORIGIN_VALUE_LEN) || (cb.readableBytes() < parseFlags.getLength())) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - parseFlags.getLength()); - } - if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); - } - - byte originValue; - originValue = cb.readByte(); - if ((originValue != ORIGINTYPE.INCOMPLETE.value) && (originValue != ORIGINTYPE.IGP.value) && - (originValue != ORIGINTYPE.EGP.value)) { - throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.INVALID_ORIGIN_ATTRIBUTE, data); - } - return new Origin(originValue); - } - - @Override - public short getType() { - return ORIGIN_TYPE; - } - - @Override - public int write(ChannelBuffer cb) { - //Not required to Implement as of now - return 0; - } - - @Override - public int hashCode() { - return Objects.hash(origin); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof Origin) { - Origin other = (Origin) obj; - return Objects.equals(origin, other.origin); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("origin", origin) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java deleted file mode 100644 index 37632ad8..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.types; - -import org.jboss.netty.buffer.ChannelBuffer; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of RouteDistinguisher. - */ -public class RouteDistinguisher implements Comparable { - - private long routeDistinguisher; - - /** - * Resets fields. - */ - public RouteDistinguisher() { - this.routeDistinguisher = 0; - } - - /** - * Constructor to initialize parameters. - * - * @param routeDistinguisher route distinguisher - */ - public RouteDistinguisher(long routeDistinguisher) { - this.routeDistinguisher = routeDistinguisher; - } - - /** - * Reads route distinguisher from channelBuffer. - * - * @param cb channelBuffer - * @return object of RouteDistinguisher - */ - public static RouteDistinguisher read(ChannelBuffer cb) { - return new RouteDistinguisher(cb.readLong()); - } - - /** - * Returns route distinguisher. - * - * @return route distinguisher - */ - public long getRouteDistinguisher() { - return this.routeDistinguisher; - } - - @Override - public int compareTo(RouteDistinguisher rd) { - if (this.equals(rd)) { - return 0; - } - return ((Long) (this.getRouteDistinguisher())).compareTo((Long) (rd.getRouteDistinguisher())); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("routeDistinguisher", routeDistinguisher) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java deleted file mode 100755 index e0fef7c8..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute node flag. - */ -public final class BgpAttrNodeFlagBitTlv implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrNodeFlagBitTlv.class); - - public static final int ATTRNODE_FLAGBIT = 1024; - - /* Node flag bit TLV */ - private final boolean bOverloadBit; - private final boolean bAttachedBit; - private final boolean bExternalBit; - private final boolean bAbrBit; - - public static final byte FIRST_BIT = (byte) 0x80; - public static final byte SECOND_BIT = 0x40; - public static final byte THIRD_BIT = 0x20; - public static final byte FOURTH_BIT = 0x01; - - /** - * Constructor to initialize parameters. - * - * @param bOverloadBit Overload bit - * @param bAttachedBit Attached bit - * @param bExternalBit External bit - * @param bAbrBit ABR Bit - */ - private BgpAttrNodeFlagBitTlv(boolean bOverloadBit, boolean bAttachedBit, - boolean bExternalBit, boolean bAbrBit) { - this.bOverloadBit = bOverloadBit; - this.bAttachedBit = bAttachedBit; - this.bExternalBit = bExternalBit; - this.bAbrBit = bAbrBit; - } - - /** - * Returns object of this class with specified values. - * - * @param bOverloadBit Overload bit - * @param bAttachedBit Attached bit - * @param bExternalBit External bit - * @param bAbrBit ABR Bit - * @return object of BgpAttrNodeFlagBitTlv - */ - public static BgpAttrNodeFlagBitTlv of(final boolean bOverloadBit, - final boolean bAttachedBit, - final boolean bExternalBit, - final boolean bAbrBit) { - return new BgpAttrNodeFlagBitTlv(bOverloadBit, bAttachedBit, - bExternalBit, bAbrBit); - } - - /** - * Reads the Node Flag Bits. - * - * @param cb ChannelBuffer - * @return attribute node flag bit tlv - * @throws BgpParseException while parsing BgpAttrNodeFlagBitTlv - */ - public static BgpAttrNodeFlagBitTlv read(ChannelBuffer cb) - throws BgpParseException { - boolean bOverloadBit = false; - boolean bAttachedBit = false; - boolean bExternalBit = false; - boolean bAbrBit = false; - - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != 1) || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - byte nodeFlagBits = cb.readByte(); - - bOverloadBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT); - bAttachedBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT); - bExternalBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT); - bAbrBit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT); - - return BgpAttrNodeFlagBitTlv.of(bOverloadBit, bAttachedBit, - bExternalBit, bAbrBit); - } - - /** - * Returns Overload Bit. - * - * @return Overload Bit - */ - public boolean overLoadBit() { - return bOverloadBit; - } - - /** - * Returns Attached Bit. - * - * @return Attached Bit - */ - public boolean attachedBit() { - return bAttachedBit; - } - - /** - * Returns External Bit. - * - * @return External Bit - */ - public boolean externalBit() { - return bExternalBit; - } - - /** - * Returns ABR Bit. - * - * @return ABR Bit - */ - public boolean abrBit() { - return bAbrBit; - } - - @Override - public short getType() { - return ATTRNODE_FLAGBIT; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public int hashCode() { - return Objects.hash(bOverloadBit, bAttachedBit, bExternalBit, bAbrBit); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrNodeFlagBitTlv) { - BgpAttrNodeFlagBitTlv other = (BgpAttrNodeFlagBitTlv) obj; - return Objects.equals(bOverloadBit, other.bOverloadBit) - && Objects.equals(bAttachedBit, other.bAttachedBit) - && Objects.equals(bExternalBit, other.bExternalBit) - && Objects.equals(bAbrBit, other.bAbrBit); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("bOverloadBit", bOverloadBit) - .add("bAttachedBit", bAttachedBit) - .add("bExternalBit", bExternalBit).add("bAbrBit", bAbrBit) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java deleted file mode 100644 index 0435a65f..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute ISIS Area Identifier. - */ -public class BgpAttrNodeIsIsAreaId implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrNodeIsIsAreaId.class); - - public static final int ATTRNODE_ISISAREAID = 1027; - - /* IS-IS Area Identifier TLV */ - private byte[] isisAreaId; - - /** - * Constructor to initialize value. - * - * @param isisAreaId ISIS area Identifier - */ - public BgpAttrNodeIsIsAreaId(byte[] isisAreaId) { - this.isisAreaId = Arrays.copyOf(isisAreaId, isisAreaId.length); - } - - /** - * Returns object of this class with specified values. - * - * @param isisAreaId ISIS area Identifier - * @return object of BgpAttrNodeIsIsAreaId - */ - public static BgpAttrNodeIsIsAreaId of(final byte[] isisAreaId) { - return new BgpAttrNodeIsIsAreaId(isisAreaId); - } - - /** - * Reads the IS-IS Area Identifier. - * - * @param cb ChannelBuffer - * @return object of BgpAttrNodeIsIsAreaId - * @throws BgpParseException while parsing BgpAttrNodeIsIsAreaId - */ - public static BgpAttrNodeIsIsAreaId read(ChannelBuffer cb) - throws BgpParseException { - byte[] isisAreaId; - - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - isisAreaId = new byte[lsAttrLength]; - cb.readBytes(isisAreaId); - - return BgpAttrNodeIsIsAreaId.of(isisAreaId); - } - - /** - * Returns ISIS area Identifier. - * - * @return Area ID - */ - public byte[] attrNodeIsIsAreaId() { - return isisAreaId; - } - - @Override - public short getType() { - return ATTRNODE_ISISAREAID; - } - - @Override - public int hashCode() { - return Arrays.hashCode(isisAreaId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrNodeIsIsAreaId) { - BgpAttrNodeIsIsAreaId other = (BgpAttrNodeIsIsAreaId) obj; - return Arrays.equals(isisAreaId, other.isisAreaId); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("isisAreaId", isisAreaId).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java deleted file mode 100644 index 31d855db..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * BGP Multi-Topology ID of the LS attribute. - */ -public class BgpAttrNodeMultiTopologyId implements BgpValueType { - - private static final Logger log = LoggerFactory - .getLogger(BgpAttrNodeMultiTopologyId.class); - - public static final int ATTRNODE_MULTITOPOLOGY = 263; - - /* Opaque Node Attribute */ - private List multiTopologyId = new ArrayList(); - - /** - * Constructor to initialize the Node attribute multi-topology ID. - * - * @param multiTopologyId multi-topology ID - */ - public BgpAttrNodeMultiTopologyId(List multiTopologyId) { - this.multiTopologyId = multiTopologyId; - } - - /** - * Returns object of this class with specified values. - * - * @param multiTopologyId Prefix Metric - * @return object of BgpAttrNodeMultiTopologyId - */ - public static BgpAttrNodeMultiTopologyId of(ArrayList multiTopologyId) { - return new BgpAttrNodeMultiTopologyId(multiTopologyId); - } - - /** - * Reads the Multi-topology ID of Node attribute. - * - * @param cb ChannelBuffer - * @return Constructor of BgpAttrNodeMultiTopologyId - * @throws BgpParseException while parsing BgpAttrNodeMultiTopologyId - */ - public static BgpAttrNodeMultiTopologyId read(ChannelBuffer cb) - throws BgpParseException { - ArrayList multiTopologyId = new ArrayList(); - short tempMultiTopologyId; - short lsAttrLength = cb.readShort(); - int len = lsAttrLength / 2; // Length is 2*n and n is the number of MT-IDs - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - for (int i = 0; i < len; i++) { - tempMultiTopologyId = cb.readShort(); - multiTopologyId.add(new Short(tempMultiTopologyId)); - } - - return new BgpAttrNodeMultiTopologyId(multiTopologyId); - } - - /** - * to get the multi-topology ID. - * - * @return multitopology ID - */ - public List attrMultiTopologyId() { - return multiTopologyId; - } - - @Override - public short getType() { - return ATTRNODE_MULTITOPOLOGY; - } - - @Override - public int hashCode() { - return Objects.hash(multiTopologyId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrNodeMultiTopologyId) { - BgpAttrNodeMultiTopologyId other = (BgpAttrNodeMultiTopologyId) obj; - return Objects.equals(multiTopologyId, other.multiTopologyId); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("multiTopologyId", multiTopologyId) - .toString(); - } - - @Override - public int compareTo(Object o) { - if (this.equals(o)) { - return 0; - } - int countOtherSubTlv = ((BgpAttrNodeMultiTopologyId) o).multiTopologyId.size(); - int countObjSubTlv = multiTopologyId.size(); - if (countOtherSubTlv != countObjSubTlv) { - if (countOtherSubTlv > countObjSubTlv) { - return 1; - } else { - return -1; - } - } - ListIterator listIterator = multiTopologyId.listIterator(); - ListIterator listIteratorOther = ((BgpAttrNodeMultiTopologyId) o).multiTopologyId.listIterator(); - while (listIterator.hasNext()) { - short id = listIterator.next(); - short id1 = listIteratorOther.next(); - if (((Short) id).compareTo((Short) id1) != 0) { - return ((Short) id).compareTo((Short) id1); - } - } - return 0; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java deleted file mode 100644 index 2e1c7a05..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute node name. - */ -public class BgpAttrNodeName implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrNodeName.class); - - public static final int ATTRNODE_NAME = 1026; - - /* Node Name */ - private byte[] nodeName; - - /** - * Constructor to initialize value. - * - * @param nodeName node name - */ - public BgpAttrNodeName(byte[] nodeName) { - this.nodeName = Arrays.copyOf(nodeName, nodeName.length); - } - - /** - * Returns object of this class with specified values. - * - * @param nodeName node name - * @return object of BgpAttrNodeName - */ - public static BgpAttrNodeName of(final byte[] nodeName) { - return new BgpAttrNodeName(nodeName); - } - - /** - * Reads the LS attribute node name. - * - * @param cb ChannelBuffer - * @return object of BgpAttrNodeName - * @throws BgpParseException while parsing BgpAttrNodeName - */ - public static BgpAttrNodeName read(ChannelBuffer cb) - throws BgpParseException { - byte[] nodeName; - - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - nodeName = new byte[lsAttrLength]; - cb.readBytes(nodeName); - return BgpAttrNodeName.of(nodeName); - } - - /** - * Returns LS attribute node name. - * - * @return node name - */ - public byte[] attrNodeName() { - return nodeName; - } - - @Override - public short getType() { - return ATTRNODE_NAME; - } - - @Override - public int hashCode() { - return Arrays.hashCode(nodeName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrNodeName) { - BgpAttrNodeName other = (BgpAttrNodeName) obj; - return Arrays.equals(nodeName, other.nodeName); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("nodeName", nodeName).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java deleted file mode 100644 index 545755a7..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute opaque node. - */ -public class BgpAttrOpaqueNode implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrOpaqueNode.class); - - public static final int ATTRNODE_OPAQUEDATA = 1025; - - /* Opaque Node Attribute */ - private byte[] opaqueNodeAttribute; - - /** - * Constructor to initialize parameter. - * - * @param opaqueNodeAttribute opaque node attribute - */ - public BgpAttrOpaqueNode(byte[] opaqueNodeAttribute) { - this.opaqueNodeAttribute = Arrays.copyOf(opaqueNodeAttribute, opaqueNodeAttribute.length); - } - - /** - * Returns object of this class with specified values. - * - * @param opaqueNodeAttribute Prefix Metric - * @return object of BgpAttrOpaqueNode - */ - public static BgpAttrOpaqueNode of(byte[] opaqueNodeAttribute) { - return new BgpAttrOpaqueNode(opaqueNodeAttribute); - } - - /** - * Reads the Opaque Node Properties. - * - * @param cb ChannelBuffer - * @return object of BgpAttrOpaqueNode - * @throws BgpParseException while parsing BgpAttrOpaqueNode - */ - public static BgpAttrOpaqueNode read(ChannelBuffer cb) - throws BgpParseException { - - byte[] opaqueNodeAttribute; - - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - opaqueNodeAttribute = new byte[lsAttrLength]; - cb.readBytes(opaqueNodeAttribute); - - return BgpAttrOpaqueNode.of(opaqueNodeAttribute); - } - - /** - * Returns opaque node attribute. - * - * @return LS node attribute value - */ - public byte[] attrOpaqueNode() { - return opaqueNodeAttribute; - } - - @Override - public short getType() { - return ATTRNODE_OPAQUEDATA; - } - - @Override - public int hashCode() { - return Arrays.hashCode(opaqueNodeAttribute); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrOpaqueNode) { - BgpAttrOpaqueNode other = (BgpAttrOpaqueNode) obj; - return Arrays - .equals(opaqueNodeAttribute, other.opaqueNodeAttribute); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("opaqueNodeAttribute", opaqueNodeAttribute).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java deleted file mode 100644 index f3c0d17b..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute node router ID. - */ -public final class BgpAttrRouterIdV4 implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrRouterIdV4.class); - - private final short sType; - - /* IPv4 Router-ID of Node */ - private final Ip4Address ip4RouterId; - - /** - * Constructor to initialize the value. - * - * @param ip4RouterId IPV4 address of router - * @param sType TLV type - */ - private BgpAttrRouterIdV4(Ip4Address ip4RouterId, short sType) { - this.ip4RouterId = ip4RouterId; - this.sType = sType; - } - - /** - * Returns object of this class with specified values. - * - * @param ip4RouterId IPv4 address - * @param sType Type of this TLV - * @return object of BgpAttrRouterIdV4 - */ - public static BgpAttrRouterIdV4 of(final Ip4Address ip4RouterId, - final short sType) { - return new BgpAttrRouterIdV4(ip4RouterId, sType); - } - - /** - * Reads the IPv4 Router-ID. - * - * @param cb ChannelBuffer - * @param sType tag type - * @return object of BgpAttrRouterIdV4 - * @throws BgpParseException while parsing BgpAttrRouterIdV4 - */ - public static BgpAttrRouterIdV4 read(ChannelBuffer cb, short sType) - throws BgpParseException { - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != 4) || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - byte[] ipBytes = new byte[lsAttrLength]; - cb.readBytes(ipBytes, 0, lsAttrLength); - Ip4Address ip4RouterId = Ip4Address.valueOf(ipBytes); - return BgpAttrRouterIdV4.of(ip4RouterId, sType); - } - - /** - * Returns the IPV4 router ID. - * - * @return Router ID - */ - public Ip4Address attrRouterId() { - return ip4RouterId; - } - - @Override - public short getType() { - return sType; - } - - @Override - public int hashCode() { - return Objects.hash(ip4RouterId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrRouterIdV4) { - BgpAttrRouterIdV4 other = (BgpAttrRouterIdV4) obj; - return Objects.equals(ip4RouterId, other.ip4RouterId); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("ip4RouterId", ip4RouterId).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java deleted file mode 100644 index 648fd56e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip6Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute IPv6 router ID. - */ -public final class BgpAttrRouterIdV6 implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpAttrRouterIdV6.class); - - private final short sType; - - /* IPv4 Router-ID of Node */ - private final Ip6Address ip6RouterId; - - /** - * Constructor to initialize the value. - * - * @param ip6RouterId IPV6 address of the router ID - * @param sType TLV type - */ - private BgpAttrRouterIdV6(Ip6Address ip6RouterId, short sType) { - this.ip6RouterId = ip6RouterId; - this.sType = sType; - } - - /** - * Returns object of this class with specified values. - * - * @param ip6RouterId IPV6 address of the router ID - * @param sType TLV type - * @return object of BgpAttrRouterIdV6 - */ - public static BgpAttrRouterIdV6 of(final Ip6Address ip6RouterId, - final short sType) { - return new BgpAttrRouterIdV6(ip6RouterId, sType); - } - - /** - * Reads the IPv6 Router-ID. - * - * @param cb ChannelBuffer - * @param sType TLV type - * @return object of BgpAttrRouterIdV6 - * @throws BgpParseException while parsing BgpAttrRouterIdV6 - */ - public static BgpAttrRouterIdV6 read(ChannelBuffer cb, short sType) - throws BgpParseException { - byte[] ipBytes; - Ip6Address ip6RouterId; - - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != 16) || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - ipBytes = new byte[lsAttrLength]; - cb.readBytes(ipBytes); - ip6RouterId = Ip6Address.valueOf(ipBytes); - return BgpAttrRouterIdV6.of(ip6RouterId, sType); - } - - /** - * Returns IPV6 router ID. - * - * @return Router ID - */ - public Ip6Address attrRouterId() { - return ip6RouterId; - } - - @Override - public short getType() { - return sType; - } - - @Override - public int hashCode() { - return Objects.hash(ip6RouterId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpAttrRouterIdV6) { - BgpAttrRouterIdV6 other = (BgpAttrRouterIdV6) obj; - return Objects.equals(ip6RouterId, other.ip6RouterId); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("ip6RouterId", ip6RouterId).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java deleted file mode 100644 index 5721cf6c..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link IGP metric attribute. - */ -public class BgpLinkAttrIgpMetric implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrIgpMetric.class); - - public static final int ATTRLINK_IGPMETRIC = 1095; - public static final int ATTRLINK_MAX_LEN = 3; - - /* Variable metric length based on protocol */ - public static final int ISIS_SMALL_METRIC = 1; - public static final int OSPF_LINK_METRIC = 2; - public static final int ISIS_WIDE_METRIC = 3; - - /* IGP Metric */ - private final int igpMetric; - private final int igpMetricLen; - - /** - * Constructor to initialize the value. - * - * @param igpMetric 3 byte IGP metric data. - * @param igpMetricLen length of IGP metric data. - */ - public BgpLinkAttrIgpMetric(final int igpMetric, final int igpMetricLen) { - this.igpMetric = igpMetric; - this.igpMetricLen = igpMetricLen; - } - - /** - * Returns object of this class with specified values. - * - * @param igpMetric 3 byte IGP metric data. - * @param igpMetricLen length of IGP metric data. - * @return object of BgpLinkAttrIgpMetric - */ - public static BgpLinkAttrIgpMetric of(final int igpMetric, - final int igpMetricLen) { - return new BgpLinkAttrIgpMetric(igpMetric, igpMetricLen); - } - - /** - * Reads the BGP link attributes IGP Metric. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrIgpMetric - * @throws BgpParseException while parsing BgpLinkAttrIgpMetric - */ - public static BgpLinkAttrIgpMetric read(ChannelBuffer cb) - throws BgpParseException { - - short linkigp; - int igpMetric = 0; - int igpMetricLen = 0; - - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength - || lsAttrLength > ATTRLINK_MAX_LEN) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - switch (lsAttrLength) { - case ISIS_SMALL_METRIC: - igpMetric = cb.readByte(); - igpMetricLen = ISIS_SMALL_METRIC; - break; - case OSPF_LINK_METRIC: - igpMetric = cb.readShort(); - igpMetricLen = OSPF_LINK_METRIC; - break; - case ISIS_WIDE_METRIC: - linkigp = cb.readShort(); - igpMetric = cb.readByte(); - igpMetric = (igpMetric << 16) | linkigp; - igpMetricLen = ISIS_WIDE_METRIC; - break; - default: // validation is already in place - break; - } - - return BgpLinkAttrIgpMetric.of(igpMetric, igpMetricLen); - } - - /** - * Returns the variable length IGP metric data. - * - * @return IGP metric data - */ - public int attrLinkIgpMetric() { - return igpMetric; - } - - /** - * Returns IGP metric data length. - * - * @return IGP metric length - */ - public int attrLinkIgpMetricLength() { - return igpMetricLen; - } - - @Override - public short getType() { - return ATTRLINK_IGPMETRIC; - } - - @Override - public int hashCode() { - return Objects.hash(igpMetric, igpMetricLen); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrIgpMetric) { - BgpLinkAttrIgpMetric other = (BgpLinkAttrIgpMetric) obj; - return Objects.equals(igpMetric, other.igpMetric) - && Objects.equals(igpMetricLen, other.igpMetricLen); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("igpMetric", igpMetric).add("igpMetricLen", igpMetricLen) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java deleted file mode 100644 index 448f1e58..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute Is Is Administrative area. - */ -public final class BgpLinkAttrIsIsAdminstGrp implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrIsIsAdminstGrp.class); - - public static final int ATTRLINK_PROTECTIONTYPE = 1088; - public static final int ISIS_ADMIN_DATA_LEN = 4; - - /* ISIS administrative group */ - private final long isisAdminGrp; - - /** - * Constructor to initialize the values. - * - * @param isisAdminGrp ISIS protocol admin group - */ - public BgpLinkAttrIsIsAdminstGrp(long isisAdminGrp) { - this.isisAdminGrp = isisAdminGrp; - } - - /** - * Returns object of this class with specified values. - * - * @param isisAdminGrp ISIS admin group - * @return object of BgpLinkAttrIsIsAdminstGrp - */ - public static BgpLinkAttrIsIsAdminstGrp of(final long isisAdminGrp) { - return new BgpLinkAttrIsIsAdminstGrp(isisAdminGrp); - } - - /** - * Reads the BGP link attributes of ISIS administrative group area. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrIsIsAdminstGrp - * @throws BgpParseException while parsing BgpLinkAttrIsIsAdminstGrp - */ - public static BgpLinkAttrIsIsAdminstGrp read(ChannelBuffer cb) - throws BgpParseException { - long isisAdminGrp; - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != ISIS_ADMIN_DATA_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - isisAdminGrp = cb.readUnsignedInt(); - - return BgpLinkAttrIsIsAdminstGrp.of(isisAdminGrp); - } - - /** - * Link attributes of ISIS administrative group area. - * - * @return long value of the administrative group area - */ - public long linkAttrIsIsAdminGrp() { - return isisAdminGrp; - } - - @Override - public short getType() { - return ATTRLINK_PROTECTIONTYPE; - } - - @Override - public int hashCode() { - return Objects.hash(isisAdminGrp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrIsIsAdminstGrp) { - BgpLinkAttrIsIsAdminstGrp other = (BgpLinkAttrIsIsAdminstGrp) obj; - return Objects.equals(isisAdminGrp, other.isisAdminGrp); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("isisAdminGrp", isisAdminGrp).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java deleted file mode 100644 index 2711ca94..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP attribute Max Link bandwidth. - */ -public final class BgpLinkAttrMaxLinkBandwidth implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrMaxLinkBandwidth.class); - - public static final int MAX_BANDWIDTH_LEN = 4; - public static final int NO_OF_BITS = 8; - - public short type; - - /* ISIS administrative group */ - private final float maxBandwidth; - - /** - * Constructor to initialize the values. - * - * @param maxBandwidth Maximum link bandwidth. - * @param type TLV type - */ - private BgpLinkAttrMaxLinkBandwidth(float maxBandwidth, short type) { - this.maxBandwidth = maxBandwidth; - this.type = type; - } - - /** - * Returns object of this class with specified values. - * - * @param maxBandwidth Maximum link bandwidth. - * @param type TLV type - * @return object of BgpLinkAttrMaxLinkBandwidth - */ - public static BgpLinkAttrMaxLinkBandwidth of(final float maxBandwidth, - final short type) { - return new BgpLinkAttrMaxLinkBandwidth(maxBandwidth, type); - } - - /** - * Reads the BGP link attributes of Maximum link bandwidth. - * - * @param cb Channel buffer - * @param type type of this tlv - * @return object of type BgpLinkAttrMaxLinkBandwidth - * @throws BgpParseException while parsing BgpLinkAttrMaxLinkBandwidth - */ - public static BgpLinkAttrMaxLinkBandwidth read(ChannelBuffer cb, short type) - throws BgpParseException { - float maxBandwidth; - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != MAX_BANDWIDTH_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - maxBandwidth = ieeeToFloatRead(cb.readInt()) * NO_OF_BITS; - - return BgpLinkAttrMaxLinkBandwidth.of(maxBandwidth, type); - } - - /** - * Returns Maximum link bandwidth. - * - * @return Maximum link bandwidth - */ - float linkAttrMaxLinkBandwidth() { - return maxBandwidth; - } - - /** - * Parse the IEEE floating point notation and returns it in normal float. - * - * @param iVal IEEE floating point number - * @return normal float - */ - static float ieeeToFloatRead(int iVal) { - iVal = (((iVal & 0xFF) << 24) | ((iVal & 0xFF00) << 8) - | ((iVal & 0xFF0000) >> 8) | ((iVal >> 24) & 0xFF)); - - return Float.intBitsToFloat(iVal); - } - - @Override - public short getType() { - return this.type; - } - - @Override - public int hashCode() { - return Objects.hash(maxBandwidth); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrMaxLinkBandwidth) { - BgpLinkAttrMaxLinkBandwidth other = (BgpLinkAttrMaxLinkBandwidth) obj; - return Objects.equals(maxBandwidth, other.maxBandwidth); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("maxBandwidth", maxBandwidth).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java deleted file mode 100644 index 2bf1a59d..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP MPLS protocol mask attribute. - */ -public class BgpLinkAttrMplsProtocolMask implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrMplsProtocolMask.class); - - public static final int ATTRLINK_MPLSPROTOMASK = 1094; - public static final int MASK_BYTE_LEN = 1; - - private final boolean bLdp; - private final boolean bRsvpTe; - - public static final byte FIRST_BIT = (byte) 0x80; - public static final byte SECOND_BIT = 0x40; - - /** - * Constructor to initialize the values. - * - * @param bLdp boolean value true if LDP flag is available - * @param bRsvpTe boolean value true if RSVP TE information is available - */ - public BgpLinkAttrMplsProtocolMask(boolean bLdp, boolean bRsvpTe) { - this.bLdp = bLdp; - this.bRsvpTe = bRsvpTe; - } - - /** - * Returns object of this class with specified values. - * - * @param bLdp boolean value true if LDP flag is available - * @param bRsvpTe boolean value true if RSVP TE information is available - * @return object of BgpLinkAttrMplsProtocolMask - */ - public static BgpLinkAttrMplsProtocolMask of(final boolean bLdp, - final boolean bRsvpTe) { - return new BgpLinkAttrMplsProtocolMask(bLdp, bRsvpTe); - } - - /** - * Reads the BGP link attributes MPLS protocol mask. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrMPLSProtocolMask - * @throws BgpParseException while parsing BgpLinkAttrMplsProtocolMask - */ - public static BgpLinkAttrMplsProtocolMask read(ChannelBuffer cb) - throws BgpParseException { - boolean bLdp = false; - boolean bRsvpTe = false; - - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != MASK_BYTE_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - byte flags = cb.readByte(); - - bLdp = ((flags & (byte) FIRST_BIT) == FIRST_BIT); - bRsvpTe = ((flags & (byte) SECOND_BIT) == SECOND_BIT); - - return BgpLinkAttrMplsProtocolMask.of(bLdp, bRsvpTe); - } - - /** - * Returns true if LDP bit is set. - * - * @return True if LDP information is set else false. - */ - public boolean ldpBit() { - return bLdp; - } - - /** - * Returns RSVP TE information. - * - * @return True if RSVP TE information is set else false. - */ - public boolean rsvpBit() { - return bRsvpTe; - } - - @Override - public short getType() { - return ATTRLINK_MPLSPROTOMASK; - } - - @Override - public int hashCode() { - return Objects.hash(bLdp, bRsvpTe); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrMplsProtocolMask) { - BgpLinkAttrMplsProtocolMask other = (BgpLinkAttrMplsProtocolMask) obj; - return Objects.equals(bLdp, other.bLdp) - && Objects.equals(bRsvpTe, other.bRsvpTe); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("bLdp", bLdp).add("bRsvpTe", bRsvpTe).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java deleted file mode 100644 index 856ffc36..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link name attribute. - */ -public class BgpLinkAttrName implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrName.class); - - public static final int ATTRLINK_NAME = 1098; - - /* Link Name */ - private byte[] linkName; - - /** - * Constructor to initialize the values. - * - * @param linkName link name - */ - public BgpLinkAttrName(byte[] linkName) { - this.linkName = Arrays.copyOf(linkName, linkName.length); - } - - /** - * Returns object of this class with specified values. - * - * @param linkName Prefix Metric - * @return object of BgpLinkAttrName - */ - public static BgpLinkAttrName of(byte[] linkName) { - return new BgpLinkAttrName(linkName); - } - - /** - * Reads the BGP link attributes Name. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrName - * @throws BgpParseException while parsing BgpLinkAttrName - */ - public static BgpLinkAttrName read(ChannelBuffer cb) - throws BgpParseException { - byte[] linkName; - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - linkName = new byte[lsAttrLength]; - cb.readBytes(linkName); - return BgpLinkAttrName.of(linkName); - } - - /** - * Returns the link name. - * - * @return link name - */ - public byte[] attrLinkName() { - return linkName; - } - - @Override - public short getType() { - return ATTRLINK_NAME; - } - - @Override - public int hashCode() { - return Arrays.hashCode(linkName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrName) { - BgpLinkAttrName other = (BgpLinkAttrName) obj; - return Arrays.equals(linkName, other.linkName); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("linkName", linkName).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java deleted file mode 100644 index 275b85be..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link opaque attribute. - */ -public final class BgpLinkAttrOpaqLnkAttrib implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrOpaqLnkAttrib.class); - - public static final int ATTRNODE_OPAQUELNKATTRIB = 1097; - - /* Opaque Node Attribute */ - private final byte[] opaqueLinkAttribute; - - /** - * Constructor to initialize the data. - * - * @param opaqueLinkAttribute opaque link attribute - */ - private BgpLinkAttrOpaqLnkAttrib(byte[] opaqueLinkAttribute) { - this.opaqueLinkAttribute = Arrays.copyOf(opaqueLinkAttribute, - opaqueLinkAttribute.length); - } - - /** - * Returns object of this class with specified values. - * - * @param opaqueLinkAttribute opaque link attribute - * @return object of BgpLinkAttrOpaqLnkAttrib - */ - public static BgpLinkAttrOpaqLnkAttrib of(final byte[] opaqueLinkAttribute) { - return new BgpLinkAttrOpaqLnkAttrib(opaqueLinkAttribute); - } - - /** - * Reads the BGP link attributes Opaque link attribute. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrOpaqLnkAttrib - * @throws BgpParseException while parsing BgpLinkAttrOpaqLnkAttrib - */ - public static BgpLinkAttrOpaqLnkAttrib read(ChannelBuffer cb) - throws BgpParseException { - - byte[] opaqueLinkAttribute; - - short lsAttrLength = cb.readShort(); - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - opaqueLinkAttribute = new byte[lsAttrLength]; - cb.readBytes(opaqueLinkAttribute); - - return BgpLinkAttrOpaqLnkAttrib.of(opaqueLinkAttribute); - } - - /** - * Returns the Opaque link attribute. - * - * @return byte array of opaque link attribute. - */ - public byte[] attrOpaqueLnk() { - return opaqueLinkAttribute; - } - - @Override - public short getType() { - return ATTRNODE_OPAQUELNKATTRIB; - } - - @Override - public int hashCode() { - return Arrays.hashCode(opaqueLinkAttribute); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrOpaqLnkAttrib) { - BgpLinkAttrOpaqLnkAttrib other = (BgpLinkAttrOpaqLnkAttrib) obj; - return Arrays - .equals(opaqueLinkAttribute, other.opaqueLinkAttribute); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("opaqueLinkAttribute", opaqueLinkAttribute).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java deleted file mode 100644 index 59011d97..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link protection type attribute. - */ -public final class BgpLinkAttrProtectionType implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrProtectionType.class); - - public static final int ATTRLINK_PROTECTIONTYPE = 1093; - public static final int LINK_PROTECTION_LEN = 2; - - public static final int EXTRA_TRAFFIC = 0x01; - public static final int UNPROTECTED = 0x02; - public static final int SHARED = 0x04; - public static final int DEDICATED_ONE_ISTO_ONE = 0x08; - public static final int DEDICATED_ONE_PLUS_ONE = 0x10; - public static final int ENHANCED = 0x20; - - /* Link Protection type flags */ - private final boolean bExtraTraffic; - private final boolean bUnprotected; - private final boolean bShared; - private final boolean bDedOneIstoOne; - private final boolean bDedOnePlusOne; - private final boolean bEnhanced; - - /** - * Constructor to initialize the value. - * - * @param bExtraTraffic Extra Traffic - * @param bUnprotected Unprotected - * @param bShared Shared - * @param bDedOneIstoOne Dedicated 1:1 - * @param bDedOnePlusOne Dedicated 1+1 - * @param bEnhanced Enhanced - */ - private BgpLinkAttrProtectionType(boolean bExtraTraffic, - boolean bUnprotected, - boolean bShared, boolean bDedOneIstoOne, - boolean bDedOnePlusOne, boolean bEnhanced) { - this.bExtraTraffic = bExtraTraffic; - this.bUnprotected = bUnprotected; - this.bShared = bShared; - this.bDedOneIstoOne = bDedOneIstoOne; - this.bDedOnePlusOne = bDedOnePlusOne; - this.bEnhanced = bEnhanced; - } - - /** - * Returns object of this class with specified values. - * - * @param bExtraTraffic Extra Traffic - * @param bUnprotected Unprotected - * @param bShared Shared - * @param bDedOneIstoOne Dedicated 1:1 - * @param bDedOnePlusOne Dedicated 1+1 - * @param bEnhanced Enhanced - * @return object of BgpLinkAttrProtectionType - */ - public static BgpLinkAttrProtectionType of(boolean bExtraTraffic, - boolean bUnprotected, - boolean bShared, - boolean bDedOneIstoOne, - boolean bDedOnePlusOne, - boolean bEnhanced) { - return new BgpLinkAttrProtectionType(bExtraTraffic, bUnprotected, - bShared, bDedOneIstoOne, - bDedOnePlusOne, bEnhanced); - } - - /** - * Reads the BGP link attributes protection type. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrProtectionType - * @throws BgpParseException while parsing BgpLinkAttrProtectionType - */ - public static BgpLinkAttrProtectionType read(ChannelBuffer cb) - throws BgpParseException { - short linkProtectionType; - byte higherByte; - short lsAttrLength = cb.readShort(); - - boolean bExtraTraffic; - boolean bUnprotected; - boolean bShared; - boolean bDedOneIstoOne; - boolean bDedOnePlusOne; - boolean bEnhanced; - - if ((lsAttrLength != LINK_PROTECTION_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - linkProtectionType = cb.readShort(); - higherByte = (byte) (linkProtectionType >> 8); - - bExtraTraffic = ((higherByte & (byte) EXTRA_TRAFFIC) == EXTRA_TRAFFIC); - bUnprotected = ((higherByte & (byte) UNPROTECTED) == UNPROTECTED); - bShared = ((higherByte & (byte) SHARED) == SHARED); - bDedOneIstoOne = ((higherByte & (byte) DEDICATED_ONE_ISTO_ONE) == DEDICATED_ONE_ISTO_ONE); - bDedOnePlusOne = ((higherByte & (byte) DEDICATED_ONE_PLUS_ONE) == DEDICATED_ONE_PLUS_ONE); - bEnhanced = ((higherByte & (byte) ENHANCED) == ENHANCED); - - return BgpLinkAttrProtectionType.of(bExtraTraffic, bUnprotected, - bShared, bDedOneIstoOne, - bDedOnePlusOne, bEnhanced); - } - - /** - * Returns ExtraTraffic Bit. - * - * @return ExtraTraffic Bit - */ - public boolean extraTraffic() { - return bExtraTraffic; - } - - /** - * Returns Unprotected Bit. - * - * @return Unprotected Bit - */ - public boolean unprotected() { - return bUnprotected; - } - - /** - * Returns Shared Bit. - * - * @return Shared Bit - */ - public boolean shared() { - return bShared; - } - - /** - * Returns DedOneIstoOne Bit. - * - * @return DedOneIstoOne Bit - */ - public boolean dedOneIstoOne() { - return bDedOneIstoOne; - } - - /** - * Returns DedOnePlusOne Bit. - * - * @return DedOnePlusOne Bit - */ - public boolean dedOnePlusOne() { - return bDedOnePlusOne; - } - - /** - * Returns Enhanced Bit. - * - * @return Enhanced Bit - */ - public boolean enhanced() { - return bEnhanced; - } - - @Override - public short getType() { - return ATTRLINK_PROTECTIONTYPE; - } - - @Override - public int hashCode() { - return Objects.hash(bExtraTraffic, bUnprotected, bShared, - bDedOneIstoOne, bDedOnePlusOne, bEnhanced); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrProtectionType) { - BgpLinkAttrProtectionType other = (BgpLinkAttrProtectionType) obj; - return Objects.equals(bExtraTraffic, other.bExtraTraffic) - && Objects.equals(bUnprotected, other.bUnprotected) - && Objects.equals(bShared, other.bShared) - && Objects.equals(bDedOneIstoOne, other.bDedOneIstoOne) - && Objects.equals(bDedOnePlusOne, other.bDedOnePlusOne) - && Objects.equals(bEnhanced, other.bEnhanced); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("bExtraTraffic", bExtraTraffic) - .add("bUnprotected", bUnprotected).add("bShared", bShared) - .add("bDedOneIstoOne", bDedOneIstoOne) - .add("bDedOnePlusOne", bDedOnePlusOne) - .add("bEnhanced", bEnhanced).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java deleted file mode 100644 index 4a6f23f9..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link Shared Risk Link Group attribute. - */ -public class BgpLinkAttrSrlg implements BgpValueType { - - public static final short ATTRNODE_SRLG = 1097; - - /* Shared Risk Link Group */ - private List sRlg = new ArrayList(); - - /** - * Constructor to initialize the date. - * - * @param sRlg Shared Risk link group data - */ - public BgpLinkAttrSrlg(List sRlg) { - this.sRlg = sRlg; - } - - /** - * Returns object of this class with specified values. - * - * @param sRlg Shared Risk link group data - * @return object of BgpLinkAttrSrlg - */ - public static BgpLinkAttrSrlg of(ArrayList sRlg) { - return new BgpLinkAttrSrlg(sRlg); - } - - /** - * Reads the BGP link attributes Shared Risk link group data. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrSrlg - * @throws BgpParseException while parsing BgpLinkAttrSrlg - */ - public static BgpLinkAttrSrlg read(ChannelBuffer cb) - throws BgpParseException { - int tempSrlg; - ArrayList sRlg = new ArrayList(); - - short lsAttrLength = cb.readShort(); - int len = lsAttrLength / Integer.SIZE; // each element is of 4 octets - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - for (int i = 0; i < len; i++) { - tempSrlg = cb.readInt(); - sRlg.add(new Integer(tempSrlg)); - } - - return BgpLinkAttrSrlg.of(sRlg); - } - - /** - * Returns the Shared Risk link group data. - * - * @return array of Shared Risk link group data - */ - public List attrSrlg() { - return sRlg; - } - - @Override - public short getType() { - return ATTRNODE_SRLG; - } - - @Override - public int hashCode() { - return Objects.hash(sRlg); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrSrlg) { - BgpLinkAttrSrlg other = (BgpLinkAttrSrlg) obj; - return Objects.equals(sRlg, other.sRlg); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues().add("sRlg", sRlg).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java deleted file mode 100644 index 1ae7ecc5..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP link state Default TE metric link attribute. - */ -public class BgpLinkAttrTeDefaultMetric implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrTeDefaultMetric.class); - - public static final int ATTRLINK_TEDEFAULTMETRIC = 1092; - public static final int TE_DATA_LEN = 4; - - /* TE Default Metric */ - private int linkTeMetric; - - /** - * Constructor to initialize the value. - * - * @param linkTeMetric TE default metric - * - */ - public BgpLinkAttrTeDefaultMetric(int linkTeMetric) { - this.linkTeMetric = linkTeMetric; - } - - /** - * Returns object of this class with specified values. - * - * @param linkTeMetric TE default metric - * @return object of BgpLinkAttrTeDefaultMetric - */ - public static BgpLinkAttrTeDefaultMetric of(final int linkTeMetric) { - return new BgpLinkAttrTeDefaultMetric(linkTeMetric); - } - - /** - * Reads the BGP link attributes of TE default metric. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrTeDefaultMetric - * @throws BgpParseException while parsing BgpLinkAttrTeDefaultMetric - */ - public static BgpLinkAttrTeDefaultMetric read(ChannelBuffer cb) - throws BgpParseException { - int linkTeMetric; - - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != TE_DATA_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - linkTeMetric = cb.readInt(); - - return new BgpLinkAttrTeDefaultMetric(linkTeMetric); - } - - /** - * Returns the TE default metrics. - * - * @return link default metric - */ - public int attrLinkDefTeMetric() { - return linkTeMetric; - } - - @Override - public short getType() { - return ATTRLINK_TEDEFAULTMETRIC; - } - - @Override - public int hashCode() { - return Objects.hash(linkTeMetric); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrTeDefaultMetric) { - BgpLinkAttrTeDefaultMetric other = (BgpLinkAttrTeDefaultMetric) obj; - return Objects.equals(linkTeMetric, other.linkTeMetric); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("linkTEMetric", linkTeMetric).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java deleted file mode 100644 index c927eea5..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP unreserved bandwidth attribute. - */ -public class BgpLinkAttrUnRsrvdLinkBandwidth implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpLinkAttrUnRsrvdLinkBandwidth.class); - - public static final int MAX_BANDWIDTH_LEN = 4; - public static final int NO_OF_BITS = 8; - public static final int NO_OF_PRIORITY = 8; - - public short sType; - - /* ISIS administrative group */ - private List maxUnResBandwidth = new ArrayList(); - - /** - * Constructor to initialize the values. - * - * @param maxUnResBandwidth Maximum Unreserved bandwidth - * @param sType returns the tag value - */ - public BgpLinkAttrUnRsrvdLinkBandwidth(List maxUnResBandwidth, - short sType) { - this.maxUnResBandwidth = maxUnResBandwidth; - this.sType = sType; - } - - /** - * Returns object of this class with specified values. - * - * @param linkPfxMetric Prefix Metric - * @param sType returns the tag value - * @return object of BgpLinkAttrUnRsrvdLinkBandwidth - */ - public static BgpLinkAttrUnRsrvdLinkBandwidth of(List linkPfxMetric, short sType) { - return new BgpLinkAttrUnRsrvdLinkBandwidth(linkPfxMetric, sType); - } - - /** - * Reads the BGP link attributes of Maximum link bandwidth. - * - * @param cb Channel buffer - * @return object of type BgpLinkAttrMaxLinkBandwidth - * @throws BgpParseException while parsing BgpLinkAttrMaxLinkBandwidth - */ - public static BgpLinkAttrUnRsrvdLinkBandwidth read(ChannelBuffer cb, - short sType) - throws BgpParseException { - ArrayList maxUnResBandwidth = new ArrayList(); - float tmp; - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != MAX_BANDWIDTH_LEN * NO_OF_PRIORITY) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - for (int i = 0; i < NO_OF_PRIORITY; i++) { - tmp = ieeeToFloatRead(cb.readInt()) * NO_OF_BITS; - maxUnResBandwidth.add(new Float(tmp)); - } - - return BgpLinkAttrUnRsrvdLinkBandwidth.of(maxUnResBandwidth, sType); - } - - /** - * Returns maximum unreserved bandwidth. - * - * @return unreserved bandwidth. - */ - public List getLinkAttrUnRsrvdLinkBandwidth() { - return maxUnResBandwidth; - } - - /** - * Parse the IEEE floating point notation and returns it in normal float. - * - * @param iVal IEEE floating point number - * @return normal float - */ - static float ieeeToFloatRead(int iVal) { - iVal = (((iVal & 0xFF) << 24) | ((iVal & 0xFF00) << 8) - | ((iVal & 0xFF0000) >> 8) | ((iVal >> 24) & 0xFF)); - - return Float.intBitsToFloat(iVal); - } - - @Override - public short getType() { - return this.sType; - } - - @Override - public int hashCode() { - return Objects.hash(maxUnResBandwidth); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpLinkAttrUnRsrvdLinkBandwidth) { - BgpLinkAttrUnRsrvdLinkBandwidth other = (BgpLinkAttrUnRsrvdLinkBandwidth) obj; - return Objects.equals(maxUnResBandwidth, other.maxUnResBandwidth); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("maxUnResBandwidth", maxUnResBandwidth).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java deleted file mode 100644 index a2d7c57e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix route Extended tag attribute. - */ -public class BgpPrefixAttrExtRouteTag implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrExtRouteTag.class); - - public static final int ATTR_PREFIX_EXTROUTETAG = 1154; - public static final int ATTR_PREFIX_EXT_LEN = 8; - - /* Prefix Route Tag */ - private List pfxExtRouteTag = new ArrayList(); - - /** - * Constructor to initialize the values. - * - * @param pfxExtRouteTag Extended route tag - */ - public BgpPrefixAttrExtRouteTag(List pfxExtRouteTag) { - this.pfxExtRouteTag = checkNotNull(pfxExtRouteTag); - } - - /** - * Returns object of this class with specified values. - * - * @param pfxExtRouteTag Prefix Metric - * @return object of BgpPrefixAttrMetric - */ - public static BgpPrefixAttrExtRouteTag of(ArrayList pfxExtRouteTag) { - return new BgpPrefixAttrExtRouteTag(pfxExtRouteTag); - } - - /** - * Reads the Extended Tag. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrExtRouteTag - * @throws BgpParseException while parsing BgpPrefixAttrExtRouteTag - */ - public static BgpPrefixAttrExtRouteTag read(ChannelBuffer cb) - throws BgpParseException { - ArrayList pfxExtRouteTag = new ArrayList(); - long temp; - - short lsAttrLength = cb.readShort(); - int len = lsAttrLength / ATTR_PREFIX_EXT_LEN; - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - for (int i = 0; i < len; i++) { - temp = cb.readLong(); - pfxExtRouteTag.add(new Long(temp)); - } - - return new BgpPrefixAttrExtRouteTag(pfxExtRouteTag); - } - - /** - * Returns Extended route tag. - * - * @return route tag - */ - public List pfxExtRouteTag() { - return pfxExtRouteTag; - } - - @Override - public short getType() { - return ATTR_PREFIX_EXTROUTETAG; - } - - @Override - public int hashCode() { - return Objects.hash(pfxExtRouteTag); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrExtRouteTag) { - BgpPrefixAttrExtRouteTag other = (BgpPrefixAttrExtRouteTag) obj; - return Objects.equals(pfxExtRouteTag, other.pfxExtRouteTag); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("pfxExtRouteTag", pfxExtRouteTag).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java deleted file mode 100644 index 4e84191a..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix IGP Flag attribute. - */ -public final class BgpPrefixAttrIgpFlags implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrIgpFlags.class); - - public static final int ATTR_PREFIX_FLAGBIT = 1152; - public static final int ATTR_PREFIX_FLAG_LEN = 1; - - public static final byte FIRST_BIT = (byte) 0x80; - public static final byte SECOND_BIT = 0x40; - public static final byte THIRD_BIT = 0x20; - public static final byte FOURTH_BIT = 0x01; - - /* Prefix IGP flag bit TLV */ - private final boolean bisisUpDownBit; - private final boolean bOspfNoUnicastBit; - private final boolean bOspfLclAddrBit; - private final boolean bOspfNSSABit; - - /** - * Constructor to initialize the value. - * - * @param bisisUpDownBit IS-IS Up/Down Bit - * @param bOspfNoUnicastBit OSPF no unicast Bit - * @param bOspfLclAddrBit OSPF local address Bit - * @param bOspfNSSABit OSPF propagate NSSA Bit - */ - BgpPrefixAttrIgpFlags(boolean bisisUpDownBit, - boolean bOspfNoUnicastBit, - boolean bOspfLclAddrBit, boolean bOspfNSSABit) { - this.bisisUpDownBit = bisisUpDownBit; - this.bOspfNoUnicastBit = bOspfNoUnicastBit; - this.bOspfLclAddrBit = bOspfLclAddrBit; - this.bOspfNSSABit = bOspfNSSABit; - } - - /** - * Returns object of this class with specified values. - * - * @param bisisUpDownBit IS-IS Up/Down Bit - * @param bOspfNoUnicastBit OSPF no unicast Bit - * @param bOspfLclAddrBit OSPF local address Bit - * @param bOspfNSSABit OSPF propagate NSSA Bit - * @return object of BgpPrefixAttrIGPFlags - */ - public static BgpPrefixAttrIgpFlags of(final boolean bisisUpDownBit, - final boolean bOspfNoUnicastBit, - final boolean bOspfLclAddrBit, - final boolean bOspfNSSABit) { - return new BgpPrefixAttrIgpFlags(bisisUpDownBit, bOspfNoUnicastBit, - bOspfLclAddrBit, bOspfNSSABit); - } - - /** - * Reads the IGP Flags. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrIGPFlags - * @throws BgpParseException while parsing BgpPrefixAttrIGPFlags - */ - public static BgpPrefixAttrIgpFlags read(ChannelBuffer cb) - throws BgpParseException { - boolean bisisUpDownBit = false; - boolean bOspfNoUnicastBit = false; - boolean bOspfLclAddrBit = false; - boolean bOspfNSSABit = false; - - short lsAttrLength = cb.readShort(); - - if ((lsAttrLength != ATTR_PREFIX_FLAG_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - byte nodeFlagBits = cb.readByte(); - - bisisUpDownBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT); - bOspfNoUnicastBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT); - bOspfLclAddrBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT); - bOspfNSSABit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT); - - return BgpPrefixAttrIgpFlags.of(bisisUpDownBit, bOspfNoUnicastBit, - bOspfLclAddrBit, bOspfNSSABit); - } - - /** - * Returns the IS-IS Up/Down Bit set or not. - * - * @return IS-IS Up/Down Bit set or not - */ - public boolean isisUpDownBit() { - return bisisUpDownBit; - } - - /** - * Returns the OSPF no unicast Bit set or not. - * - * @return OSPF no unicast Bit set or not - */ - public boolean ospfNoUnicastBit() { - return bOspfNoUnicastBit; - } - - /** - * Returns the OSPF local address Bit set or not. - * - * @return OSPF local address Bit set or not - */ - public boolean ospfLclAddrBit() { - return bOspfLclAddrBit; - } - - /** - * Returns the OSPF propagate NSSA Bit set or not. - * - * @return OSPF propagate NSSA Bit set or not - */ - public boolean ospfNSSABit() { - return bOspfNSSABit; - } - - @Override - public short getType() { - return ATTR_PREFIX_FLAGBIT; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public int hashCode() { - return Objects.hash(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, - bOspfNSSABit); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrIgpFlags) { - BgpPrefixAttrIgpFlags other = (BgpPrefixAttrIgpFlags) obj; - return Objects.equals(bisisUpDownBit, other.bisisUpDownBit) - && Objects.equals(bOspfNoUnicastBit, - other.bOspfNoUnicastBit) - && Objects.equals(bOspfLclAddrBit, other.bOspfLclAddrBit) - && Objects.equals(bOspfNSSABit, other.bOspfNSSABit); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("bisisUpDownBit", bisisUpDownBit) - .add("bOspfNoUnicastBit", bOspfNoUnicastBit) - .add("bOspfLclAddrBit", bOspfLclAddrBit) - .add("bOspfNSSABit", bOspfNSSABit).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java deleted file mode 100644 index 1886102c..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix metric attribute. - */ -public class BgpPrefixAttrMetric implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrMetric.class); - - public static final int ATTR_PREFIX_METRIC = 1155; - public static final int ATTR_PREFIX_LEN = 4; - - /* TE Default Metric */ - private final int linkPfxMetric; - - /** - * Constructor to initialize value. - * - * @param linkPfxMetric Prefix Metric - */ - public BgpPrefixAttrMetric(int linkPfxMetric) { - this.linkPfxMetric = linkPfxMetric; - } - - /** - * Returns object of this class with specified values. - * - * @param linkPfxMetric Prefix Metric - * @return object of BgpPrefixAttrMetric - */ - public static BgpPrefixAttrMetric of(final int linkPfxMetric) { - return new BgpPrefixAttrMetric(linkPfxMetric); - } - - /** - * Reads the Prefix Metric. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrMetric - * @throws BgpParseException while parsing BgpPrefixAttrMetric - */ - public static BgpPrefixAttrMetric read(ChannelBuffer cb) - throws BgpParseException { - int linkPfxMetric; - - short lsAttrLength = cb.readShort(); // 4 Bytes - - if ((lsAttrLength != ATTR_PREFIX_LEN) - || (cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - linkPfxMetric = cb.readInt(); - - return BgpPrefixAttrMetric.of(linkPfxMetric); - } - - /** - * Returns the Prefix Metric. - * - * @return Prefix Metric - */ - public int attrPfxMetric() { - return linkPfxMetric; - } - - @Override - public short getType() { - return ATTR_PREFIX_METRIC; - } - - @Override - public int hashCode() { - return Objects.hash(linkPfxMetric); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrMetric) { - BgpPrefixAttrMetric other = (BgpPrefixAttrMetric) obj; - return Objects.equals(linkPfxMetric, other.linkPfxMetric); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("linkPfxMetric", linkPfxMetric).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java deleted file mode 100644 index 6f7a74bb..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix opaque data attribute. - */ -public final class BgpPrefixAttrOpaqueData implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrOpaqueData.class); - - public static final int ATTR_PREFIX_OPAQUEDATA = 1157; - - /* Opaque Node Attribute */ - private final byte[] opaquePrefixAttribute; - - /** - * Constructor to initialize the values. - * - * @param opaquePrefixAttribute opaque prefix data - */ - public BgpPrefixAttrOpaqueData(byte[] opaquePrefixAttribute) { - this.opaquePrefixAttribute = Arrays - .copyOf(opaquePrefixAttribute, opaquePrefixAttribute.length); - } - - /** - * Returns object of this class with specified values. - * - * @param opaquePrefixAttribute opaque prefix data - * @return object of BgpPrefixAttrOpaqueData - */ - public static BgpPrefixAttrOpaqueData of(final byte[] opaquePrefixAttribute) { - return new BgpPrefixAttrOpaqueData(opaquePrefixAttribute); - } - - /** - * Reads the Opaque Prefix Attribute. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrOpaqueData - * @throws BgpParseException while parsing BgpPrefixAttrOpaqueData - */ - public static BgpPrefixAttrOpaqueData read(ChannelBuffer cb) - throws BgpParseException { - byte[] opaquePrefixAttribute; - - short lsAttrLength = cb.readShort(); - opaquePrefixAttribute = new byte[lsAttrLength]; - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - cb.readBytes(opaquePrefixAttribute); - - return BgpPrefixAttrOpaqueData.of(opaquePrefixAttribute); - } - - /** - * Returns the Opaque prefix attribute name. - * - * @return opaque prefix name - */ - public byte[] getOpaquePrefixAttribute() { - return opaquePrefixAttribute; - } - - @Override - public short getType() { - return ATTR_PREFIX_OPAQUEDATA; - } - - @Override - public int hashCode() { - return Arrays.hashCode(opaquePrefixAttribute); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrOpaqueData) { - BgpPrefixAttrOpaqueData other = (BgpPrefixAttrOpaqueData) obj; - return Arrays.equals(opaquePrefixAttribute, - other.opaquePrefixAttribute); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("opaquePrefixAttribute", getOpaquePrefixAttribute()) - .toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java deleted file mode 100644 index 4e9db1ee..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.Ip6Address; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix OSPF Forwarding address attribute. - */ -public class BgpPrefixAttrOspfFwdAddr implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrOspfFwdAddr.class); - - public static final int ATTR_PREFIX_OSPFFWDADDR = 1156; - public static final int IPV4_LEN = 4; - public static final int IPV6_LEN = 16; - - /* OSPF Forwarding Address */ - private final short lsAttrLength; - private final Ip4Address ip4RouterId; - private final Ip6Address ip6RouterId; - - /** - * Constructor to initialize the value. - * - * @param lsAttrLength length of the IP address - * @param ip4RouterId Valid IPV4 address if length is 4 else null - * @param ip6RouterId Valid IPV6 address if length is 16 else null - */ - public BgpPrefixAttrOspfFwdAddr(short lsAttrLength, Ip4Address ip4RouterId, - Ip6Address ip6RouterId) { - this.lsAttrLength = lsAttrLength; - this.ip4RouterId = ip4RouterId; - this.ip6RouterId = ip6RouterId; - } - - /** - * Returns object of this class with specified values. - * - * @param lsAttrLength length of the IP address - * @param ip4RouterId Valid IPV4 address if length is 4 else null - * @param ip6RouterId Valid IPV6 address if length is 16 else null - * @return object of BgpPrefixAttrOspfFwdAddr - */ - public static BgpPrefixAttrOspfFwdAddr of(final short lsAttrLength, - final Ip4Address ip4RouterId, - final Ip6Address ip6RouterId) { - return new BgpPrefixAttrOspfFwdAddr(lsAttrLength, ip4RouterId, - ip6RouterId); - } - - /** - * Reads the OSPF Forwarding Address. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrOSPFFwdAddr - * @throws BgpParseException while parsing BgpPrefixAttrOspfFwdAddr - */ - public static BgpPrefixAttrOspfFwdAddr read(ChannelBuffer cb) - throws BgpParseException { - short lsAttrLength; - byte[] ipBytes; - Ip4Address ip4RouterId = null; - Ip6Address ip6RouterId = null; - - lsAttrLength = cb.readShort(); - ipBytes = new byte[lsAttrLength]; - - if ((cb.readableBytes() < lsAttrLength)) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - cb.readBytes(ipBytes); - - if (IPV4_LEN == lsAttrLength) { - ip4RouterId = Ip4Address.valueOf(ipBytes); - } else if (IPV6_LEN == lsAttrLength) { - ip6RouterId = Ip6Address.valueOf(ipBytes); - } - - return BgpPrefixAttrOspfFwdAddr.of(lsAttrLength, ip4RouterId, - ip6RouterId); - } - - /** - * Returns IPV4 Address of OSPF forwarding address. - * - * @return IPV4 address - */ - public Ip4Address ospfv4FwdAddr() { - return ip4RouterId; - } - - /** - * Returns IPV6 Address of OSPF forwarding address. - * - * @return IPV6 address - */ - public Ip6Address ospfv6FwdAddr() { - return ip6RouterId; - } - - /** - * Returns OSPF forwarding address length. - * - * @return length of the ip address - */ - public short ospfFwdAddrLen() { - return lsAttrLength; - } - - @Override - public short getType() { - return ATTR_PREFIX_OSPFFWDADDR; - } - - @Override - public int hashCode() { - if (IPV4_LEN == lsAttrLength) { - return Objects.hash(ip4RouterId); - } else { - return Objects.hash(ip6RouterId); - } - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrOspfFwdAddr) { - BgpPrefixAttrOspfFwdAddr other = (BgpPrefixAttrOspfFwdAddr) obj; - if (IPV4_LEN == lsAttrLength) { - return Objects.equals(ip4RouterId, other.ip4RouterId); - } else { - return Objects.equals(ip6RouterId, other.ip6RouterId); - } - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - if (IPV4_LEN == lsAttrLength) { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("ip4RouterId", ip4RouterId).toString(); - } else { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("ip6RouterId", ip6RouterId).toString(); - } - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java deleted file mode 100644 index 3894c003..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.util.Validation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * Implements BGP prefix route tag attribute. - */ -public class BgpPrefixAttrRouteTag implements BgpValueType { - - protected static final Logger log = LoggerFactory - .getLogger(BgpPrefixAttrRouteTag.class); - - public static final short ATTR_PREFIX_ROUTETAG = 1153; - - /* Prefix Route Tag */ - private List pfxRouteTag = new ArrayList(); - - /** - * Constructor to initialize the values. - * - * @param pfxRouteTag prefix route tag - */ - public BgpPrefixAttrRouteTag(List pfxRouteTag) { - this.pfxRouteTag = pfxRouteTag; - } - - /** - * Returns object of this class with specified values. - * - * @param pfxRouteTag Prefix Metric - * @return object of BgpPrefixAttrRouteTag - */ - public static BgpPrefixAttrRouteTag of(ArrayList pfxRouteTag) { - return new BgpPrefixAttrRouteTag(pfxRouteTag); - } - - /** - * Reads the Route Tag. - * - * @param cb ChannelBuffer - * @return object of BgpPrefixAttrRouteTag - * @throws BgpParseException while parsing BgpPrefixAttrRouteTag - */ - public static BgpPrefixAttrRouteTag read(ChannelBuffer cb) - throws BgpParseException { - int tmp; - ArrayList pfxRouteTag = new ArrayList(); - - short lsAttrLength = cb.readShort(); - int len = lsAttrLength / Integer.SIZE; - - if (cb.readableBytes() < lsAttrLength) { - Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, - BgpErrorType.ATTRIBUTE_LENGTH_ERROR, - lsAttrLength); - } - - for (int i = 0; i < len; i++) { - tmp = cb.readInt(); - pfxRouteTag.add(new Integer(tmp)); - } - - return BgpPrefixAttrRouteTag.of(pfxRouteTag); - } - - /** - * Returns the prefix route tag. - * - * @return route tag - */ - public List getPfxRouteTag() { - return pfxRouteTag; - } - - @Override - public short getType() { - return ATTR_PREFIX_ROUTETAG; - } - - @Override - public int hashCode() { - return Objects.hash(pfxRouteTag); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BgpPrefixAttrRouteTag) { - BgpPrefixAttrRouteTag other = (BgpPrefixAttrRouteTag) obj; - return Objects.equals(pfxRouteTag, other.pfxRouteTag); - } - return false; - } - - @Override - public int write(ChannelBuffer cb) { - // TODO This will be implemented in the next version - return 0; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("pfxRouteTag", pfxRouteTag).toString(); - } - - @Override - public int compareTo(Object o) { - // TODO Auto-generated method stub - return 0; - } -} diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java deleted file mode 100755 index e2a74dbc..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of BGP Link state attribute Tlvs. - */ -package org.onosproject.bgpio.types.attr; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java deleted file mode 100755 index 1f2ed95e..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of Tlvs, Attributes and Descriptors. - */ -package org.onosproject.bgpio.types; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java deleted file mode 100644 index 9649bf16..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.util; - -/** - * Provides Constants usage for BGP. - */ -public final class Constants { - private Constants() { - } - - public static final short TYPE_AND_LEN = 4; - public static final short TYPE_AND_LEN_AS_SHORT = 4; - public static final short TYPE_AND_LEN_AS_BYTE = 3; - public static final int ISIS_LEVELONE = 1; - public static final int ISIS_LEVELTWO = 2; - public static final int OSPFV2 = 3; - public static final int DIRECT = 4; - public static final int STATIC_CONFIGURATION = 5; - public static final int OSPFV3 = 6; - public static final short AFI_VALUE = 16388; - public static final byte VPN_SAFI_VALUE = (byte) 0x80; - public static final byte SAFI_VALUE = 71; -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java deleted file mode 100644 index 663b1e9a..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.util; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides methods to handle UnSupportedAttribute. - */ -public final class UnSupportedAttribute { - protected static final Logger log = LoggerFactory.getLogger(UnSupportedAttribute.class); - - private UnSupportedAttribute() { - } - - /** - * Reads channel buffer parses attribute header and skips specified length. - * - * @param cb channelBuffer - */ - public static void read(ChannelBuffer cb) { - Validation parseFlags = Validation.parseAttributeHeader(cb); - cb.skipBytes(parseFlags.getLength()); - } - - /** - * Skip specified bytes in channel buffer. - * - * @param cb channelBuffer - * @param length to be skipped - */ - public static void skipBytes(ChannelBuffer cb, short length) { - cb.skipBytes(length); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java deleted file mode 100644 index 23dd1a75..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgpio.util; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.onlab.packet.IpAddress; -import org.onlab.packet.IpPrefix; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.primitives.Ints; - -/** - * Provides methods to parse attribute header, validate length and type. - */ -public class Validation { - private static final Logger log = LoggerFactory.getLogger(Validation.class); - public static final byte FIRST_BIT = (byte) 0x80; - public static final byte SECOND_BIT = 0x40; - public static final byte THIRD_BIT = 0x20; - public static final byte FOURTH_BIT = (byte) 0x10; - public static final byte IPV4_SIZE = 4; - private boolean firstBit; - private boolean secondBit; - private boolean thirdBit; - private boolean fourthBit; - private int len; - private boolean isShort; - - /** - * Constructor to initialize parameter. - * - * @param firstBit in AttributeFlags - * @param secondBit in AttributeFlags - * @param thirdBit in AttributeFlags - * @param fourthBit in AttributeFlags - * @param len length - * @param isShort true if length is read as short otherwise false - */ - Validation(boolean firstBit, boolean secondBit, boolean thirdBit, boolean fourthBit, int len, boolean isShort) { - this.firstBit = firstBit; - this.secondBit = secondBit; - this.thirdBit = thirdBit; - this.fourthBit = fourthBit; - this.len = len; - this.isShort = isShort; - } - - /** - * Parses attribute Header. - * - * @param cb ChannelBuffer - * @return object of Validation - */ - public static Validation parseAttributeHeader(ChannelBuffer cb) { - - boolean firstBit; - boolean secondBit; - boolean thirdBit; - boolean fourthBit; - boolean isShort; - byte flags = cb.readByte(); - byte typeCode = cb.readByte(); - byte temp = flags; - //first Bit : Optional (1) or well-known (0) - firstBit = ((temp & FIRST_BIT) == FIRST_BIT); - //second Bit : Transitive (1) or non-Transitive (0) - secondBit = ((temp & SECOND_BIT) == SECOND_BIT); - //third Bit : partial (1) or complete (0) - thirdBit = ((temp & THIRD_BIT) == THIRD_BIT); - //forth Bit(Extended Length bit) : Attribute Length is 1 octects (0) or 2 octects (1) - fourthBit = ((temp & FOURTH_BIT) == FOURTH_BIT); - int len; - if (fourthBit) { - isShort = true; - short length = cb.readShort(); - len = length; - } else { - isShort = false; - byte length = cb.readByte(); - len = length; - } - return new Validation(firstBit, secondBit, thirdBit, fourthBit, len, isShort); - } - - /** - * Throws exception if length is not correct. - * - * @param errorCode Error code - * @param subErrCode Sub Error Code - * @param length erroneous length - * @throws BgpParseException for erroneous length - */ - public static void validateLen(byte errorCode, byte subErrCode, int length) throws BgpParseException { - byte[] errLen = Ints.toByteArray(length); - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(errLen); - throw new BgpParseException(errorCode, subErrCode, buffer); - } - - /** - * Throws exception if type is not correct. - * - * @param errorCode Error code - * @param subErrCode Sub Error Code - * @param type erroneous type - * @throws BgpParseException for erroneous type - */ - public static void validateType(byte errorCode, byte subErrCode, int type) throws BgpParseException { - byte[] errType = Ints.toByteArray(type); - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(errType); - throw new BgpParseException(errorCode, subErrCode, buffer); - } - - /** - * Convert byte array to InetAddress. - * - * @param length of IpAddress - * @param cb channelBuffer - * @return InetAddress - */ - public static InetAddress toInetAddress(int length, ChannelBuffer cb) { - byte[] address = new byte[length]; - cb.readBytes(address, 0, length); - InetAddress ipAddress = null; - try { - ipAddress = InetAddress.getByAddress(address); - } catch (UnknownHostException e) { - log.info("InetAddress convertion failed"); - } - return ipAddress; - } - - /** - * Returns first bit in type flags. - * - * @return first bit in type flags - */ - public boolean getFirstBit() { - return this.firstBit; - } - - /** - * Returns second bit in type flags. - * - * @return second bit in type flags - */ - public boolean getSecondBit() { - return this.secondBit; - } - - /** - * Returns third bit in type flags. - * - * @return third bit in type flags - */ - public boolean getThirdBit() { - return this.thirdBit; - } - - /** - * Returns fourth bit in type flags. - * - * @return fourth bit in type flags - */ - public boolean getFourthBit() { - return this.fourthBit; - } - - /** - * Returns attribute length. - * - * @return attribute length - */ - public int getLength() { - return this.len; - } - - /** - * Returns whether attribute length read in short or byte. - * - * @return whether attribute length read in short or byte - */ - public boolean isShort() { - return this.isShort; - } - - /** - * Converts byte array of prefix value to IpPrefix object. - * - * @param value byte array of prefix value - * @param length prefix length in bits - * @return object of IpPrefix - */ - public static IpPrefix bytesToPrefix(byte[] value, int length) { - if (value.length != IPV4_SIZE) { - value = Arrays.copyOf(value, IPV4_SIZE); - } - IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length); - return ipPrefix; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java deleted file mode 100755 index 3229d89a..00000000 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of BGP utility functions. - */ -package org.onosproject.bgpio.util; diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java deleted file mode 100644 index d4c3b610..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import org.junit.Test; -import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP link max bandwidth attribute. - */ -public class BgpLinkAttrMaxLinkBandwidthTest { - private final float val = 0x010203; - private final short valLen = 3; - private final float val1 = 0x01020304; - private final short val1Len = 4; - - private final BgpLinkAttrMaxLinkBandwidth data = BgpLinkAttrMaxLinkBandwidth - .of(val, valLen); - private final BgpLinkAttrMaxLinkBandwidth sameAsData = BgpLinkAttrMaxLinkBandwidth - .of(val, valLen); - private final BgpLinkAttrMaxLinkBandwidth diffData = BgpLinkAttrMaxLinkBandwidth - .of(val1, val1Len); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java deleted file mode 100644 index b6453c45..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import org.junit.Test; -import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP link TE default metric attribute. - */ -public class BgpLinkAttrTeDefaultMetricTest { - private final int val = 0x010203; - private final int val1 = 0x01020304; - - private final BgpLinkAttrTeDefaultMetric data = BgpLinkAttrTeDefaultMetric - .of(val); - private final BgpLinkAttrTeDefaultMetric sameAsData = BgpLinkAttrTeDefaultMetric - .of(val); - private final BgpLinkAttrTeDefaultMetric diffData = BgpLinkAttrTeDefaultMetric - .of(val1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java deleted file mode 100644 index 7ba6a880..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import org.junit.Test; -import org.onosproject.bgpio.types.attr.BgpPrefixAttrOpaqueData; - -import com.google.common.testing.EqualsTester; - -/** - * Test for prefix attribute opaque data Tlv. - */ -public class BgpPrefixAttrOpaqueDataTest { - private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; - private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; - - private final BgpPrefixAttrOpaqueData isisData = BgpPrefixAttrOpaqueData - .of(array); - private final BgpPrefixAttrOpaqueData sameAsIsisData = BgpPrefixAttrOpaqueData - .of(array); - private final BgpPrefixAttrOpaqueData isisDiff = BgpPrefixAttrOpaqueData - .of(array1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java deleted file mode 100755 index 682c1bc0..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.junit.Test; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.core.Is.is; - -/** - * Test case for BGP KEEPALIVE Message. - */ -public class BgpKeepaliveMsgTest { - - /** - * This test case checks BGP Keepalive message. - */ - @Test - public void keepaliveMessageTest1() throws BgpParseException { - - // BGP KEEPALIVE Message - byte[] keepaliveMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - 0x00, 0x13, 0x04}; - - byte[] testKeepaliveMsg; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(keepaliveMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpKeepaliveMsg.class)); - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - - int readLen = buf.writerIndex(); - testKeepaliveMsg = new byte[readLen]; - buf.readBytes(testKeepaliveMsg, 0, readLen); - - assertThat(testKeepaliveMsg, is(keepaliveMsg)); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java deleted file mode 100644 index 6dfa57ee..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.junit.Test; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.core.Is.is; - -/** - * Test for Notification message. - */ -public class BgpNotificationMsgTest { - - /** - * Notification message with error code, error subcode and data. - * - * @throws BgpParseException while decoding and encoding notification message - */ - @Test - public void bgpNotificationMessageTest1() throws BgpParseException { - byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, - 0x17, 0x03, 0x02, 0x02, - (byte) 0xfe, (byte) 0xb0}; - - byte[] testNotificationMsg = {0}; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(notificationMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message = null; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - assertThat(message, instanceOf(BgpNotificationMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - testNotificationMsg = buf.array(); - - int iReadLen = buf.writerIndex() - 0; - testNotificationMsg = new byte[iReadLen]; - buf.readBytes(testNotificationMsg, 0, iReadLen); - assertThat(testNotificationMsg, is(notificationMsg)); - } - - /** - * Notification message without data. - * - * @throws BgpParseException while decoding and encoding notification message - */ - @Test - public void bgpNotificationMessageTest2() throws BgpParseException { - byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, - 0x15, 0x03, 0x02, 0x00}; - - byte[] testNotificationMsg = {0}; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(notificationMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message = null; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - assertThat(message, instanceOf(BgpNotificationMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - testNotificationMsg = buf.array(); - - int iReadLen = buf.writerIndex() - 0; - testNotificationMsg = new byte[iReadLen]; - buf.readBytes(testNotificationMsg, 0, iReadLen); - assertThat(testNotificationMsg, is(notificationMsg)); - } - - //Negative scenarios - /** - * Notification message with wrong maker value. - * - * @throws BgpParseException while decoding and encoding notification message - */ - @Test(expected = BgpParseException.class) - public void bgpNotificationMessageTest3() throws BgpParseException { - byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - 0x01, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, - 0x15, 0x03, 0x02, 0x00}; - - byte[] testNotificationMsg = {0}; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(notificationMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message = null; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - assertThat(message, instanceOf(BgpNotificationMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - testNotificationMsg = buf.array(); - - int iReadLen = buf.writerIndex() - 0; - testNotificationMsg = new byte[iReadLen]; - buf.readBytes(testNotificationMsg, 0, iReadLen); - assertThat(testNotificationMsg, is(notificationMsg)); - } - - /** - * Notification message without error subcode. - * - * @throws BgpParseException while decoding and encoding notification message - */ - @Test(expected = BgpParseException.class) - public void bgpNotificationMessageTest4() throws BgpParseException { - byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, - 0x14, 0x03, 0x02}; - - byte[] testNotificationMsg = {0}; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(notificationMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message = null; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - assertThat(message, instanceOf(BgpNotificationMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - testNotificationMsg = buf.array(); - - int iReadLen = buf.writerIndex() - 0; - testNotificationMsg = new byte[iReadLen]; - buf.readBytes(testNotificationMsg, 0, iReadLen); - assertThat(testNotificationMsg, is(notificationMsg)); - } - - /** - * Notification message with wrong message length. - * - * @throws BgpParseException while decoding and encoding notification message - */ - @Test(expected = BgpParseException.class) - public void bgpNotificationMessageTest5() throws BgpParseException { - byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, - 0x14, 0x03, 0x02, 0x02}; - - byte[] testNotificationMsg = {0}; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(notificationMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message = null; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - assertThat(message, instanceOf(BgpNotificationMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - testNotificationMsg = buf.array(); - - int iReadLen = buf.writerIndex() - 0; - testNotificationMsg = new byte[iReadLen]; - buf.readBytes(testNotificationMsg, 0, iReadLen); - assertThat(testNotificationMsg, is(notificationMsg)); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java deleted file mode 100755 index 1fe4036f..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.junit.Test; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.types.BgpHeader; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.core.Is.is; - -/** - * Test cases for BGP Open Message. - */ -public class BgpOpenMsgTest { - - /** - * This test case checks open message without optional parameter. - */ - @Test - public void openMessageTest1() throws BgpParseException { - //Open message without optional parameter - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - 0x00, 0x1d, 0x01, 0X04, (byte) 0xfe, 0x09, 0x00, - (byte) 0xb4, (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, - 0x00}; - - byte[] testOpenMsg; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - - int readLen = buf.writerIndex(); - testOpenMsg = new byte[readLen]; - buf.readBytes(testOpenMsg, 0, readLen); - - assertThat(testOpenMsg, is(openMsg)); - } - - /** - * This test case checks open message with Multiprotocol extension - * capability. - */ - @Test - public void openMessageTest2() throws BgpParseException { - - // OPEN Message (MultiProtocolExtension-CAPABILITY). - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x25, - 0x01, //BGP Header - 0X04, //Version - (byte) 0x00, (byte) 0xc8, // AS Number - 0x00, (byte) 0xb4, // Hold time - (byte) 0xb6, (byte) 0x02, 0x5d, - (byte) 0xc8, // BGP Identifier - 0x08, 0x02, 0x06, // Opt Parameter length - 0x01, 0x04, 0x00, 0x00, 0x00, (byte) 0xc8}; // Multiprotocol CAPABILITY - - byte[] testOpenMsg; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - - int readLen = buf.writerIndex(); - testOpenMsg = new byte[readLen]; - buf.readBytes(testOpenMsg, 0, readLen); - - assertThat(testOpenMsg, is(openMsg)); - } - - /** - * This test case checks open message with Four-octet AS number - * capability. - */ - @Test - public void openMessageTest3() throws BgpParseException { - - // OPEN Message (Four-Octet AS number capability). - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x25, - 0x01, //BGPHeader - 0X04, //Version - (byte) 0x00, (byte) 0xc8, //AS Number - 0x00, (byte) 0xb4, //Hold Time - (byte) 0xb6, (byte) 0x02, 0x5d, - (byte) 0xc8, //BGP Identifier - 0x08, 0x02, 0x06, //Opt Parameter Length - 0x41, 0x04, 0x00, 0x01, 0x00, 0x01}; //Four Octet AS Number-CAPABILITY-TLV - - byte[] testOpenMsg; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - - int readLen = buf.writerIndex(); - testOpenMsg = new byte[readLen]; - buf.readBytes(testOpenMsg, 0, readLen); - - assertThat(testOpenMsg, is(openMsg)); - } - - /** - * This test case checks open message with capabilities. - */ - @Test - public void openMessageTest4() throws BgpParseException { - - // OPEN Message with capabilities. - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x2b, - 0x01, //BGPHeader - 0X04, //Version - (byte) 0x00, (byte) 0xc8, //AS Number - 0x00, (byte) 0xb4, //Hold Time - (byte) 0xb6, (byte) 0x02, 0x5d, (byte) 0xc8, //BGP Identifier - 0x0e, 0x02, 0x0c, //Opt Parameter Length - 0x01, 0x04, 0x00, 0x00, 0x00, (byte) 0xc8, // Multiprotocol extension capability - 0x41, 0x04, 0x00, 0x01, 0x00, 0x01}; //Four Octet AS Number-CAPABILITY-TLV - - byte[] testOpenMsg; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - message.writeTo(buf); - - int readLen = buf.writerIndex(); - testOpenMsg = new byte[readLen]; - buf.readBytes(testOpenMsg, 0, readLen); - - assertThat(testOpenMsg, is(openMsg)); - } - - /** - * In this test case, Invalid version is given as input and expecting - * an exception. - */ - @Test(expected = BgpParseException.class) - public void openMessageTest5() throws BgpParseException { - - // OPEN Message with invalid version number. - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x1d, 0x01, 0X05, - (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, - (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, - 0x00}; - - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - } - - /** - * In this test case, Marker is set as 0 in input and expecting - * an exception. - */ - @Test(expected = BgpParseException.class) - public void openMessageTest6() throws BgpParseException { - - // OPEN Message with marker set to 0. - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x00, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - 0x00, 0x00, 0x1d, 0x01, 0X04, - (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, - (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, - 0x00}; - - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - } - - /** - * In this test case, Invalid message length is given as input and expecting - * an exception. - */ - @Test(expected = BgpParseException.class) - public void openMessageTest7() throws BgpParseException { - - // OPEN Message with invalid header length. - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x1e, 0x01, 0X04, - (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, - (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, - 0x00}; - - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - } - - /** - * In this test case, Invalid message type is given as input and expecting - * an exception. - */ - @Test(expected = BgpParseException.class) - public void openMessageTest8() throws BgpParseException { - - // OPEN Message with invalid message type. - byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, 0x00, 0x1d, 0x05, 0X04, - (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, - (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, - 0x00}; - - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(openMsg); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - BgpMessage message; - BgpHeader bgpHeader = new BgpHeader(); - message = reader.readFrom(buffer, bgpHeader); - - assertThat(message, instanceOf(BgpOpenMsg.class)); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java deleted file mode 100644 index e11564ab..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for AreaID Tlv. - */ -public class AreaIdTest { - private final int value1 = 10; - private final int value2 = 20; - private final AreaIDTlv tlv1 = AreaIDTlv.of(value1); - private final AreaIDTlv sameAsTlv1 = AreaIDTlv.of(value1); - private final AreaIDTlv tlv2 = AreaIDTlv.of(value2); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java deleted file mode 100755 index 3ea56b64..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for As4Path BGP Path Attribute. - */ -public class As4PathTest { - //Two scenarios as4path set and sequence - private final List as4pathSet1 = new ArrayList<>(); - private final List as4pathSeq1 = new ArrayList<>(); - private final List as4pathSet2 = new ArrayList<>(); - private final List as4pathSeq2 = new ArrayList<>(); - private final As4Path attr1 = new As4Path(as4pathSet1, null); - private final As4Path sameAsAttr1 = new As4Path(as4pathSet1, null); - private final As4Path attr2 = new As4Path(as4pathSet2, null); - private final As4Path attr3 = new As4Path(null, as4pathSeq1); - private final As4Path sameAsAttr3 = new As4Path(null, as4pathSeq1); - private final As4Path attr4 = new As4Path(null, as4pathSeq2); - - @Test - public void basics() { - as4pathSet1.add(197358); - as4pathSet1.add(12883); - as4pathSet2.add(2008989); - as4pathSeq1.add(3009009); - as4pathSeq2.add(409900); - new EqualsTester() - .addEqualityGroup(attr1, sameAsAttr1) - .addEqualityGroup(attr2) - .addEqualityGroup(attr3, sameAsAttr3) - .addEqualityGroup(attr4) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java deleted file mode 100644 index e56ec5a5..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for AsPath BGP Path Attribute. - */ -public class AsPathTest { - //Two scenarios aspath set and sequence - private final List aspathSet1 = new ArrayList<>(); - private final List aspathSet2 = new ArrayList<>(); - private final List aspathSeq1 = new ArrayList<>(); - private final List aspathSeq2 = new ArrayList<>(); - private final AsPath attr1 = new AsPath(aspathSet1, null); - private final AsPath sameAsAttr1 = new AsPath(aspathSet1, null); - private final AsPath attr2 = new AsPath(aspathSet2, null); - private final AsPath attr3 = new AsPath(null, aspathSeq1); - private final AsPath sameAsAttr3 = new AsPath(null, aspathSeq1); - private final AsPath attr4 = new AsPath(null, aspathSeq2); - - @Test - public void basics() { - aspathSet1.add((short) 100); - aspathSet1.add((short) 300); - aspathSet2.add((short) 200); - aspathSeq2.add((short) 400); - aspathSeq1.add((short) 300); - new EqualsTester() - .addEqualityGroup(attr1, sameAsAttr1) - .addEqualityGroup(attr2) - .addEqualityGroup(attr3, sameAsAttr3) - .addEqualityGroup(attr4) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java deleted file mode 100644 index 1695583b..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for AutonomousSystem Tlv. - */ -public class AutonomousSystemTest { - private final int value1 = 101; - private final int value2 = 201; - private final AutonomousSystemTlv tlv1 = AutonomousSystemTlv.of(value1); - private final AutonomousSystemTlv sameAsTlv1 = AutonomousSystemTlv.of(value1); - private final AutonomousSystemTlv tlv2 = AutonomousSystemTlv.of(value2); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java deleted file mode 100644 index 59cf96fa..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGPLSIdentifier Tlv. - */ -public class BgpLSIdentifierTest { - private final int value1 = 8738; - private final int value2 = 13107; - private final BgpLSIdentifierTlv tlv1 = BgpLSIdentifierTlv.of(value1); - private final BgpLSIdentifierTlv sameAsTlv1 = new BgpLSIdentifierTlv(value1); - private final BgpLSIdentifierTlv tlv2 = new BgpLSIdentifierTlv(value2); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java deleted file mode 100644 index 7bea518a..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for IPReachabilityInformation Tlv. - */ -public class IPReachabilityInformationTest { - private final byte[] value1 = new byte[] {(byte) 0xc0, (byte) 0xa8, 0x4d, 0x01}; - private final byte[] value2 = new byte[] {(byte) 0xc0}; - private final IPReachabilityInformationTlv tlv1 = IPReachabilityInformationTlv.of((byte) 0x17, value1, (short) 4); - private final IPReachabilityInformationTlv sameAsTlv1 = IPReachabilityInformationTlv - .of((byte) 0x17, value1, (short) 4); - private final IPReachabilityInformationTlv tlv2 = IPReachabilityInformationTlv.of((byte) 0x05, value2, (short) 1); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java deleted file mode 100755 index fdb71189..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; -import org.onlab.packet.Ip4Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for IPv4Address Tlv. - */ -public class IPv4AddressTest { - private final Ip4Address value1 = Ip4Address.valueOf("127.0.0.1"); - private final Ip4Address value2 = Ip4Address.valueOf("127.0.0.1"); - private final IPv4AddressTlv tlv1 = IPv4AddressTlv.of(value1, (short) 259); - private final IPv4AddressTlv sameAsTlv1 = IPv4AddressTlv.of(value1, (short) 259); - private final IPv4AddressTlv tlv2 = IPv4AddressTlv.of(value2, (short) 260); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java deleted file mode 100644 index 781935b4..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; -import org.onlab.packet.Ip6Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for IPv6Address Tlv. - */ -public class IPv6AddressTest { - private final Ip6Address value1 = Ip6Address.valueOf("2001:db8:0:0:0:0:2:1"); - private final Ip6Address value2 = Ip6Address.valueOf("2001:db8:0:0:0:0:2:1"); - private final IPv6AddressTlv tlv1 = IPv6AddressTlv.of(value1, (short) 261); - private final IPv6AddressTlv sameAsTlv1 = IPv6AddressTlv.of(value1, (short) 261); - private final IPv6AddressTlv tlv2 = IPv6AddressTlv.of(value2, (short) 262); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java deleted file mode 100644 index 7ce4d5d3..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for IsIsNonPseudonode Tlv. - */ -public class IsIsNonPseudonodeTest { - private final byte[] value1 = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; - private final byte[] value2 = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x59}; - private final IsIsNonPseudonode tlv1 = IsIsNonPseudonode.of(value1); - private final IsIsNonPseudonode sameAsTlv1 = IsIsNonPseudonode.of(value1); - private final IsIsNonPseudonode tlv2 = IsIsNonPseudonode.of(value2); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java deleted file mode 100644 index a2a7c2b5..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for IsIsPseudonode Tlv. - */ -public class IsIsPseudonodeTest { - private final byte[] value1 = new byte[] {0x01, 0x02, 0x01, 0x02, 0x01, 0x02}; - private final byte[] value2 = new byte[] {0x01, 0x02, 0x01, 0x02, 0x01, 0x03}; - private final IsIsPseudonode tlv1 = IsIsPseudonode.of(value1, (byte) 1); - private final IsIsPseudonode sameAsTlv1 = IsIsPseudonode.of(value1, (byte) 1); - private final IsIsPseudonode tlv2 = IsIsPseudonode.of(value2, (byte) 1); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java deleted file mode 100644 index f1510b17..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for LinkLocalRemoteIdentifiers Tlv. - */ -public class LinkLocalRemoteIdentifiersTest { - private final int value1 = 0x12101010; - private final int value2 = 0x12101012; - private final LinkLocalRemoteIdentifiersTlv tlv1 = LinkLocalRemoteIdentifiersTlv.of(value1, value2); - private final LinkLocalRemoteIdentifiersTlv sameAsTlv1 = LinkLocalRemoteIdentifiersTlv.of(value1, value2); - private final LinkLocalRemoteIdentifiersTlv tlv2 = LinkLocalRemoteIdentifiersTlv.of(value2, value1); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java deleted file mode 100644 index 1bd34385..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for LocalPref BGP Path Attribute. - */ -public class LocalPrefTest { - private final int value1 = 800; - private final int value2 = 300; - private final LocalPref attr1 = new LocalPref(value1); - private final LocalPref sameAsAttr1 = new LocalPref(value1); - private final LocalPref attr2 = new LocalPref(value2); - - @Test - public void testEquality() { - new EqualsTester().addEqualityGroup(attr1, sameAsAttr1).addEqualityGroup(attr2).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java deleted file mode 100644 index 2ee5b33f..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for MED BGP Path Attribute. - */ -public class MedTest { - private final int value1 = 800; - private final int value2 = 200; - private final Med attr1 = new Med(value1); - private final Med sameAsAttr1 = new Med(value1); - private final Med attr2 = new Med(value2); - - @Test - public void testEquality() { - new EqualsTester().addEqualityGroup(attr1, sameAsAttr1).addEqualityGroup(attr2).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java deleted file mode 100755 index 799419a1..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; -import org.onlab.packet.Ip4Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for NextHop BGP Path Attribute. - */ -public class NextHopTest { - private final Ip4Address value1 = Ip4Address.valueOf("12.12.12.12"); - private final Ip4Address value2 = Ip4Address.valueOf("12.12.12.13"); - private final NextHop attr1 = new NextHop(value1); - private final NextHop sameAsAttr1 = new NextHop(value1); - private final NextHop attr2 = new NextHop(value2); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(attr1, sameAsAttr1) - .addEqualityGroup(attr2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java deleted file mode 100644 index da7b5570..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for Origin BGP Path Attribute. - */ -public class OriginTest { - private final byte value1 = 0x01; - private final byte value2 = 0x02; - private final Origin attr1 = new Origin(value1); - private final Origin sameAsAttr1 = new Origin(value1); - private final Origin attr2 = new Origin(value2); - - @Test - public void basics() { - new EqualsTester() - .addEqualityGroup(attr1, sameAsAttr1) - .addEqualityGroup(attr2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java deleted file mode 100644 index a8002311..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; -import org.onlab.packet.Ip4Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for OSPFPseudonode Tlv. - */ -public class OspfPseudonodeTest { - private final int value1 = 0xc3223409; - private final int value2 = 0xc3223406; - private final Ip4Address drInterface1 = Ip4Address.valueOf(0xaf91e01); - private final Ip4Address drInterface2 = Ip4Address.valueOf(0xaf91e02); - private final OSPFPseudonode tlv1 = OSPFPseudonode.of(value1, drInterface1); - private final OSPFPseudonode sameAsTlv1 = OSPFPseudonode.of(value1, drInterface1); - private final OSPFPseudonode tlv2 = OSPFPseudonode.of(value2, drInterface2); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java deleted file mode 100644 index 859bdbe5..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for OSPFRouteType Tlv. - */ -public class OspfRouteTypeTest { - private final byte value1 = 5; - private final byte value2 = 4; - private final OSPFRouteTypeTlv tlv1 = OSPFRouteTypeTlv.of(value1); - private final OSPFRouteTypeTlv sameAsTlv1 = OSPFRouteTypeTlv.of(value1); - private final OSPFRouteTypeTlv tlv2 = OSPFRouteTypeTlv.of(value2); - - @Test - public void testEquality() { - new EqualsTester() - .addEqualityGroup(tlv1, sameAsTlv1) - .addEqualityGroup(tlv2) - .testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java deleted file mode 100644 index 4efb7f5b..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP attribute node flag. - */ -public class BgpAttrNodeFlagBitTlvTest { - - private final boolean bOverloadBit = true; - private final boolean bAttachedBit = true; - private final boolean bExternalBit = true; - private final boolean bABRBit = true; - - private final boolean bOverloadBit1 = false; - private final boolean bAttachedBit1 = false; - private final boolean bExternalBit1 = false; - private final boolean bABRBit1 = false; - - private final BgpAttrNodeFlagBitTlv data = BgpAttrNodeFlagBitTlv - .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit); - private final BgpAttrNodeFlagBitTlv sameAsData = BgpAttrNodeFlagBitTlv - .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit); - private final BgpAttrNodeFlagBitTlv diffData = BgpAttrNodeFlagBitTlv - .of(bOverloadBit1, bAttachedBit1, bExternalBit1, bABRBit1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java deleted file mode 100644 index 16ca58ee..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; -import org.onlab.packet.Ip6Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP attribute node router ID. - */ -public class BgpAttrRouterIdV6Test { - - private final short sType = 1; - private final Ip6Address ip6RouterId = Ip6Address - .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001"); - - private final short sType1 = 2; - private final Ip6Address ip6RouterId1 = Ip6Address - .valueOf("2004:0db8:0a0b:12f0:0000:0000:0000:0004"); - - private final BgpAttrRouterIdV6 data = BgpAttrRouterIdV6.of(ip6RouterId, - sType); - private final BgpAttrRouterIdV6 sameAsData = BgpAttrRouterIdV6 - .of(ip6RouterId, sType); - private final BgpAttrRouterIdV6 diffData = BgpAttrRouterIdV6 - .of(ip6RouterId1, sType1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java deleted file mode 100644 index ef1cfcea..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP link IGP metric attribute. - */ -public class BgpLinkAttrIgpMetricTest { - private final int val = 0x010203; - private final int valLen = 3; - private final int val1 = 0x01020304; - private final int val1Len = 4; - - private final BgpLinkAttrIgpMetric data = BgpLinkAttrIgpMetric.of(val, - valLen); - private final BgpLinkAttrIgpMetric sameAsData = BgpLinkAttrIgpMetric - .of(val, valLen); - private final BgpLinkAttrIgpMetric diffData = BgpLinkAttrIgpMetric - .of(val1, val1Len); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java deleted file mode 100644 index 06fecc92..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP link max bandwidth attribute. - */ -public class BgpLinkAttrMaxLinkBandwidthTest { - private final float val = 0x010203; - private final short valLen = 3; - private final float val1 = 0x01020304; - private final short val1Len = 4; - - private final BgpLinkAttrMaxLinkBandwidth data = BgpLinkAttrMaxLinkBandwidth - .of(val, valLen); - private final BgpLinkAttrMaxLinkBandwidth sameAsData = BgpLinkAttrMaxLinkBandwidth - .of(val, valLen); - private final BgpLinkAttrMaxLinkBandwidth diffData = BgpLinkAttrMaxLinkBandwidth - .of(val1, val1Len); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java deleted file mode 100644 index c0d7f986..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for MPLS protocol mask attribute. - */ -public class BgpLinkAttrMplsProtocolMaskTest { - private final boolean val = true; - private final boolean val1 = false; - - private final BgpLinkAttrMplsProtocolMask data = BgpLinkAttrMplsProtocolMask - .of(val, val); - private final BgpLinkAttrMplsProtocolMask sameAsData = BgpLinkAttrMplsProtocolMask - .of(val, val); - private final BgpLinkAttrMplsProtocolMask diffData = BgpLinkAttrMplsProtocolMask - .of(val, val1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java deleted file mode 100644 index 45048527..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for Link attribute name Tlv. - */ -public class BgpLinkAttrNameTest { - private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; - private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; - - private final BgpLinkAttrName isisData = BgpLinkAttrName.of(array); - private final BgpLinkAttrName sameAsIsisData = BgpLinkAttrName.of(array); - private final BgpLinkAttrName isisDiff = BgpLinkAttrName.of(array1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java deleted file mode 100644 index 71d05f85..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for Opaque Link attribute Tlv. - */ -public class BgpLinkAttrOpaqLnkAttribTest { - private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; - private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; - - private final BgpLinkAttrOpaqLnkAttrib isisData = BgpLinkAttrOpaqLnkAttrib - .of(array); - private final BgpLinkAttrOpaqLnkAttrib sameAsIsisData = BgpLinkAttrOpaqLnkAttrib - .of(array); - private final BgpLinkAttrOpaqLnkAttrib isisDiff = BgpLinkAttrOpaqLnkAttrib - .of(array1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java deleted file mode 100644 index 2fb76352..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for MPLS protocol mask attribute. - */ -public class BgpLinkAttrProtectionTypeTest { - boolean bExtraTraffic = true; - boolean bUnprotected = true; - boolean bShared = true; - boolean bDedOneIstoOne = true; - boolean bDedOnePlusOne = true; - boolean bEnhanced = true; - - boolean bExtraTraffic1 = false; - boolean bUnprotected1 = false; - boolean bShared1 = false; - boolean bDedOneIstoOne1 = false; - boolean bDedOnePlusOne1 = false; - boolean bEnhanced1 = false; - - private final BgpLinkAttrProtectionType data = BgpLinkAttrProtectionType - .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne, - bDedOnePlusOne, bEnhanced); - private final BgpLinkAttrProtectionType sameAsData = BgpLinkAttrProtectionType - .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne, - bDedOnePlusOne, bEnhanced); - private final BgpLinkAttrProtectionType diffData = BgpLinkAttrProtectionType - .of(bExtraTraffic1, bUnprotected1, bShared1, bDedOneIstoOne1, - bDedOnePlusOne1, bEnhanced1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java deleted file mode 100644 index 9f3a7fad..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP link TE default metric attribute. - */ -public class BgpLinkAttrTeDefaultMetricTest { - private final int val = 0x010203; - private final int val1 = 0x01020304; - - private final BgpLinkAttrTeDefaultMetric data = BgpLinkAttrTeDefaultMetric - .of(val); - private final BgpLinkAttrTeDefaultMetric sameAsData = BgpLinkAttrTeDefaultMetric - .of(val); - private final BgpLinkAttrTeDefaultMetric diffData = BgpLinkAttrTeDefaultMetric - .of(val1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java deleted file mode 100644 index f1d2a1fa..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP unreserved bandwidth attribute. - */ -public class BgpLinkAttrUnRsrvdLinkBandwidthTest { - ArrayList maxUnResBandwidth = new ArrayList(); - ArrayList maxUnResBandwidth1 = new ArrayList(); - short sType = 10; - - private final BgpLinkAttrUnRsrvdLinkBandwidth isisData = BgpLinkAttrUnRsrvdLinkBandwidth - .of(maxUnResBandwidth, sType); - private final BgpLinkAttrUnRsrvdLinkBandwidth sameAsIsisData = BgpLinkAttrUnRsrvdLinkBandwidth - .of(maxUnResBandwidth, sType); - private final BgpLinkAttrUnRsrvdLinkBandwidth isisDiff = BgpLinkAttrUnRsrvdLinkBandwidth - .of(maxUnResBandwidth1, sType); - - @Test - public void basics() { - - maxUnResBandwidth.add(new Float(1)); - maxUnResBandwidth.add(new Float(2)); - maxUnResBandwidth.add(new Float(3)); - maxUnResBandwidth.add(new Float(4)); - - maxUnResBandwidth1.add(new Float(1)); - maxUnResBandwidth1.add(new Float(2)); - maxUnResBandwidth1.add(new Float(3)); - maxUnResBandwidth1.add(new Float(1)); - - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java deleted file mode 100644 index 535518f8..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP prefix IGP Flag attribute. - */ -public class BgpPrefixAttrIgpFlagsTest { - - private final boolean bisisUpDownBit = true; - private final boolean bOspfNoUnicastBit = true; - private final boolean bOspfLclAddrBit = true; - private final boolean bOspfNSSABit = true; - - private final boolean bisisUpDownBit1 = false; - private final boolean bOspfNoUnicastBit1 = false; - private final boolean bOspfLclAddrBit1 = false; - private final boolean bOspfNSSABit1 = false; - - private final BgpPrefixAttrIgpFlags data = BgpPrefixAttrIgpFlags - .of(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, - bOspfNSSABit); - private final BgpPrefixAttrIgpFlags sameAsData = BgpPrefixAttrIgpFlags - .of(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, - bOspfNSSABit); - private final BgpPrefixAttrIgpFlags diffData = BgpPrefixAttrIgpFlags - .of(bisisUpDownBit1, bOspfNoUnicastBit1, bOspfLclAddrBit1, - bOspfNSSABit1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java deleted file mode 100644 index fe6079fd..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP prefix metric attribute. - */ -public class BgpPrefixAttrMetricTest { - private final int val = 1111; - private final int val1 = 2222; - - private final BgpPrefixAttrMetric data = BgpPrefixAttrMetric.of(val); - private final BgpPrefixAttrMetric sameAsData = BgpPrefixAttrMetric.of(val); - private final BgpPrefixAttrMetric diffData = BgpPrefixAttrMetric.of(val1); - - @Test - public void basics() { - - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java deleted file mode 100644 index 17dafbb7..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for prefix attribute opaque data Tlv. - */ -public class BgpPrefixAttrOpaqueDataTest { - private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; - private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; - - private final BgpPrefixAttrOpaqueData isisData = BgpPrefixAttrOpaqueData - .of(array); - private final BgpPrefixAttrOpaqueData sameAsIsisData = BgpPrefixAttrOpaqueData - .of(array); - private final BgpPrefixAttrOpaqueData isisDiff = BgpPrefixAttrOpaqueData - .of(array1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java deleted file mode 100644 index f6fe39f8..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import org.junit.Test; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.Ip6Address; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP prefix metric attribute. - */ -public class BgpPrefixAttrOspfFwdAddrTest { - - private final short lsAttrLength = 4; - private final Ip4Address ip4RouterId = Ip4Address.valueOf("192.168.1.1"); - private final Ip6Address ip6RouterId = Ip6Address - .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001"); - - private final short lsAttrLength1 = 16; - private final Ip4Address ip4RouterId1 = Ip4Address.valueOf("192.168.1.2"); - private final Ip6Address ip6RouterId1 = Ip6Address - .valueOf("1002:0db8:0a0b:12f0:0000:0000:0000:0002"); - - private final BgpPrefixAttrOspfFwdAddr data = BgpPrefixAttrOspfFwdAddr - .of(lsAttrLength, ip4RouterId, ip6RouterId); - private final BgpPrefixAttrOspfFwdAddr sameAsData = BgpPrefixAttrOspfFwdAddr - .of(lsAttrLength, ip4RouterId, ip6RouterId); - private final BgpPrefixAttrOspfFwdAddr diffData = BgpPrefixAttrOspfFwdAddr - .of(lsAttrLength1, ip4RouterId1, ip6RouterId1); - - @Test - public void basics() { - new EqualsTester().addEqualityGroup(data, sameAsData) - .addEqualityGroup(diffData).testEquals(); - } -} diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java deleted file mode 100644 index 25ced61f..00000000 --- a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgpio.types.attr; - -import java.util.ArrayList; - -import org.junit.Test; - -import com.google.common.testing.EqualsTester; - -/** - * Test for BGP prefix route tag attribute. - */ -public class BgpPrefixAttrRouteTagTest { - ArrayList maxUnResBandwidth = new ArrayList(); - ArrayList maxUnResBandwidth1 = new ArrayList(); - - private final BgpPrefixAttrRouteTag isisData = BgpPrefixAttrRouteTag - .of(maxUnResBandwidth); - private final BgpPrefixAttrRouteTag sameAsIsisData = BgpPrefixAttrRouteTag - .of(maxUnResBandwidth); - private final BgpPrefixAttrRouteTag isisDiff = BgpPrefixAttrRouteTag - .of(maxUnResBandwidth1); - - @Test - public void basics() { - - maxUnResBandwidth.add(new Integer(1)); - maxUnResBandwidth.add(new Integer(2)); - maxUnResBandwidth.add(new Integer(3)); - maxUnResBandwidth.add(new Integer(4)); - - maxUnResBandwidth1.add(new Integer(1)); - maxUnResBandwidth1.add(new Integer(2)); - maxUnResBandwidth1.add(new Integer(3)); - maxUnResBandwidth1.add(new Integer(1)); - - new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) - .addEqualityGroup(isisDiff).testEquals(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/pom.xml b/framework/src/onos/bgp/ctl/pom.xml deleted file mode 100755 index 5cefd737..00000000 --- a/framework/src/onos/bgp/ctl/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - - org.onosproject - onos-bgp - 1.4.0-SNAPSHOT - ../pom.xml - - - onos-bgp-ctl - bundle - - ONOS BGP controller subsystem API - - - - org.onosproject - onos-bgp-api - - - io.netty - netty - - - org.apache.felix - org.apache.felix.scr.annotations - - - org.osgi - org.osgi.compendium - - - org.onosproject - onlab-misc - - - - - - - org.apache.felix - maven-scr-plugin - - - - - diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java deleted file mode 100644 index 9cbfbf65..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.util.Map; -import java.util.TreeMap; - -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Adj-RIB-In for each peer. - */ -public class AdjRibIn { - private Map nodeTree = new TreeMap<>(); - private Map linkTree = new TreeMap<>(); - private Map prefixTree = new TreeMap<>(); - - /** - * Returns the adjacency node. - * - * @return node adjacency RIB node - */ - public Map nodeTree() { - return nodeTree; - } - - /** - * Returns the adjacency link. - * - * @return link adjacency RIB node - */ - public Map linkTree() { - return linkTree; - } - - /** - * Returns the adjacency prefix. - * - * @return prefix adjacency RIB node - */ - public Map prefixTree() { - return prefixTree; - } - - /** - * Update nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. - * - * @param nlri NLRI Info - * @param details has pathattribute , protocolID and identifier - */ - public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { - if (nlri instanceof BgpNodeLSNlriVer4) { - BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); - if (nodeTree.containsKey(nodeLSIdentifier)) { - nodeTree.replace(nodeLSIdentifier, details); - } else { - nodeTree.put(nodeLSIdentifier, details); - } - } else if (nlri instanceof BgpLinkLsNlriVer4) { - BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); - if (linkTree.containsKey(linkLSIdentifier)) { - linkTree.replace(linkLSIdentifier, details); - } else { - linkTree.put(linkLSIdentifier, details); - } - } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { - BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); - if (prefixTree.containsKey(prefixIdentifier)) { - prefixTree.replace(prefixIdentifier, details); - } else { - prefixTree.put(prefixIdentifier, details); - } - } - } - - /** - * Removes nlri identifier if it exists in the adjacency tree. - * - * @param nlri NLRI Info - */ - public void remove(BgpLSNlri nlri) { - if (nlri instanceof BgpNodeLSNlriVer4) { - BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); - if (nodeTree.containsKey(nodeLSIdentifier)) { - nodeTree.remove(nodeLSIdentifier); - } - } else if (nlri instanceof BgpLinkLsNlriVer4) { - BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); - if (linkTree.containsKey(linkLSIdentifier)) { - linkTree.remove(linkLSIdentifier); - } - } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { - BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); - if (prefixTree.containsKey(prefixIdentifier)) { - prefixTree.remove(prefixIdentifier); - } - } - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues() - .add("nodeTree", nodeTree) - .add("linkTree", linkTree) - .add("prefixTree", prefixTree) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java deleted file mode 100755 index 8754563d..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java +++ /dev/null @@ -1,911 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.nio.channels.ClosedChannelException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.concurrent.RejectedExecutionException; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; -import org.jboss.netty.handler.timeout.ReadTimeoutException; -import org.jboss.netty.handler.timeout.ReadTimeoutHandler; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.IpAddress; -import org.onosproject.bgp.controller.BgpCfg; -import org.onosproject.bgp.controller.BgpController; -import org.onosproject.bgp.controller.BgpId; -import org.onosproject.bgp.controller.BgpPeer; -import org.onosproject.bgp.controller.BgpPeerCfg; -import org.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpFactory; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onosproject.bgpio.protocol.BgpOpenMsg; -import org.onosproject.bgpio.protocol.BgpType; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.onosproject.bgpio.types.BgpErrorType; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; -import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Channel handler deals with the bgp peer connection and dispatches messages from peer to the appropriate locations. - */ -class BgpChannelHandler extends IdleStateAwareChannelHandler { - - private static final Logger log = LoggerFactory.getLogger(BgpChannelHandler.class); - static final int BGP_MIN_HOLDTIME = 3; - static final int BGP_MAX_KEEPALIVE_INTERVAL = 3; - private BgpPeer bgpPeer; - private BgpId thisbgpId; - private Channel channel; - private BgpKeepAliveTimer keepAliveTimer = null; - private short peerHoldTime = 0; - private short negotiatedHoldTime = 0; - private long peerAsNum; - private int peerIdentifier; - private BgpPacketStatsImpl bgpPacketStats; - static final int MAX_WRONG_COUNT_PACKET = 5; - static final byte MULTI_PROTOCOL_EXTN_CAPA_TYPE = 1; - static final byte FOUR_OCTET_AS_NUM_CAPA_TYPE = 65; - static final int AS_TRANS = 23456; - static final int MAX_AS2_NUM = 65535; - static final short AFI = 16388; - static final byte RES = 0; - static final byte SAFI = 71; - - // State needs to be volatile because the HandshakeTimeoutHandler - // needs to check if the handshake is complete - private volatile ChannelState state; - - // When a bgp peer with a ip addresss is found (i.e we already have a - // connected peer with the same ip), the new peer is immediately - // disconnected. At that point netty callsback channelDisconnected() which - // proceeds to cleaup peer state - we need to ensure that it does not - // cleanup - // peer state for the older (still connected) peer - private volatile Boolean duplicateBGPIdFound; - // Indicates the bgp version used by this bgp peer - protected BgpVersion bgpVersion; - private BgpController bgpController; - protected BgpFactory factory4; - private boolean isIbgpSession; - private BgpSessionInfoImpl sessionInfo; - private BgpPeerManagerImpl peerManager; - private InetSocketAddress inetAddress; - private IpAddress ipAddress; - private SocketAddress address; - private String peerAddr; - private BgpCfg bgpconfig; - - /** - * Create a new unconnected BGPChannelHandler. - * - * @param bgpController bgp controller - */ - BgpChannelHandler(BgpController bgpController) { - this.bgpController = bgpController; - this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager(); - this.state = ChannelState.IDLE; - this.factory4 = Controller.getBgpMessageFactory4(); - this.duplicateBGPIdFound = Boolean.FALSE; - this.bgpPacketStats = new BgpPacketStatsImpl(); - this.bgpconfig = bgpController.getConfig(); - } - - // To disconnect peer session. - public void disconnectPeer() { - bgpPeer.disconnectPeer(); - } - - // ************************* - // Channel State Machine - // ************************* - - /** - * The state machine for handling the peer/channel state. All state transitions should happen from within the state - * machine (and not from other parts of the code) - */ - enum ChannelState { - /** - * Initial state before channel is connected. - */ - IDLE(false) { - - }, - - OPENSENT(false) { - @Override - void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { - log.debug("message received in OPENSENT state"); - // check for OPEN message - if (m.getType() != BgpType.OPEN) { - // When the message type is not keep alive message increment the wrong packet statistics - h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, - BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, - m.getType().getType()); - log.debug("Message is not OPEN message"); - } else { - log.debug("Sending keep alive message in OPENSENT state"); - h.bgpPacketStats.addInPacket(); - - BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; - h.peerIdentifier = pOpenmsg.getBgpId(); - - // validate capabilities and open msg - if (h.openMsgValidation(h, pOpenmsg)) { - if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENCONFIRM, - h.peerIdentifier, h.peerAddr)) { - h.channel.close(); - return; - } - log.debug("Sending handshake OPEN message"); - - /* - * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the - * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time - * received in the OPEN message - */ - h.peerHoldTime = pOpenmsg.getHoldTime(); - if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { - h.channel.getPipeline().replace("holdTime", - "holdTime", - new ReadTimeoutHandler(BgpPipelineFactory.TIMER, - h.peerHoldTime)); - } - - log.info("Hold Time : " + h.peerHoldTime); - - // update AS number - h.peerAsNum = pOpenmsg.getAsNumber(); - } - - // Send keepalive message to peer. - h.sendKeepAliveMessage(); - h.bgpPacketStats.addOutPacket(); - h.setState(OPENCONFIRM); - h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); - } - } - }, - - OPENWAIT(false) { - @Override - void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { - log.debug("Message received in OPEN WAIT State"); - - // check for open message - if (m.getType() != BgpType.OPEN) { - // When the message type is not open message increment the wrong packet statistics - h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, BgpErrorType.UNSPECIFIED_ERROR, - m.getType().getType()); - log.debug("Message is not OPEN message"); - } else { - h.bgpPacketStats.addInPacket(); - - BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; - h.peerIdentifier = pOpenmsg.getBgpId(); - - // Validate open message - if (h.openMsgValidation(h, pOpenmsg)) { - if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENSENT, - h.peerIdentifier, h.peerAddr)) { - h.channel.close(); - return; - } - log.debug("Sending handshake OPEN message"); - - /* - * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the - * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time - * received in the OPEN message - */ - h.peerHoldTime = pOpenmsg.getHoldTime(); - if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { - h.channel.getPipeline().replace("holdTime", - "holdTime", - new ReadTimeoutHandler(BgpPipelineFactory.TIMER, - h.peerHoldTime)); - } - - log.debug("Hold Time : " + h.peerHoldTime); - - // update AS number - h.peerAsNum = pOpenmsg.getAsNumber(); - - h.sendHandshakeOpenMessage(); - h.bgpPacketStats.addOutPacket(); - h.setState(OPENCONFIRM); - h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); - } - } - } - }, - - OPENCONFIRM(false) { - @Override - void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { - log.debug("Message received in OPENCONFIRM state"); - // check for keep alive message - if (m.getType() != BgpType.KEEP_ALIVE) { - // When the message type is not keep alive message handle the wrong packet - h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, - BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, - m.getType().getType()); - log.debug("Message is not KEEPALIVE message"); - } else { - - // Set the peer connected status - h.bgpPacketStats.addInPacket(); - log.debug("Sending keep alive message in OPENCONFIRM state"); - - final InetSocketAddress inetAddress = (InetSocketAddress) h.address; - h.thisbgpId = BgpId.bgpId(IpAddress.valueOf(inetAddress.getAddress())); - - // set session parameters - h.negotiatedHoldTime = (h.peerHoldTime < h.bgpconfig.getHoldTime()) ? h.peerHoldTime - : h.bgpconfig.getHoldTime(); - h.sessionInfo = new BgpSessionInfoImpl(h.thisbgpId, h.bgpVersion, h.peerAsNum, h.peerHoldTime, - h.peerIdentifier, h.negotiatedHoldTime, h.isIbgpSession); - - h.bgpPeer = h.peerManager.getBgpPeerInstance(h.bgpController, h.sessionInfo, h.bgpPacketStats); - // set the status of bgp as connected - h.bgpPeer.setConnected(true); - h.bgpPeer.setChannel(h.channel); - - /* - * RFC 4271, When an OPEN message is received, sends a KEEPALIVE message, If the negotiated hold - * time value is zero, then the HoldTimer and KeepaliveTimer are not started. A reasonable maximum - * time between KEEPALIVE messages would be one third of the Hold Time interval. - */ - - if (h.negotiatedHoldTime != 0) { - h.keepAliveTimer = new BgpKeepAliveTimer(h, - (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); - } else { - h.sendKeepAliveMessage(); - } - - h.bgpPacketStats.addOutPacket(); - - // set the state handshake completion. - h.setHandshakeComplete(true); - - if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) { - disconnectDuplicate(h); - } else { - h.setState(ESTABLISHED); - h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.ESTABLISHED); - } - } - } - }, - - ESTABLISHED(true) { - @Override - void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { - log.debug("Message received in established state " + m.getType()); - // dispatch the message - h.dispatchMessage(m); - } - }; - - private boolean handshakeComplete; - - ChannelState(boolean handshakeComplete) { - this.handshakeComplete = handshakeComplete; - } - - /** - * Is this a state in which the handshake has completed? - * - * @return true if the handshake is complete - */ - public boolean isHandshakeComplete() { - return this.handshakeComplete; - } - - /** - * Disconnect duplicate peer connection. - * - * @param h channel handler - */ - protected void disconnectDuplicate(BgpChannelHandler h) { - log.error("Duplicated BGP IP or incompleted cleanup - " + "" + "disconnecting channel {}", - h.getPeerInfoString()); - h.duplicateBGPIdFound = Boolean.TRUE; - h.channel.disconnect(); - } - - // set handshake completion status - public void setHandshakeComplete(boolean handshakeComplete) { - this.handshakeComplete = handshakeComplete; - } - - void processBgpMessage(BgpChannelHandler bgpChannelHandler, BgpMessage pm) - throws IOException, BgpParseException { - // TODO Auto-generated method stub - log.debug("BGP message stub"); - } - - } - - // ************************* - // Channel handler methods - // ************************* - - @Override - public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - - channel = e.getChannel(); - log.info("BGP connected from {}", channel.getRemoteAddress()); - - address = channel.getRemoteAddress(); - if (!(address instanceof InetSocketAddress)) { - throw new IOException("Invalid peer connection."); - } - - // Connection should establish only if local ip and Autonomous system number is configured. - if (bgpconfig.getState() != BgpCfg.State.IP_AS_CONFIGURED) { - sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_REJECTED, null); - channel.close(); - log.info("BGP local AS and router ID not configured"); - return; - } - - inetAddress = (InetSocketAddress) address; - peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); - - // if peer is not configured disconnect session - if (!bgpconfig.isPeerConfigured(peerAddr)) { - log.debug("Peer is not configured {}", peerAddr); - sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_REJECTED, null); - channel.close(); - return; - } - - // if connection is already established close channel - if (peerManager.isPeerConnected(BgpId.bgpId(IpAddress.valueOf(peerAddr)))) { - log.debug("Duplicate connection received, peer {}", peerAddr); - channel.close(); - return; - } - - if (null != channel.getPipeline().get("PassiveHandler")) { - log.info("BGP handle connection request from peer"); - // Wait for open message from bgp peer - setState(ChannelState.OPENWAIT); - } else if (null != channel.getPipeline().get("ActiveHandler")) { - log.info("BGP handle connection response from peer"); - - sendHandshakeOpenMessage(); - bgpPacketStats.addOutPacket(); - setState(ChannelState.OPENSENT); - bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.OPENSENT); - } - } - - @Override - public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - - channel = e.getChannel(); - log.info("BGP disconnected callback for bgp:{}. Cleaning up ...", getPeerInfoString()); - - address = channel.getRemoteAddress(); - if (!(address instanceof InetSocketAddress)) { - throw new IOException("Invalid peer connection."); - } - - inetAddress = (InetSocketAddress) address; - peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); - - if (thisbgpId != null) { - if (!duplicateBGPIdFound) { - // if the disconnected peer (on this ChannelHandler) - // was not one with a duplicate, it is safe to remove all - // state for it at the controller. Notice that if the disconnected - // peer was a duplicate-ip, calling the method below would clear - // all state for the original peer (with the same ip), - // which we obviously don't want. - log.debug("{}:removal called", getPeerInfoString()); - if (bgpPeer != null) { - peerManager.removeConnectedPeer(thisbgpId); - } - - // Retry connection if connection is lost to bgp speaker/peer - if ((channel != null) && (null != channel.getPipeline().get("ActiveHandler"))) { - BgpConnectPeerImpl connectPeer; - BgpPeerCfg.State peerCfgState; - - peerCfgState = bgpconfig.getPeerConnState(peerAddr); - // on session disconnect using configuration, do not retry - if (!peerCfgState.equals(BgpPeerCfg.State.IDLE)) { - log.debug("Connection reset by peer, retry, STATE:{}", peerCfgState); - BgpPeerConfig peerConfig = (BgpPeerConfig) bgpconfig.displayPeers(peerAddr); - - bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); - connectPeer = new BgpConnectPeerImpl(bgpController, peerAddr, Controller.getBgpPortNum()); - peerConfig.setConnectPeer(connectPeer); - } - } else { - bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); - } - } else { - // A duplicate was disconnected on this ChannelHandler, - // this is the same peer reconnecting, but the original state was - // not cleaned up - XXX check liveness of original ChannelHandler - log.debug("{}:duplicate found", getPeerInfoString()); - duplicateBGPIdFound = Boolean.FALSE; - } - - if (null != keepAliveTimer) { - keepAliveTimer.getKeepAliveTimer().cancel(); - } - } else { - bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); - log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString()); - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { - - log.info("[exceptionCaught]: " + e.toString()); - - if (e.getCause() instanceof ReadTimeoutException) { - if ((ChannelState.OPENWAIT == state) || (ChannelState.OPENSENT == state)) { - - // When ReadTimeout timer is expired in OPENWAIT/OPENSENT state, it is considered - sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); - channel.close(); - state = ChannelState.IDLE; - return; - } else if (ChannelState.OPENCONFIRM == state) { - - // When ReadTimeout timer is expired in OPENCONFIRM state. - sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); - channel.close(); - state = ChannelState.IDLE; - return; - } - } else if (e.getCause() instanceof ClosedChannelException) { - log.debug("Channel for bgp {} already closed", getPeerInfoString()); - } else if (e.getCause() instanceof IOException) { - log.error("Disconnecting peer {} due to IO Error: {}", getPeerInfoString(), e.getCause().getMessage()); - if (log.isDebugEnabled()) { - // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); - } - channel.close(); - } else if (e.getCause() instanceof BgpParseException) { - byte[] data = new byte[] {}; - BgpParseException errMsg = (BgpParseException) e.getCause(); - byte errorCode = errMsg.getErrorCode(); - byte errorSubCode = errMsg.getErrorSubCode(); - ChannelBuffer tempCb = errMsg.getData(); - if (tempCb != null) { - int dataLength = tempCb.capacity(); - data = new byte[dataLength]; - tempCb.readBytes(data, 0, dataLength); - } - sendNotification(errorCode, errorSubCode, data); - } else if (e.getCause() instanceof RejectedExecutionException) { - log.warn("Could not process message: queue full"); - } else { - log.error("Error while processing message from peer " + getPeerInfoString() + "state " + this.state); - channel.close(); - } - } - - @Override - public String toString() { - return getPeerInfoString(); - } - - @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - if (e.getMessage() instanceof List) { - @SuppressWarnings("Unchecked") - List msglist = (List) e.getMessage(); - for (BgpMessage pm : msglist) { - // Do the actual packet processing - state.processBgpMessage(this, pm); - } - } else { - state.processBgpMessage(this, (BgpMessage) e.getMessage()); - } - } - - /** - * Check for connection collision. - * - * @param state connection state - * @param peerIdentifier BGP peer identifier - * @param peerAddr BGP peer address - * @return true if bgp spreakers initiated connection - * @throws BgpParseException on error while procession collision detection - * @throws IOException on error while procession collision detection - */ - public boolean connectionCollisionDetection(BgpPeerCfg.State state, int peerIdentifier, String peerAddr) - throws IOException, BgpParseException { - /* - * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established for detecting - * which BGP connection is to be preserved when a collision occurs. The convention is to compare the BGP - * Identifiers of the peers involved in the collision and to retain only the connection initiated by the BGP - * speaker with the higher-valued BGP Identifier.. - */ - BgpPeerCfg.State currentState = bgpconfig.getPeerConnState(peerAddr); - if (currentState.equals(state)) { - if (((Ip4Address.valueOf(bgpconfig.getRouterId())).compareTo(Ip4Address.valueOf(peerIdentifier))) > 0) { - // send notification - sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_COLLISION_RESOLUTION, null); - log.debug("Connection collision detected, local id: {}, peer id: {}, peer state:{}, in state:{}", - (Ip4Address.valueOf(bgpconfig.getRouterId())), (Ip4Address.valueOf(peerIdentifier)), - currentState, state); - return true; - } - } - - return false; - } - - // ************************* - // Channel utility methods - // ************************* - /** - * Set handshake status. - * - * @param handshakeComplete handshake complete status - */ - public void setHandshakeComplete(boolean handshakeComplete) { - this.state.setHandshakeComplete(handshakeComplete); - } - - /** - * Is this a state in which the handshake has completed? - * - * @return true if the handshake is complete - */ - public boolean isHandshakeComplete() { - return state.isHandshakeComplete(); - } - - /** - * To handle the BGP message. - * - * @param m bgp message - * @throws BgpParseException throw exception - */ - private void dispatchMessage(BgpMessage m) throws BgpParseException { - bgpPacketStats.addInPacket(); - bgpController.processBGPPacket(thisbgpId, m); - } - - /** - * Return a string describing this peer based on the already available information (ip address and/or remote - * socket). - * - * @return display string - */ - private String getPeerInfoString() { - if (bgpPeer != null) { - return bgpPeer.toString(); - } - String channelString; - if (channel == null || channel.getRemoteAddress() == null) { - channelString = "?"; - } else { - channelString = channel.getRemoteAddress().toString(); - } - String bgpIpString; - // TODO: implement functionality to get bgp id string - bgpIpString = "?"; - return String.format("[%s BGP-IP[%s]]", channelString, bgpIpString); - } - - /** - * Update the channels state. Only called from the state machine. TODO: enforce restricted state transitions - * - * @param state - */ - private void setState(ChannelState state) { - this.state = state; - } - - /** - * get packet statistics. - * - * @return packet statistics - */ - public BgpPacketStatsImpl getBgpPacketStats() { - return bgpPacketStats; - } - - /** - * Send handshake open message to the peer. - * - * @throws IOException, BgpParseException - */ - private void sendHandshakeOpenMessage() throws IOException, BgpParseException { - int bgpId; - - bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt(); - BgpMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber()) - .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId).setLsCapabilityTlv(bgpconfig.getLsCapability()) - .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()).build(); - log.debug("Sending open message to {}", channel.getRemoteAddress()); - channel.write(Collections.singletonList(msg)); - - } - - /** - * Send notification message to peer. - * - * @param errorCode error code send in notification - * @param errorSubCode sub error code send in notification - * @param data data to send in notification - * @throws IOException, BgpParseException while building message - */ - private void sendNotification(byte errorCode, byte errorSubCode, byte[] data) - throws IOException, BgpParseException { - BgpMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode) - .setErrorSubCode(errorSubCode).setData(data).build(); - log.debug("Sending notification message to {}", channel.getRemoteAddress()); - channel.write(Collections.singletonList(msg)); - } - - /** - * Send keep alive message. - * - * @throws IOException when channel is disconnected - * @throws BgpParseException while building keep alive message - */ - synchronized void sendKeepAliveMessage() throws IOException, BgpParseException { - - BgpMessage msg = factory4.keepaliveMessageBuilder().build(); - log.debug("Sending keepalive message to {}", channel.getRemoteAddress()); - channel.write(Collections.singletonList(msg)); - } - - /** - * Process unknown BGP message received. - * - * @param errorCode error code - * @param errorSubCode error sub code - * @param data message type - * @throws BgpParseException while processing error messsage - * @throws IOException while processing error message - */ - public void processUnknownMsg(byte errorCode, byte errorSubCode, byte data) throws BgpParseException, IOException { - log.debug("UNKNOWN message received"); - byte[] byteArray = new byte[1]; - byteArray[0] = data; - sendNotification(errorCode, errorSubCode, byteArray); - channel.close(); - } - - /** - * BGP open message validation. - * - * @param h channel handler - * @param openMsg open message - * @return true if valid message, otherwise false - * @throws BgpParseException throw exception - */ - public boolean openMsgValidation(BgpChannelHandler h, BgpOpenMsg openMsg) throws BgpParseException { - boolean result; - - // Validate BGP ID - result = bgpIdValidation(openMsg); - if (!result) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_BGP_IDENTIFIER, null); - } - - // Validate AS number - result = asNumberValidation(h, openMsg); - if (!result) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); - } - - // Validate hold timer - if ((openMsg.getHoldTime() != 0) && (openMsg.getHoldTime() < BGP_MIN_HOLDTIME)) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNACCEPTABLE_HOLD_TIME, null); - } - - // Validate capabilities - result = capabilityValidation(h, openMsg); - return result; - } - - /** - * Capability Validation. - * - * @param h channel handler - * @param openmsg open message - * @return success or failure - * @throws BgpParseException - */ - private boolean capabilityValidation(BgpChannelHandler h, BgpOpenMsg openmsg) throws BgpParseException { - log.debug("capabilityValidation"); - - boolean isMultiProtocolcapabilityExists = false; - boolean isFourOctetCapabilityExits = false; - int capAsNum = 0; - - List capabilityTlv = openmsg.getCapabilityTlv(); - ListIterator listIterator = capabilityTlv.listIterator(); - List unSupportedCapabilityTlv = new LinkedList<>(); - ListIterator unSupportedCaplistIterator = unSupportedCapabilityTlv.listIterator(); - BgpValueType tempTlv; - boolean isLargeAsCapabilityCfg = h.bgpconfig.getLargeASCapability(); - boolean isLsCapabilityCfg = h.bgpconfig.getLsCapability(); - - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - if (tlv.getType() == MULTI_PROTOCOL_EXTN_CAPA_TYPE) { - isMultiProtocolcapabilityExists = true; - } - if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { - isFourOctetCapabilityExits = true; - capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); - } - } - - if (isFourOctetCapabilityExits) { - if (capAsNum > MAX_AS2_NUM) { - if (openmsg.getAsNumber() != AS_TRANS) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); - } - } else { - if (capAsNum != openmsg.getAsNumber()) { - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); - } - } - } - - if ((isLsCapabilityCfg)) { - if (!isMultiProtocolcapabilityExists) { - tempTlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI); - unSupportedCapabilityTlv.add(tempTlv); - } - } - - if ((isLargeAsCapabilityCfg)) { - if (!isFourOctetCapabilityExits) { - tempTlv = new FourOctetAsNumCapabilityTlv(h.bgpconfig.getAsNumber()); - unSupportedCapabilityTlv.add(tempTlv); - } - } - - if (unSupportedCaplistIterator.hasNext()) { - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - while (unSupportedCaplistIterator.hasNext()) { - BgpValueType tlv = unSupportedCaplistIterator.next(); - tlv.write(buffer); - } - throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNSUPPORTED_CAPABILITY, buffer); - } else { - return true; - } - } - - /** - * AS Number Validation. - * - * @param h channel Handler - * @param openMsg open message - * @return true or false - */ - private boolean asNumberValidation(BgpChannelHandler h, BgpOpenMsg openMsg) { - log.debug("AS Num validation"); - - int capAsNum = 0; - boolean isFourOctetCapabilityExits = false; - - BgpPeerCfg peerCfg = h.bgpconfig.displayPeers(peerAddr); - List capabilityTlv = openMsg.getCapabilityTlv(); - ListIterator listIterator = capabilityTlv.listIterator(); - - while (listIterator.hasNext()) { - BgpValueType tlv = listIterator.next(); - if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { - isFourOctetCapabilityExits = true; - capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); - } - } - - if (peerCfg.getAsNumber() > MAX_AS2_NUM) { - if (openMsg.getAsNumber() != AS_TRANS) { - return false; - } - - if (!isFourOctetCapabilityExits) { - return false; - } - - if (peerCfg.getAsNumber() != capAsNum) { - return false; - } - - isIbgpSession = peerCfg.getIsIBgp(); - if (isIbgpSession) { - // IBGP - AS number should be same for Peer and local if it is IBGP - if (h.bgpconfig.getAsNumber() != capAsNum) { - return false; - } - } - } else { - - if (openMsg.getAsNumber() != peerCfg.getAsNumber()) { - return false; - } - - if (isFourOctetCapabilityExits) { - if (capAsNum != peerCfg.getAsNumber()) { - return false; - } - } - - isIbgpSession = peerCfg.getIsIBgp(); - if (isIbgpSession) { - // IBGP - AS number should be same for Peer and local if it is IBGP - if (openMsg.getAsNumber() != h.bgpconfig.getAsNumber()) { - return false; - } - } - } - return true; - } - - /** - * Validates BGP ID. - * - * @param openMsg open message - * @return true or false - */ - private boolean bgpIdValidation(BgpOpenMsg openMsg) { - String openMsgBgpId = Ip4Address.valueOf(openMsg.getBgpId()).toString(); - - InetAddress ipAddress; - try { - ipAddress = InetAddress.getByName(openMsgBgpId); - if (ipAddress.isMulticastAddress()) { - return false; - } - } catch (UnknownHostException e) { - log.debug("InetAddress convertion failed"); - } - return true; - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java deleted file mode 100755 index 716cc0c5..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; - -import org.onlab.packet.Ip4Address; -import org.onosproject.bgp.controller.BgpCfg; -import org.onosproject.bgp.controller.BgpPeerCfg; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides BGP configuration of this BGP speaker. - */ -public class BgpConfig implements BgpCfg { - - protected static final Logger log = LoggerFactory.getLogger(BgpConfig.class); - - private static final short DEFAULT_HOLD_TIMER = 120; - private static final short DEFAULT_CONN_RETRY_TIME = 120; - private static final short DEFAULT_CONN_RETRY_COUNT = 5; - - private State state = State.INIT; - private int localAs; - private int maxSession; - private boolean lsCapability; - private short holdTime; - private boolean largeAs = false; - private int maxConnRetryTime; - private int maxConnRetryCount; - - private Ip4Address routerId = null; - private TreeMap bgpPeerTree = new TreeMap<>(); - - /** - * Constructor to initialize the values. - */ - public BgpConfig() { - - this.holdTime = DEFAULT_HOLD_TIMER; - this.maxConnRetryTime = DEFAULT_CONN_RETRY_TIME; - this.maxConnRetryCount = DEFAULT_CONN_RETRY_COUNT; - } - - @Override - public State getState() { - return state; - } - - @Override - public void setState(State state) { - this.state = state; - } - - @Override - public int getAsNumber() { - return this.localAs; - } - - @Override - public void setAsNumber(int localAs) { - - State localState = getState(); - this.localAs = localAs; - - /* Set configuration state */ - if (localState == State.IP_CONFIGURED) { - setState(State.IP_AS_CONFIGURED); - } else { - setState(State.AS_CONFIGURED); - } - } - - @Override - public int getMaxSession() { - return this.maxSession; - } - - @Override - public void setMaxSession(int maxSession) { - this.maxSession = maxSession; - } - - @Override - public boolean getLsCapability() { - return this.lsCapability; - } - - @Override - public void setLsCapability(boolean lsCapability) { - this.lsCapability = lsCapability; - } - - @Override - public String getRouterId() { - if (this.routerId != null) { - return this.routerId.toString(); - } else { - return null; - } - } - - @Override - public void setRouterId(String routerId) { - State localState = getState(); - this.routerId = Ip4Address.valueOf(routerId); - - /* Set configuration state */ - if (localState == State.AS_CONFIGURED) { - setState(State.IP_AS_CONFIGURED); - } else { - setState(State.IP_CONFIGURED); - } - } - - @Override - public boolean addPeer(String routerid, int remoteAs) { - return addPeer(routerid, remoteAs, DEFAULT_HOLD_TIMER); - } - - @Override - public boolean addPeer(String routerid, short holdTime) { - return addPeer(routerid, this.getAsNumber(), holdTime); - } - - @Override - public boolean addPeer(String routerid, int remoteAs, short holdTime) { - BgpPeerConfig lspeer = new BgpPeerConfig(); - if (this.bgpPeerTree.get(routerid) == null) { - - lspeer.setPeerRouterId(routerid); - lspeer.setAsNumber(remoteAs); - lspeer.setHoldtime(holdTime); - lspeer.setState(BgpPeerCfg.State.IDLE); - lspeer.setSelfInnitConnection(false); - - if (this.getAsNumber() == remoteAs) { - lspeer.setIsIBgp(true); - } else { - lspeer.setIsIBgp(false); - } - - this.bgpPeerTree.put(routerid, lspeer); - log.debug("added successfully"); - return true; - } else { - log.debug("already exists"); - return false; - } - } - - @Override - public boolean connectPeer(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if (lspeer != null) { - lspeer.setSelfInnitConnection(true); - // TODO: initiate peer connection - return true; - } - - return false; - } - - @Override - public boolean removePeer(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if (lspeer != null) { - - //TODO DISCONNECT PEER - disconnectPeer(routerid); - lspeer.setSelfInnitConnection(false); - lspeer = this.bgpPeerTree.remove(routerid); - log.debug("Deleted : " + routerid + " successfully"); - - return true; - } else { - log.debug("Did not find : " + routerid); - return false; - } - } - - @Override - public boolean disconnectPeer(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if (lspeer != null) { - - //TODO DISCONNECT PEER - lspeer.setState(BgpPeerCfg.State.IDLE); - lspeer.setSelfInnitConnection(false); - log.debug("Disconnected : " + routerid + " successfully"); - - return true; - } else { - log.debug("Did not find : " + routerid); - return false; - } - } - - @Override - public void setPeerConnState(String routerid, BgpPeerCfg.State state) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if (lspeer != null) { - lspeer.setState(state); - log.debug("Peer : " + routerid + " is not available"); - - return; - } else { - log.debug("Did not find : " + routerid); - return; - } - } - - @Override - public BgpPeerCfg.State getPeerConnState(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if (lspeer != null) { - return lspeer.getState(); - } else { - return BgpPeerCfg.State.INVALID; //No instance - } - } - - @Override - public boolean isPeerConnectable(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - - if ((lspeer != null) && lspeer.getState().equals(BgpPeerCfg.State.IDLE)) { - return true; - } - - return false; - } - - @Override - public TreeMap getPeerTree() { - return this.bgpPeerTree; - } - - @Override - public TreeMap displayPeers() { - if (this.bgpPeerTree.isEmpty()) { - log.debug("There are no BGP peers"); - } else { - Set> set = this.bgpPeerTree.entrySet(); - Iterator> list = set.iterator(); - BgpPeerCfg lspeer; - - while (list.hasNext()) { - Entry me = list.next(); - lspeer = me.getValue(); - log.debug("Peer neighbor IP :" + me.getKey()); - log.debug(", AS Number : " + lspeer.getAsNumber()); - log.debug(", Hold Timer : " + lspeer.getHoldtime()); - log.debug(", Is iBGP : " + lspeer.getIsIBgp()); - } - } - return null; - } - - @Override - public BgpPeerCfg displayPeers(String routerid) { - - if (this.bgpPeerTree.isEmpty()) { - log.debug("There are no Bgp peers"); - } else { - return this.bgpPeerTree.get(routerid); - } - return null; - } - - @Override - public void setHoldTime(short holdTime) { - this.holdTime = holdTime; - } - - @Override - public short getHoldTime() { - return this.holdTime; - } - - @Override - public boolean getLargeASCapability() { - return this.largeAs; - } - - @Override - public void setLargeASCapability(boolean largeAs) { - this.largeAs = largeAs; - } - - @Override - public boolean isPeerConfigured(String routerid) { - BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); - return (lspeer != null) ? true : false; - } - - @Override - public boolean isPeerConnected(String routerid) { - // TODO: is peer connected - return true; - } - - @Override - public int getMaxConnRetryCount() { - return this.maxConnRetryCount; - } - - @Override - public void setMaxConnRetryCout(int retryCount) { - this.maxConnRetryCount = retryCount; - } - - @Override - public int getMaxConnRetryTime() { - return this.maxConnRetryTime; - } - - @Override - public void setMaxConnRetryTime(int retryTime) { - this.maxConnRetryTime = retryTime; - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java deleted file mode 100755 index 27db618d..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import java.net.InetSocketAddress; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.jboss.netty.bootstrap.ClientBootstrap; -import org.jboss.netty.channel.ChannelFuture; -import org.jboss.netty.channel.ChannelFutureListener; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.onosproject.bgp.controller.BgpCfg; -import org.onosproject.bgp.controller.BgpController; -import org.onosproject.bgp.controller.BgpPeerCfg; -import org.onosproject.bgp.controller.BgpConnectPeer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implements connection initiation to peer on peer configuration and manage channel using netty channel handler. - */ -public class BgpConnectPeerImpl implements BgpConnectPeer { - private static final Logger log = LoggerFactory.getLogger(BgpConnectPeerImpl.class); - - private ScheduledExecutorService connectExecutor = null; - private final String peerHost; - private static final int RETRY_INTERVAL = 4; - private final int peerPort; - private int connectRetryCounter = 0; - private int connectRetryTime; - private ChannelPipelineFactory pfact; - private ClientBootstrap peerBootstrap; - private BgpCfg bgpconfig; - - /** - * Initialize timer and initiate pipeline factory. - * - * @param bgpController parent BGP controller - * @param remoteHost remote host to connect - * @param remotePort remote port to connect - */ - public BgpConnectPeerImpl(BgpController bgpController, String remoteHost, int remotePort) { - - this.bgpconfig = bgpController.getConfig(); - this.pfact = new BgpPipelineFactory(bgpController, false); - this.peerBootstrap = Controller.peerBootstrap(); - this.peerBootstrap.setPipelineFactory(pfact); - this.peerHost = remoteHost; - this.peerPort = remotePort; - this.connectRetryTime = 0; - } - - @Override - public void disconnectPeer() { - if (connectExecutor != null) { - connectExecutor.shutdown(); - connectExecutor = null; - } - } - - @Override - public void connectPeer() { - scheduleConnectionRetry(this.connectRetryTime); - } - - /** - * Retry connection with exponential back-off mechanism. - * - * @param retryDelay retry delay - */ - private void scheduleConnectionRetry(long retryDelay) { - if (this.connectExecutor == null) { - this.connectExecutor = Executors.newSingleThreadScheduledExecutor(); - } - this.connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES); - } - - /** - * Implements BGP connection and manages connection to peer with back-off mechanism in case of failure. - */ - class ConnectionRetry implements Runnable { - @Override - public void run() { - log.debug("Connect to peer {}", peerHost); - - InetSocketAddress connectToSocket = new InetSocketAddress(peerHost, peerPort); - - try { - bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.CONNECT); - peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.ACTIVE); - connectRetryCounter++; - log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter, - peerHost); - /* - * Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4 - * mins. - */ - if (connectRetryTime < RETRY_INTERVAL) { - connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1; - } - scheduleConnectionRetry(connectRetryTime); - } else { - - connectRetryCounter++; - log.info("Connected to remote host {}, Connect Counter {}", peerHost, connectRetryCounter); - disconnectPeer(); - return; - } - } - }); - } catch (Exception e) { - log.info("Connect peer exception : " + e.toString()); - disconnectPeer(); - } - } - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java deleted file mode 100755 index 6a14e85c..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.bgp.controller.BgpCfg; -import org.onosproject.bgp.controller.BgpController; -import org.onosproject.bgp.controller.BgpId; -import org.onosproject.bgp.controller.BgpPeer; -import org.onosproject.bgp.controller.BgpNodeListener; -import org.onosproject.bgp.controller.BgpPeerManager; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Component(immediate = true) -@Service -public class BgpControllerImpl implements BgpController { - - private static final Logger log = LoggerFactory.getLogger(BgpControllerImpl.class); - - protected ConcurrentHashMap connectedPeers = new ConcurrentHashMap(); - - protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl(); - - protected Set bgpNodeListener = new CopyOnWriteArraySet<>(); - - final Controller ctrl = new Controller(this); - - private BgpConfig bgpconfig = new BgpConfig(); - - @Activate - public void activate() { - this.ctrl.start(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - // Close all connected peers - closeConnectedPeers(); - this.ctrl.stop(); - log.info("Stopped"); - } - - @Override - public Iterable getPeers() { - return this.connectedPeers.values(); - } - - @Override - public BgpPeer getPeer(BgpId bgpId) { - return this.connectedPeers.get(bgpId); - } - - @Override - public void addListener(BgpNodeListener listener) { - this.bgpNodeListener.add(listener); - } - - @Override - public void removeListener(BgpNodeListener listener) { - this.bgpNodeListener.remove(listener); - } - - @Override - public Set listener() { - return bgpNodeListener; - } - - @Override - public void writeMsg(BgpId bgpId, BgpMessage msg) { - this.getPeer(bgpId).sendMessage(msg); - } - - @Override - public void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException { - - switch (msg.getType()) { - case OPEN: - // TODO: Process Open message - break; - case KEEP_ALIVE: - // TODO: Process keepalive message - break; - case NOTIFICATION: - // TODO: Process notificatoin message - break; - case UPDATE: - // TODO: Process update message - break; - default: - // TODO: Process other message - break; - } - } - - @Override - public void closeConnectedPeers() { - BgpPeer bgpPeer; - for (BgpId id : this.connectedPeers.keySet()) { - bgpPeer = getPeer(id); - bgpPeer.disconnectPeer(); - } - } - - /** - * Implementation of an BGP Peer which is responsible for keeping track of connected peers and the state in which - * they are. - */ - public class BgpPeerManagerImpl implements BgpPeerManager { - - private final Logger log = LoggerFactory.getLogger(BgpPeerManagerImpl.class); - private final Lock peerLock = new ReentrantLock(); - - @Override - public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer) { - - if (connectedPeers.get(bgpId) != null) { - this.log.error("Trying to add connectedPeer but found previous " + "value for bgp ip: {}", - bgpId.toString()); - return false; - } else { - this.log.debug("Added Peer {}", bgpId.toString()); - connectedPeers.put(bgpId, bgpPeer); - return true; - } - } - - @Override - public boolean isPeerConnected(BgpId bgpId) { - if (connectedPeers.get(bgpId) == null) { - this.log.error("Is peer connected: bgpIp {}.", bgpId.toString()); - return false; - } - - return true; - } - - @Override - public void removeConnectedPeer(BgpId bgpId) { - connectedPeers.remove(bgpId); - } - - @Override - public BgpPeer getPeer(BgpId bgpId) { - return connectedPeers.get(bgpId); - } - - /** - * Gets bgp peer instance. - * - * @param bgpController controller instance. - * @param sessionInfo bgp session info. - * @param pktStats packet statistics. - * @return BGPPeer peer instance. - */ - public BgpPeer getBgpPeerInstance(BgpController bgpController, BgpSessionInfoImpl sessionInfo, - BgpPacketStatsImpl pktStats) { - BgpPeer bgpPeer = new BgpPeerImpl(bgpController, sessionInfo, pktStats); - return bgpPeer; - } - - } - - /** - * Returns controller. - * - * @return controller - */ - public Controller controller() { - return this.ctrl; - } - - @Override - public ConcurrentHashMap connectedPeers() { - return connectedPeers; - } - - @Override - public BgpPeerManagerImpl peerManager() { - return peerManager; - } - - @Override - public BgpCfg getConfig() { - return this.bgpconfig; - } - - @Override - public int connectedPeerCount() { - return connectedPeers.size(); - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java deleted file mode 100755 index 524ac4c1..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.util.Timer; -import java.util.TimerTask; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implement sending keepalive message to connected peer periodically based on negotiated holdtime. - */ -public class BgpKeepAliveTimer { - - private Timer keepAliveTimer; - private BgpChannelHandler handler; - private static final Logger log = LoggerFactory.getLogger(BgpKeepAliveTimer.class); - - /** - * Gets keepalive timer object. - * - * @return keepAliveTimer keepalive timer. - */ - public Timer getKeepAliveTimer() { - return keepAliveTimer; - } - - /** - * Initialize timer to send keepalive message periodically. - * - * @param h channel handler - * @param seconds time interval. - */ - public BgpKeepAliveTimer(BgpChannelHandler h, int seconds) { - this.handler = h; - this.keepAliveTimer = new Timer(); - this.keepAliveTimer.schedule(new SendKeepAlive(), 0, seconds * 1000); - } - - /** - * Send keepalive message to connected peer on schedule. - */ - class SendKeepAlive extends TimerTask { - @Override - public void run() { - log.debug("Sending periodic KeepAlive"); - - try { - // Send keep alive message - handler.sendKeepAliveMessage(); - handler.getBgpPacketStats().addOutPacket(); - } catch (Exception e) { - log.info("Exception occured while sending keepAlive message" + e.toString()); - } - } - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java deleted file mode 100755 index 431c6210..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.frame.FrameDecoder; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onlab.util.HexDump; -import org.onosproject.bgpio.protocol.BgpFactories; -import org.onosproject.bgpio.protocol.BgpMessageReader; -import org.onosproject.bgpio.types.BgpHeader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Decode an bgp message from a Channel, for use in a netty pipeline. - */ -public class BgpMessageDecoder extends FrameDecoder { - - protected static final Logger log = LoggerFactory.getLogger(BgpMessageDecoder.class); - - @Override - protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { - log.debug("MESSAGE IS RECEIVED."); - if (!channel.isConnected()) { - log.info("Channel is not connected."); - return null; - } - - HexDump.dump(buffer); - - BgpMessageReader reader = BgpFactories.getGenericReader(); - List msgList = new LinkedList(); - - while (buffer.readableBytes() > 0) { - BgpHeader bgpHeader = new BgpHeader(); - BgpMessage message = reader.readFrom(buffer, bgpHeader); - msgList.add(message); - } - return msgList; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java deleted file mode 100755 index 3e56d6ff..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onlab.util.HexDump; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Encode an bgp message for output into a ChannelBuffer, for use in a - * netty pipeline. - */ -public class BgpMessageEncoder extends OneToOneEncoder { - protected static final Logger log = LoggerFactory.getLogger(BgpMessageEncoder.class); - - @Override - protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { - log.debug("BGPMessageEncoder::encode"); - if (!(msg instanceof List)) { - log.debug("Invalid msg."); - return msg; - } - - @SuppressWarnings("unchecked") - List msglist = (List) msg; - - ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); - - log.debug("SENDING MESSAGE"); - for (BgpMessage pm : msglist) { - pm.writeTo(buf); - } - - HexDump.dump(buf); - - return buf; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java deleted file mode 100755 index 7494c814..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import org.onosproject.bgp.controller.BgpPacketStats; - -/** - * A representation of a packet context which allows any provider - * to view a packet in event, but may block the response to the - * event if blocked has been called. This packet context can be used - * to react to the packet in event with a packet out. - */ -public class BgpPacketStatsImpl implements BgpPacketStats { - - private int inPacketCount; - private int outPacketCount; - private int wrongPacketCount; - private long time; - - /** - * Resets parameter. - */ - public BgpPacketStatsImpl() { - this.inPacketCount = 0; - this.outPacketCount = 0; - this.wrongPacketCount = 0; - this.time = 0; - } - - /** - * Get the outgoing packet count number. - * - * @return packet count - */ - public int outPacketCount() { - return outPacketCount; - } - - /** - * Get the incoming packet count number. - * - * @return packet count - */ - public int inPacketCount() { - return inPacketCount; - } - - /** - * Get the wrong packet count number. - * - * @return packet count - */ - public int wrongPacketCount() { - return wrongPacketCount; - } - - /** - * Increments the received packet counter. - */ - public void addInPacket() { - this.inPacketCount++; - } - - /** - * Increments the sent packet counter. - */ - public void addOutPacket() { - this.outPacketCount++; - } - - /** - * Increments the sent packet counter by specified value. - * - * @param value of no of packets sent - */ - public void addOutPacket(int value) { - this.outPacketCount = this.outPacketCount + value; - } - - /** - * Increments the wrong packet counter. - */ - public void addWrongPacket() { - this.wrongPacketCount++; - } - - /** - * Resets wrong packet count. - */ - public void resetWrongPacket() { - this.wrongPacketCount = 0; - } - - /** - * Get the time. - * - * @return time - */ - public long getTime() { - return this.time; - } - - /** - * Sets the time. - * - * @param time value to set - */ - public void setTime(long time) { - this.time = time; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java deleted file mode 100755 index a8eaee3c..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import org.onlab.packet.Ip4Address; -import org.onosproject.bgp.controller.BgpConnectPeer; -import org.onosproject.bgp.controller.BgpPeerCfg; - -/** - * BGP Peer configuration information. - */ -public class BgpPeerConfig implements BgpPeerCfg { - private int asNumber; - private short holdTime; - private boolean isIBgp; - private Ip4Address peerId = null; - private State state; - private boolean selfInitiated; - private BgpConnectPeer connectPeer; - - /** - * Constructor to initialize the values. - */ - BgpPeerConfig() { - state = State.IDLE; - selfInitiated = false; - } - - @Override - public int getAsNumber() { - return this.asNumber; - } - - @Override - public void setAsNumber(int asNumber) { - this.asNumber = asNumber; - } - - @Override - public short getHoldtime() { - return this.holdTime; - } - - @Override - public void setHoldtime(short holdTime) { - this.holdTime = holdTime; - } - - @Override - public boolean getIsIBgp() { - return this.isIBgp; - } - - @Override - public void setIsIBgp(boolean isIBgp) { - this.isIBgp = isIBgp; - } - - @Override - public String getPeerRouterId() { - if (this.peerId != null) { - return this.peerId.toString(); - } else { - return null; - } - } - - @Override - public void setPeerRouterId(String peerId) { - this.peerId = Ip4Address.valueOf(peerId); - } - - @Override - public void setPeerRouterId(String peerId, int asNumber) { - this.peerId = Ip4Address.valueOf(peerId); - this.asNumber = asNumber; - } - - @Override - public State getState() { - return this.state; - } - - @Override - public void setState(State state) { - this.state = state; - } - - @Override - public boolean getSelfInnitConnection() { - return this.selfInitiated; - } - - @Override - public void setSelfInnitConnection(boolean selfInit) { - this.selfInitiated = selfInit; - } - - @Override - public BgpConnectPeer connectPeer() { - return this.connectPeer; - } - - @Override - public void setConnectPeer(BgpConnectPeer connectPeer) { - this.connectPeer = connectPeer; - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java deleted file mode 100644 index 57a924a8..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; -import java.util.concurrent.RejectedExecutionException; - -import org.jboss.netty.channel.Channel; -import org.onlab.packet.IpAddress; -import org.onosproject.bgp.controller.BgpController; -import org.onosproject.bgp.controller.BgpPeer; -import org.onosproject.bgp.controller.BgpSessionInfo; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.BgpFactories; -import org.onosproject.bgpio.protocol.BgpFactory; -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.BgpMessage; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.MpReachNlri; -import org.onosproject.bgpio.types.MpUnReachNlri; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.MoreObjects; - -/** - * BGPPeerImpl implements BGPPeer, maintains peer information and store updates in RIB . - */ -public class BgpPeerImpl implements BgpPeer { - - protected final Logger log = LoggerFactory.getLogger(BgpPeerImpl.class); - - private static final String SHUTDOWN_MSG = "Worker has already been shutdown"; - - private BgpController bgpController; - private Channel channel; - protected String channelId; - private boolean connected; - protected boolean isHandShakeComplete = false; - private BgpSessionInfo sessionInfo; - private BgpPacketStatsImpl pktStats; - private AdjRibIn adjRib; - private VpnAdjRibIn vpnAdjRib; - - - @Override - public BgpSessionInfo sessionInfo() { - return sessionInfo; - } - - /** - * Initialize peer. - * - *@param bgpController controller instance - *@param sessionInfo bgp session info - *@param pktStats packet statistics - */ - public BgpPeerImpl(BgpController bgpController, BgpSessionInfo sessionInfo, BgpPacketStatsImpl pktStats) { - this.bgpController = bgpController; - this.sessionInfo = sessionInfo; - this.pktStats = pktStats; - this.adjRib = new AdjRibIn(); - this.vpnAdjRib = new VpnAdjRibIn(); - } - - - @Override - public void buildAdjRibIn(List pathAttr) throws BgpParseException { - ListIterator iterator = pathAttr.listIterator(); - while (iterator.hasNext()) { - BgpValueType attr = iterator.next(); - if (attr instanceof MpReachNlri) { - List nlri = ((MpReachNlri) attr).mpReachNlri(); - callAdd(this, nlri, pathAttr); - } - if (attr instanceof MpUnReachNlri) { - List nlri = ((MpUnReachNlri) attr).mpUnReachNlri(); - callRemove(this, nlri); - } - } - } - - /** - * Updates NLRI identifier node in a tree separately based on afi and safi. - * - * @param peerImpl BGP peer instance - * @param nlri MpReachNlri path attribute - * @param pathAttr list of BGP path attributes - * @throws BgpParseException throws exception - */ - public void callAdd(BgpPeerImpl peerImpl, List nlri, List pathAttr) - throws BgpParseException { - ListIterator listIterator = nlri.listIterator(); - while (listIterator.hasNext()) { - BgpLSNlri nlriInfo = listIterator.next(); - if (nlriInfo instanceof BgpNodeLSNlriVer4) { - PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); - if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.add(nlriInfo, details); - } else { - vpnAdjRib.addVpn(nlriInfo, details, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { - PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); - if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.add(nlriInfo, details); - } else { - vpnAdjRib.addVpn(nlriInfo, details, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { - PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); - if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.add(nlriInfo, details); - } else { - vpnAdjRib.addVpn(nlriInfo, details, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } - } - } - - /** - * Sets BGP path attribute and NLRI details. - * - * @param nlriInfo MpReachNlri path attribute - * @param pathAttr list of BGP path attributes - * @return details object of PathAttrNlriDetails - * @throws BgpParseException throw exception - */ - public PathAttrNlriDetails setPathAttrDetails(BgpLSNlri nlriInfo, List pathAttr) - throws BgpParseException { - PathAttrNlriDetails details = new PathAttrNlriDetails(); - details.setProtocolID(nlriInfo.getProtocolId()); - details.setIdentifier(nlriInfo.getIdentifier()); - details.setPathAttribute(pathAttr); - return details; - } - - /** - * Removes NLRI identifier node in a tree separately based on afi and safi. - * - * @param peerImpl BGP peer instance - * @param nlri NLRI information - */ - public void callRemove(BgpPeerImpl peerImpl, List nlri) { - ListIterator listIterator = nlri.listIterator(); - while (listIterator.hasNext()) { - BgpLSNlri nlriInfo = listIterator.next(); - if (nlriInfo instanceof BgpNodeLSNlriVer4) { - if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.remove(nlriInfo); - } else { - vpnAdjRib.removeVpn(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { - if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.remove(nlriInfo); - } else { - vpnAdjRib.removeVpn(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { - if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { - adjRib.remove(nlriInfo); - } else { - vpnAdjRib.removeVpn(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); - } - } - } - } - - /** - * Return the adjacency RIB-IN. - * - * @return adjRib the adjacency RIB-IN - */ - public AdjRibIn adjRib() { - return adjRib; - } - - /** - * Return the adjacency RIB-IN with VPN. - * - * @return vpnAdjRib the adjacency RIB-IN with VPN - */ - public VpnAdjRibIn vpnAdjRib() { - return vpnAdjRib; - } - - // ************************ - // Channel related - // ************************ - - @Override - public final void disconnectPeer() { - this.channel.close(); - } - - @Override - public final void sendMessage(BgpMessage m) { - log.debug("Sending message to {}", channel.getRemoteAddress()); - try { - channel.write(Collections.singletonList(m)); - this.pktStats.addOutPacket(); - } catch (RejectedExecutionException e) { - log.warn(e.getMessage()); - if (!e.getMessage().contains(SHUTDOWN_MSG)) { - throw e; - } - } - } - - @Override - public final void sendMessage(List msgs) { - try { - channel.write(msgs); - this.pktStats.addOutPacket(msgs.size()); - } catch (RejectedExecutionException e) { - log.warn(e.getMessage()); - if (!e.getMessage().contains(SHUTDOWN_MSG)) { - throw e; - } - } - } - - @Override - public final boolean isConnected() { - return this.connected; - } - - @Override - public final void setConnected(boolean connected) { - this.connected = connected; - }; - - @Override - public final void setChannel(Channel channel) { - this.channel = channel; - final SocketAddress address = channel.getRemoteAddress(); - if (address instanceof InetSocketAddress) { - final InetSocketAddress inetAddress = (InetSocketAddress) address; - final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress()); - if (ipAddress.isIp4()) { - channelId = ipAddress.toString() + ':' + inetAddress.getPort(); - } else { - channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort(); - } - } - }; - - @Override - public final Channel getChannel() { - return this.channel; - }; - - @Override - public String channelId() { - return channelId; - } - - @Override - public BgpFactory factory() { - return BgpFactories.getFactory(sessionInfo.remoteBgpVersion()); - } - - @Override - public boolean isHandshakeComplete() { - return isHandShakeComplete; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).omitNullValues() - .add("channel", channelId()) - .add("BgpId", sessionInfo().remoteBgpId()).toString(); - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java deleted file mode 100755 index 28e1041c..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.handler.timeout.ReadTimeoutHandler; -import org.jboss.netty.util.ExternalResourceReleasable; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; -import org.onosproject.bgp.controller.BgpController; - -/** - * Creates a ChannelPipeline for a server-side bgp channel. - */ -public class BgpPipelineFactory - implements ChannelPipelineFactory, ExternalResourceReleasable { - - static final Timer TIMER = new HashedWheelTimer(); - protected ReadTimeoutHandler readTimeoutHandler; - private boolean isBgpServ; - private BgpController bgpController; - - /** - * Constructor to initialize the values. - * - * @param bgpController parent controller - * @param isBgpServ if it is a server or remote peer - */ - public BgpPipelineFactory(BgpController bgpController, boolean isBgpServ) { - super(); - this.isBgpServ = isBgpServ; - this.bgpController = bgpController; - /* hold time */ - this.readTimeoutHandler = new ReadTimeoutHandler(TIMER, bgpController.getConfig().getHoldTime()); - } - - @Override - public ChannelPipeline getPipeline() throws Exception { - BgpChannelHandler handler = new BgpChannelHandler(bgpController); - - ChannelPipeline pipeline = Channels.pipeline(); - pipeline.addLast("bgpmessagedecoder", new BgpMessageDecoder()); - pipeline.addLast("bgpmessageencoder", new BgpMessageEncoder()); - pipeline.addLast("holdTime", readTimeoutHandler); - if (isBgpServ) { - pipeline.addLast("PassiveHandler", handler); - } else { - pipeline.addLast("ActiveHandler", handler); - } - - return pipeline; - } - - @Override - public void releaseExternalResources() { - TIMER.stop(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java deleted file mode 100644 index d3065f43..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import java.util.Comparator; -import java.util.List; -import java.util.ListIterator; - -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; -import org.onosproject.bgpio.types.AsPath; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.LocalPref; -import org.onosproject.bgpio.types.Med; -import org.onosproject.bgpio.types.Origin; -import org.onosproject.bgpio.types.Origin.ORIGINTYPE; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Implementation of BGP best path Selection process. - */ -public final class BgpSelectionAlgo implements Comparator { - private static final Logger log = LoggerFactory.getLogger(BgpSelectionAlgo.class); - LocalPref obj1LocPref = null; - AsPath obj1Aspath = null; - Origin obj1Origin = null; - Med obj1Med = null; - LocalPref obj2LocPref = null; - AsPath obj2Aspath = null; - Origin obj2Origin = null; - Med obj2Med = null; - - @Override - public int compare(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { - if (pathNlriDetails1 == null) { - return -1; - } - if (pathNlriDetails2 == null) { - return 1; - } - if (pathNlriDetails1.equals(pathNlriDetails2)) { - return 0; - } - - List o1 = pathNlriDetails1.localRibNlridetails().pathAttributes(); - List o2 = pathNlriDetails2.localRibNlridetails().pathAttributes(); - ListIterator listIteratorObj1 = o1.listIterator(); - ListIterator listIteratorObj2 = o2.listIterator(); - storeAttr(listIteratorObj1, listIteratorObj2); - - // prefer attribute with higher local preference - if (obj1LocPref != null || obj2LocPref != null && (obj1LocPref != null && !obj1LocPref.equals(obj2LocPref))) { - return compareLocalPref(obj1LocPref, obj2LocPref); - } - - // prefer attribute with shortest Aspath - if (!obj1Aspath.equals(obj2Aspath)) { - Integer obj1Size = countASSize(obj1Aspath); - Integer obj2Size = countASSize(obj2Aspath); - if (obj1Size != obj2Size) { - return compareAsPath(obj1Size, obj2Size); - } - } - - // prefer attribute with lowest origin type - if (!obj1Origin.equals(obj2Origin)) { - return compareOrigin(obj1Origin, obj2Origin); - } - - // prefer attribute with lowest MED - if (obj1Med != null || obj2Med != null && (obj1Med != null && !obj1Med.equals(obj2Med))) { - return compareMed(obj1Med, obj2Med); - } - - if ((pathNlriDetails1 != null || pathNlriDetails2 != null) && (pathNlriDetails1 != null && !pathNlriDetails1 - .equals(pathNlriDetails2))) { - return comparePeerDetails(pathNlriDetails1, pathNlriDetails2); - } - return 0; - } - - /** - * Compares local preference of two objects and returns object with higher preference. - * - * @param obj1LocPref local preference object1 - * @param obj2LocPref local preference object2 - * @return object with higher preference - */ - int compareLocalPref(LocalPref obj1LocPref, LocalPref obj2LocPref) { - return ((Integer) (obj1LocPref.localPref())).compareTo((Integer) (obj2LocPref.localPref())); - } - - /** - * Compares AsPath of two objects and returns object with shortest AsPath. - * - * @param obj1Size object1 AS count - * @param obj2Size object2 AS count - * @return - */ - int compareAsPath(Integer obj1Size, Integer obj2Size) { - return obj1Size.compareTo(obj2Size); - } - - /** - * Compare Origin of two objects and returns object with lowest origin value. - * - * @param obj1Origin Origin object1 - * @param obj2Origin Origin object1 - * @return object with lowest origin value - */ - int compareOrigin(Origin obj1Origin, Origin obj2Origin) { - if (obj1Origin.origin() == ORIGINTYPE.IGP) { - return 1; - } - if (obj2Origin.origin() == ORIGINTYPE.IGP) { - return -1; - } - if (obj1Origin.origin() == ORIGINTYPE.EGP) { - return 1; - } else { - return -1; - } - } - - /** - * Compare Med of two objects and returns object with lowestMed value. - * - * @param obj1Med Med object1 - * @param obj2Med Med object2 - * @return returns object with lowestMed value - */ - int compareMed(Med obj1Med, Med obj2Med) { - return ((Integer) (obj2Med.med())).compareTo((Integer) (obj1Med.med())); - } - - /** - * Compares EBGP over IBGP, BGP identifier value and peer address. - * - * @param pathNlriDetails1 PathAttrNlriDetailsLocalRib object1 - * @param pathNlriDetails2 PathAttrNlriDetailsLocalRib object2 - * @return object which as EBGP over IBGP, lowest BGP identifier value and lowest peer address - */ - int comparePeerDetails(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { - // consider EBGP over IBGP - if (pathNlriDetails1.isLocalRibIbgpSession() != pathNlriDetails2.isLocalRibIbgpSession()) { - if (pathNlriDetails1 == null || pathNlriDetails1.isLocalRibIbgpSession()) { - return -1; - } - if (pathNlriDetails2 == null || pathNlriDetails2.isLocalRibIbgpSession()) { - return 1; - } - } - // prefer lowest BGP identifier value. - if (pathNlriDetails1.localRibIdentifier() != pathNlriDetails2.localRibIdentifier()) { - return ((Integer) pathNlriDetails2.localRibIdentifier()) - .compareTo(pathNlriDetails1.localRibIdentifier()); - } - //prefer lowest peer address - if (pathNlriDetails1.localRibIpAddress() != pathNlriDetails2.localRibIpAddress()) { - return pathNlriDetails2.localRibIpAddress().compareTo(pathNlriDetails1.localRibIpAddress()); - } - return 0; - } - - /** - * Returns ASes count of AsPath attribute , if AS_SET is present then count as 1. - * - * @param aspath object of AsPath - * @return count of ASes - */ - Integer countASSize(AsPath aspath) { - boolean isASSet = false; - int count = 0; - if (!aspath.asPathSet().isEmpty()) { - isASSet = true; - } - if (!aspath.asPathSeq().isEmpty()) { - count = aspath.asPathSeq().size(); - } - return isASSet ? ++count : count; - } - - /** - * Stores BGP basic attributes of two objects. - * - * @param listIteratorObj1 list iterator of object1 - * @param listIteratorObj2 list iterator of object2 - */ - void storeAttr(ListIterator listIteratorObj1, ListIterator listIteratorObj2) { - while (listIteratorObj1.hasNext()) { - BgpValueType pathAttributeObj1 = listIteratorObj1.next(); - switch (pathAttributeObj1.getType()) { - case LocalPref.LOCAL_PREF_TYPE: - obj1LocPref = (LocalPref) pathAttributeObj1; - break; - case AsPath.ASPATH_TYPE: - obj1Aspath = (AsPath) pathAttributeObj1; - break; - case Origin.ORIGIN_TYPE: - obj1Origin = (Origin) pathAttributeObj1; - break; - case Med.MED_TYPE: - obj1Med = (Med) pathAttributeObj1; - break; - default: - log.debug("Got other type, Not required: " + pathAttributeObj1.getType()); - } - } - while (listIteratorObj2.hasNext()) { - BgpValueType pathAttributeObj2 = listIteratorObj2.next(); - switch (pathAttributeObj2.getType()) { - case LocalPref.LOCAL_PREF_TYPE: - obj2LocPref = (LocalPref) pathAttributeObj2; - break; - case AsPath.ASPATH_TYPE: - obj2Aspath = (AsPath) pathAttributeObj2; - break; - case Origin.ORIGIN_TYPE: - obj2Origin = (Origin) pathAttributeObj2; - break; - case Med.MED_TYPE: - obj2Med = (Med) pathAttributeObj2; - break; - default: - log.debug("Got other type, Not required: " + pathAttributeObj2.getType()); - } - } - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java deleted file mode 100755 index 33623dc2..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import org.onosproject.bgp.controller.BgpId; -import org.onosproject.bgp.controller.BgpSessionInfo; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class maintains BGP peer session info. - */ -public class BgpSessionInfoImpl implements BgpSessionInfo { - - protected final Logger log = LoggerFactory.getLogger(BgpSessionInfoImpl.class); - private BgpId remoteBgpId; - private BgpVersion remoteBgpVersion; - private long remoteBgpASNum; - private short remoteBgpholdTime; - private int remoteBgpIdentifier; - private short negotiatedholdTime; - private boolean isIbgpSession; - - /** - * Initialize session info. - * - *@param remoteBgpId remote peer id - *@param remoteBgpVersion remote peer version - *@param remoteBgpASNum remote peer AS number - *@param remoteBgpholdTime remote peer hold time - *@param remoteBgpIdentifier remote peer identifier - *@param negotiatedholdTime negotiated hold time - *@param isIbgpSession session type ibgp/ebgp - */ - public BgpSessionInfoImpl(BgpId remoteBgpId, BgpVersion remoteBgpVersion, long remoteBgpASNum, - short remoteBgpholdTime, int remoteBgpIdentifier, short negotiatedholdTime, - boolean isIbgpSession) { - this.remoteBgpId = remoteBgpId; - this.remoteBgpVersion = remoteBgpVersion; - this.remoteBgpASNum = remoteBgpASNum; - this.remoteBgpholdTime = remoteBgpholdTime; - this.remoteBgpIdentifier = remoteBgpIdentifier; - this.negotiatedholdTime = negotiatedholdTime; - this.isIbgpSession = isIbgpSession; - } - - @Override - public boolean isIbgpSession() { - return isIbgpSession; - } - - @Override - public short negotiatedholdTime() { - return negotiatedholdTime; - } - - @Override - public BgpId remoteBgpId() { - return remoteBgpId; - } - - @Override - public BgpVersion remoteBgpVersion() { - return remoteBgpVersion; - } - - @Override - public long remoteBgpASNum() { - return remoteBgpASNum; - } - - @Override - public short remoteBgpHoldTime() { - return remoteBgpholdTime; - } - - @Override - public int remoteBgpIdentifier() { - return remoteBgpIdentifier; - } -} diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java deleted file mode 100755 index f02cee8a..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp.controller.impl; - -import static org.onlab.util.Tools.groupedThreads; - -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Executors; - -import org.jboss.netty.bootstrap.ClientBootstrap; -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.group.ChannelGroup; -import org.jboss.netty.channel.group.DefaultChannelGroup; -import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; -import org.onosproject.bgp.controller.BgpController; -import org.onosproject.bgpio.protocol.BgpFactories; -import org.onosproject.bgpio.protocol.BgpFactory; -import org.onosproject.bgpio.protocol.BgpVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The main controller class. Handles all setup and network listeners - Distributed ownership control of bgp peer - * through IControllerRegistryService - */ -public class Controller { - - private static final Logger log = LoggerFactory.getLogger(Controller.class); - - private static final BgpFactory FACTORY4 = BgpFactories.getFactory(BgpVersion.BGP_4); - - private ChannelGroup cg; - public Channel serverChannel; - - // Configuration options - private static final short BGP_PORT_NUM = 179; - private static final short PORT_NUM_ZERO = 0; - private static boolean isPortNumSet = false; - private final int workerThreads = 16; - private final int peerWorkerThreads = 16; - - // Start time of the controller - private long systemStartTime; - - private NioServerSocketChannelFactory serverExecFactory; - private NioClientSocketChannelFactory peerExecFactory; - private static ClientBootstrap peerBootstrap; - private BgpController bgpController; - - // Perf. related configuration - private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; - - /** - * Constructor to initialize the values. - * - * @param bgpController bgp controller instance - */ - public Controller(BgpController bgpController) { - this.bgpController = bgpController; - } - - /** - * Returns factory version for processing BGP messages. - * - * @return instance of factory version - */ - static BgpFactory getBgpMessageFactory4() { - return FACTORY4; - } - - /** - * To get system start time. - * - * @return system start time in milliseconds - */ - public long getSystemStartTime() { - return (this.systemStartTime); - } - - /** - * Tell controller that we're ready to accept bgp peer connections. - */ - public void run() { - - try { - - peerBootstrap = createPeerBootStrap(); - - peerBootstrap.setOption("reuseAddr", true); - peerBootstrap.setOption("child.keepAlive", true); - peerBootstrap.setOption("child.tcpNoDelay", true); - peerBootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - - final ServerBootstrap bootstrap = createServerBootStrap(); - - bootstrap.setOption("reuseAddr", true); - bootstrap.setOption("child.keepAlive", true); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - - ChannelPipelineFactory pfact = new BgpPipelineFactory(bgpController, true); - - bootstrap.setPipelineFactory(pfact); - InetSocketAddress sa = new InetSocketAddress(getBgpPortNum()); - cg = new DefaultChannelGroup(); - serverChannel = bootstrap.bind(sa); - cg.add(serverChannel); - log.info("Listening for Peer connection on {}", sa); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Creates server boot strap. - * - * @return ServerBootStrap - */ - private ServerBootstrap createServerBootStrap() { - - if (workerThreads == 0) { - serverExecFactory = new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d"))); - return new ServerBootstrap(serverExecFactory); - } else { - serverExecFactory = new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")), - workerThreads); - return new ServerBootstrap(serverExecFactory); - } - } - - /** - * Creates peer boot strap. - * - * @return ClientBootstrap - */ - private ClientBootstrap createPeerBootStrap() { - - if (peerWorkerThreads == 0) { - peerExecFactory = new NioClientSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d"))); - return new ClientBootstrap(peerExecFactory); - } else { - peerExecFactory = new NioClientSocketChannelFactory( - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), - Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")), - peerWorkerThreads); - return new ClientBootstrap(peerExecFactory); - } - } - - /** - * Gets peer bootstrap. - * - * @return peer bootstrap - */ - public static ClientBootstrap peerBootstrap() { - return peerBootstrap; - } - - /** - * Initialize internal data structures. - */ - public void init() { - // These data structures are initialized here because other - // module's startUp() might be called before ours - this.systemStartTime = System.currentTimeMillis(); - } - - /** - * Gets run time memory. - * - * @return m run time memory - */ - public Map getMemory() { - Map m = new HashMap<>(); - Runtime runtime = Runtime.getRuntime(); - m.put("total", runtime.totalMemory()); - m.put("free", runtime.freeMemory()); - return m; - } - - /** - * Gets UP time. - * - * @return UP time - */ - public Long getUptime() { - RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); - return rb.getUptime(); - } - - /** - * Starts the BGP controller. - */ - public void start() { - log.info("Started"); - this.init(); - this.run(); - } - - /** - * Stops the BGP controller. - */ - public void stop() { - log.info("Stopped"); - serverExecFactory.shutdown(); - peerExecFactory.shutdown(); - cg.close(); - } - - /** - * Returns port number. - * - * @return port number - */ - public static short getBgpPortNum() { - if (isPortNumSet) { - return PORT_NUM_ZERO; - } - return BGP_PORT_NUM; - } - - /** - * sets the isPortNumSet as true. - */ - public void setBgpPortNum() { - isPortNumSet = true; - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java deleted file mode 100644 index 8a9ea91c..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.bgp.controller.impl; - -import java.util.Map; -import java.util.TreeMap; - -import org.onosproject.bgpio.protocol.BgpLSNlri; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; -import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; -import org.onosproject.bgpio.types.RouteDistinguisher; - -import com.google.common.base.MoreObjects; - -/** - * Implementation of Adj-RIB-In with VPN for each peer. - */ -public class VpnAdjRibIn { - private Map nodeTree = new TreeMap<>(); - private Map linkTree = new TreeMap<>(); - private Map prefixTree = new TreeMap<>(); - - private Map> vpnNodeTree - = new TreeMap<>(); - private Map> vpnLinkTree - = new TreeMap<>(); - private Map> vpnPrefixTree - = new TreeMap<>(); - /** - * Returns the adjacency node. - * - * @return node adjacency RIB node - */ - public Map nodeTree() { - return nodeTree; - } - - /** - * Returns the adjacency link. - * - * @return link adjacency RIB node - */ - public Map linkTree() { - return linkTree; - } - - /** - * Returns the adjacency prefix. - * - * @return prefix adjacency RIB node - */ - public Map prefixTree() { - return prefixTree; - } - - /** - * Returns the adjacency vpnNode. - * - * @return vpnNode adjacency RIB node - */ - public Map> vpnNodeTree() { - return vpnNodeTree; - } - - /** - * Returns the adjacency vpnLink. - * - * @return vpnLink adjacency RIB node - */ - public Map> vpnLinkTree() { - return vpnLinkTree; - } - - /** - * Returns the adjacency vpnPrefix. - * - * @return vpnPrefix adjacency RIB node - */ - public Map> vpnPrefixTree() { - return vpnPrefixTree; - } - - /** - * Update vpn nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. - * - * @param nlri NLRI info - * @param details has pathattribute , protocolID and identifier - */ - public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { - if (nlri instanceof BgpNodeLSNlriVer4) { - BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); - if (nodeTree.containsKey(nodeLSIdentifier)) { - nodeTree.replace(nodeLSIdentifier, details); - } else { - nodeTree.put(nodeLSIdentifier, details); - } - } else if (nlri instanceof BgpLinkLsNlriVer4) { - BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); - if (linkTree.containsKey(linkLSIdentifier)) { - linkTree.replace(linkLSIdentifier, details); - } else { - linkTree.put(linkLSIdentifier, details); - } - } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { - BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); - if (prefixTree.containsKey(prefixIdentifier)) { - prefixTree.replace(prefixIdentifier, details); - } else { - prefixTree.put(prefixIdentifier, details); - } - } - } - - /** - * Update nlri identifier mapped with route distinguisher if it exists in tree otherwise add nlri infomation mapped - * to respective route distinguisher in tree. - * - * @param nlri NLRI info - * @param details has pathattribute , protocolID and identifier - * @param routeDistinguisher unique for for each vpn - */ - public void addVpn(BgpLSNlri nlri, PathAttrNlriDetails details, RouteDistinguisher routeDistinguisher) { - add(nlri, details); - if (nlri instanceof BgpNodeLSNlriVer4) { - if (!vpnNodeTree.containsKey(routeDistinguisher)) { - vpnNodeTree.put(routeDistinguisher, nodeTree); - } - } else if (nlri instanceof BgpLinkLsNlriVer4) { - if (!vpnLinkTree.containsKey(routeDistinguisher)) { - vpnLinkTree.put(routeDistinguisher, linkTree); - } - } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { - if (!vpnPrefixTree.containsKey(routeDistinguisher)) { - vpnPrefixTree.put(routeDistinguisher, prefixTree); - } - } - } - - /** - * Removes vpn nlri identifier mapped to route distinguisher if it exists in tree. - * - * @param nlri NLRI Info - * @param routeDistinguisher unique for for each vpn - */ - public void removeVpn(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) { - if (nlri instanceof BgpNodeLSNlriVer4) { - if (vpnNodeTree.containsKey(routeDistinguisher)) { - BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); - if (nodeTree.containsKey(nodeLSIdentifier)) { - nodeTree.remove(nodeLSIdentifier); - } - if ((vpnNodeTree.get(routeDistinguisher)).isEmpty()) { - vpnNodeTree.remove(routeDistinguisher); - } - } - } else if (nlri instanceof BgpLinkLsNlriVer4) { - if (vpnLinkTree.containsKey(routeDistinguisher)) { - BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); - if (linkTree.containsKey(linkLSIdentifier)) { - linkTree.remove(linkLSIdentifier); - } - if ((vpnLinkTree.get(routeDistinguisher)).isEmpty()) { - vpnLinkTree.remove(routeDistinguisher); - } - } - } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { - if (vpnPrefixTree.containsKey(routeDistinguisher)) { - BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); - if (prefixTree.containsKey(prefixIdentifier)) { - prefixTree.remove(prefixIdentifier); - } - if ((vpnPrefixTree.get(routeDistinguisher)).isEmpty()) { - vpnPrefixTree.remove(routeDistinguisher); - } - } - } - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .omitNullValues().add("nodeTree", nodeTree) - .add("linkTree", linkTree) - .add("prefixTree", prefixTree) - .add("vpnNodeTree", vpnNodeTree) - .add("vpnLinkTree", vpnLinkTree) - .add("vpnPrefixTree", vpnPrefixTree) - .toString(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java b/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java deleted file mode 100755 index fd4e9506..00000000 --- a/framework/src/onos/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the BGP controller IO subsystem. - */ -package org.onosproject.bgp.controller.impl; diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java deleted file mode 100755 index 36b1d6fc..00000000 --- a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import com.google.common.net.InetAddresses; -import org.jboss.netty.bootstrap.ClientBootstrap; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelFactory; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -import org.onlab.junit.TestUtils; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.LinkedList; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.onosproject.bgp.controller.BgpCfg; -import org.onosproject.bgp.controller.impl.BgpControllerImpl; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; -import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; - -/** - * Test case for BGPControllerImpl. - */ -public class BgpControllerImplTest { - - protected static final Logger log = LoggerFactory - .getLogger(BgpControllerImplTest.class); - - private static final String IP_LOOPBACK_ID1 = "127.0.0.1"; - - private static final int MESSAGE_TIMEOUT_MS = 3000; - public byte version; - public short asNumber; - public short holdTime; - public int bgpId = InetAddresses.coerceToInteger(InetAddresses.forString(IP_LOOPBACK_ID1)); - public boolean isLargeAsCapabilitySet = false; - public LinkedList capabilityTlv = new LinkedList<>(); - - @Before - public void setUp() throws Exception { - peer1 = new BgpPeerTest(version, asNumber, - holdTime, bgpId, isLargeAsCapabilitySet, - capabilityTlv); - - bgpControllerImpl = new BgpControllerImpl(); - - // NOTE: We use port 0 to bind on any available port - bgpControllerImpl.controller().setBgpPortNum(); - bgpControllerImpl.activate(); - - Channel serverChannel = TestUtils.getField(bgpControllerImpl.controller(), - "serverChannel"); - SocketAddress socketAddress = serverChannel.getLocalAddress(); - InetSocketAddress inetSocketAddress = - (InetSocketAddress) socketAddress; - InetAddress connectToAddress = InetAddresses.forString("127.0.0.1"); - connectToSocket = new InetSocketAddress(connectToAddress, - inetSocketAddress.getPort()); - - bgpControllerImpl.getConfig().setRouterId("1.1.1.1"); - bgpControllerImpl.getConfig().setAsNumber(200); - bgpControllerImpl.getConfig().setHoldTime((short) 120); - bgpControllerImpl.getConfig().setState(BgpCfg.State.IP_AS_CONFIGURED); - - bgpControllerImpl.getConfig().addPeer("127.0.0.1", 200); - } - - @After - public void tearDown() throws Exception { - bgpControllerImpl.deactivate(); - bgpControllerImpl = null; - } - - private BgpControllerImpl bgpControllerImpl; - - BgpPeerTest peer1; - - // The socket that the remote peers should connect to - private InetSocketAddress connectToSocket; - - @Test - public void bgpOpenMessageTest1() throws InterruptedException { - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - peer1.connect(connectToSocket); - boolean result; - result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest2() throws InterruptedException { - // Open message with as number which is not configured at peer - peer1.peerChannelHandler.asNumber = 500; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest3() throws InterruptedException { - // Open message with invalid hold time value - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 1; - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest4() throws InterruptedException { - // Open message with invalid as number - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - peer1.peerChannelHandler.isLargeAsCapabilitySet = true; - BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(766545); - peer1.peerChannelHandler.capabilityTlv.add(tempTlv); - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest5() throws InterruptedException { - // Open message with LS capability - short afi = 16388; - byte res = 0; - byte safi = 71; - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - bgpControllerImpl.getConfig().setLsCapability(true); - BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); - peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest6() throws InterruptedException { - // Open message with as4 capability - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - peer1.peerChannelHandler.isLargeAsCapabilitySet = true; - bgpControllerImpl.getConfig().setLargeASCapability(true); - BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); - peer1.peerChannelHandler.capabilityTlv.add(tempTlv); - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - - result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - @Test - public void bgpOpenMessageTest7() throws InterruptedException { - // Open message with both LS capability and as4 capability - short afi = 16388; - byte res = 0; - byte safi = 71; - peer1.peerChannelHandler.asNumber = 200; - peer1.peerChannelHandler.version = 4; - peer1.peerChannelHandler.holdTime = 120; - - peer1.peerChannelHandler.isLargeAsCapabilitySet = true; - bgpControllerImpl.getConfig().setLargeASCapability(true); - BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); - peer1.peerChannelHandler.capabilityTlv.add(tempTlv); - - bgpControllerImpl.getConfig().setLsCapability(true); - BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); - peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); - peer1.connect(connectToSocket); - - boolean result; - result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( - MESSAGE_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - assertThat(result, is(true)); - } - - /** - * A class to capture the state for a BGP peer. - */ - private final class BgpPeerTest { - private ClientBootstrap peerBootstrap; - private BgpPeerFrameDecoderTest peerFrameDecoder = - new BgpPeerFrameDecoderTest(); - private BgpPeerChannelHandlerTest peerChannelHandler; - - private BgpPeerTest(byte version, short asNumber, - short holdTime, int bgpId, boolean isLargeAsCapabilitySet, - LinkedList capabilityTlv) { - peerChannelHandler = new BgpPeerChannelHandlerTest(version, - asNumber, holdTime, bgpId, isLargeAsCapabilitySet, capabilityTlv); - } - - /** - * Starts the BGP peer. - * - * @param connectToSocket the socket to connect to - */ - private void connect(InetSocketAddress connectToSocket) - throws InterruptedException { - - ChannelFactory channelFactory = - new NioClientSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool()); - ChannelPipelineFactory pipelineFactory = () -> { - ChannelPipeline pipeline = Channels.pipeline(); - pipeline.addLast("BgpPeerFrameDecoderTest", - peerFrameDecoder); - pipeline.addLast("BgpPeerChannelHandlerTest", - peerChannelHandler); - return pipeline; - }; - - peerBootstrap = new ClientBootstrap(channelFactory); - peerBootstrap.setOption("child.keepAlive", true); - peerBootstrap.setOption("child.tcpNoDelay", true); - peerBootstrap.setPipelineFactory(pipelineFactory); - peerBootstrap.connect(connectToSocket); - } - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java deleted file mode 100755 index 26ed36d8..00000000 --- a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import java.util.LinkedList; -import java.util.concurrent.TimeUnit; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.SimpleChannelHandler; -import org.onosproject.bgpio.protocol.ver4.BgpKeepaliveMsgVer4; -import org.onosproject.bgpio.protocol.ver4.BgpOpenMsgVer4; -import org.onosproject.bgpio.types.BgpHeader; -import org.onosproject.bgpio.types.BgpValueType; - -public class BgpPeerChannelHandlerTest extends SimpleChannelHandler { - public static final int OPEN_MSG_MINIMUM_LENGTH = 29; - public static final byte[] MARKER = new byte[] {(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff}; - public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER, - (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01); - LinkedList capabilityTlv = new LinkedList<>(); - public byte version; - public short asNumber; - public short holdTime; - public int bgpId; - public boolean isLargeAsCapabilitySet; - - final BgpOpenMsgVer4 openMessage = new BgpOpenMsgVer4(); - ChannelHandlerContext savedCtx; - - /** - * Constructor to initialize all variables of BGP Open message. - * - * @param version BGP version in open message - * @param asNumber AS number in open message - * @param holdTime hold time in open message - * @param bgpId BGP identifier in open message - * @param capabilityTlv capabilities in open message - */ - public BgpPeerChannelHandlerTest(byte version, - short asNumber, - short holdTime, - int bgpId, - boolean isLargeAsCapabilitySet, - LinkedList capabilityTlv) { - this.version = version; - this.asNumber = asNumber; - this.holdTime = holdTime; - this.bgpId = bgpId; - this.isLargeAsCapabilitySet = isLargeAsCapabilitySet; - this.capabilityTlv = capabilityTlv; - } - - /** - * closes the channel. - */ - void closeChannel() { - savedCtx.getChannel().close(); - } - - @Override - public void channelConnected(ChannelHandlerContext ctx, - ChannelStateEvent channelEvent) throws InterruptedException { - this.savedCtx = ctx; - - BgpOpenMsgVer4 openMsg = new BgpOpenMsgVer4(DEFAULT_OPEN_HEADER, - this.version, - this.asNumber, - this.holdTime, - this.bgpId, - this.capabilityTlv); - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - openMsg.writeTo(buffer); - ctx.getChannel().write(buffer); - - TimeUnit.MILLISECONDS.sleep(100); - - BgpKeepaliveMsgVer4 keepaliveMsg = new BgpKeepaliveMsgVer4(); - ChannelBuffer buffer1 = ChannelBuffers.dynamicBuffer(); - keepaliveMsg.writeTo(buffer1); - ctx.getChannel().write(buffer1); - } - - @Override - public void channelDisconnected(ChannelHandlerContext ctx, - ChannelStateEvent channelEvent) { - //Do Nothing - } -} diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java deleted file mode 100755 index 7767053f..00000000 --- a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.bgp; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.frame.FrameDecoder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.concurrent.CountDownLatch; - -/** - * Class to decode the message received. - */ -public class BgpPeerFrameDecoderTest extends FrameDecoder { - static final byte OPEN_MSG_TYPE = 0x1; - static final byte KEEPALIVE_MSG_TYPE = 0x4; - static final byte UPDATE_MSG_TYPE = 0x2; - static final byte NOTIFICATION_MSG_TYPE = 0x3; - static final int MINIMUM_COMMON_HEADER_LENGTH = 19; - static final int MINIMUM_OPEN_MSG_LENGTH = 29; - static final int MINIMUM_HEADER_MARKER_LENGTH = 16; - static final int HEADER_AND_MSG_LEN = 18; - - protected static final Logger log = LoggerFactory - .getLogger(BgpPeerFrameDecoderTest.class); - final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1); - final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1); - final CountDownLatch receivedNotificationMessageLatch = new CountDownLatch(1); - - @Override - protected Object decode(ChannelHandlerContext ctx, - Channel channel, - ChannelBuffer cb) throws Exception { - - if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { - log.debug("Error: Packet length is less then minimum length"); - return null; - } - - byte[] marker = new byte[MINIMUM_HEADER_MARKER_LENGTH]; - cb.readBytes(marker); - for (int i = 0; i < marker.length; i++) { - if (marker[i] != (byte) 0xff) { - log.debug("Error: Marker must be set all ones"); - ctx.getChannel().close(); - return null; - } - } - - short length = cb.readShort(); - if (length < MINIMUM_COMMON_HEADER_LENGTH) { - log.debug("Error: Bad message length"); - ctx.getChannel().close(); - return null; - } - - if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) { - log.debug("Error: Bad message length"); - ctx.getChannel().close(); - return null; - } - - byte type = cb.readByte(); - int len = length - MINIMUM_COMMON_HEADER_LENGTH; - - ChannelBuffer message = cb.readBytes(len); - - switch (type) { - case OPEN_MSG_TYPE: - processBgpOpen(ctx, message); - break; - case UPDATE_MSG_TYPE: - break; - case NOTIFICATION_MSG_TYPE: - processBgpNotification(ctx, message); - break; - case KEEPALIVE_MSG_TYPE: - processBgpKeepalive(ctx, message); - break; - default: - ctx.getChannel().close(); - return null; - } - - return null; - } - - /** - * Processes BGP open message. - * - * @param ctx Channel handler context - * @param message open message - */ - private void processBgpOpen(ChannelHandlerContext ctx, - ChannelBuffer message) { - int minLength = - MINIMUM_OPEN_MSG_LENGTH - MINIMUM_COMMON_HEADER_LENGTH; - if (message.readableBytes() < minLength) { - log.debug("Error: Bad message length"); - ctx.getChannel().close(); - return; - } - - message.readByte(); // read version - message.readShort(); // read AS number - message.readShort(); // read Hold timer - message.readInt(); // read BGP Identifier - // Optional Parameters - int optParamLen = message.readUnsignedByte(); - if (message.readableBytes() < optParamLen) { - log.debug("Error: Bad message length"); - ctx.getChannel().close(); - return; - } - message.readBytes(optParamLen); - - // Open message received - receivedOpenMessageLatch.countDown(); - } - - /** - * Processes BGP keepalive message. - * - * @param ctx Channel handler context - * @param message keepalive message - */ - private void processBgpKeepalive(ChannelHandlerContext ctx, - ChannelBuffer message) { - - // Keepalive message received - receivedKeepaliveMessageLatch.countDown(); - } - - /** - * Processes BGP notification message. - * - * @param ctx Channel handler context - * @param message notification message - */ - private void processBgpNotification(ChannelHandlerContext ctx, - ChannelBuffer message) { - byte[] data; - message.readByte(); //read error code - message.readByte(); // read error sub code - if (message.readableBytes() > 0) { - data = new byte[message.readableBytes()]; - message.readBytes(data, 0, message.readableBytes()); - } - - // Notification message received - receivedNotificationMessageLatch.countDown(); - } -} \ No newline at end of file diff --git a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java b/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java deleted file mode 100644 index 7c0fa417..00000000 --- a/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.controller.impl; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; - -import java.util.LinkedList; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.junit.Test; -import org.onlab.packet.IpAddress; -import org.onlab.packet.IpAddress.Version; -import org.onosproject.bgpio.exceptions.BgpParseException; -import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; -import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; -import org.onosproject.bgpio.types.AsPath; -import org.onosproject.bgpio.types.BgpValueType; -import org.onosproject.bgpio.types.LocalPref; -import org.onosproject.bgpio.types.Med; -import org.onosproject.bgpio.types.Origin; -import org.onosproject.bgp.controller.impl.BgpSelectionAlgo; - -/** - * Test cases for BGP Selection Algorithm. - */ -public class BgpSelectionAlgoTest { - - /** - * firstPathAttribute and secondPathAttribute has same AS count and firstPathAttribute - * has shortest Origin value than secondPathAttribute. - */ - @Test - public void selectionAlgoTest1() throws BgpParseException { - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - //origin with IGP - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - //AsPath with AS_SEQ with one AS - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xea }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - //origin with INCOMPLETE - origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - //AsPath with AS_SEQ with one AS - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = true; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(1)); - } - - /** - * firstPathAttribute has 1 AS count and secondPathAttribute has 2 AS count - * and firstPathAttribute has shortest Origin value than secondPathAttribute. - */ - @Test - public void selectionAlgoTest2() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x08, 0x02, 0x01, (byte) 0xfd, - (byte) 0xea, 0x02, 0x01, (byte) 0xfd, (byte) 0xea }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = true; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(-1)); - } - - /** - * firstPathAttribute and secondPathAttribute has same AS value - * and firstPathAttribute has shortest Origin value than secondPathAttribute. - */ - @Test - public void selectionAlgoTest3() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = true; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(1)); - } - - /** - * firstPathAttribute has lowest med than secondPathAttribute. - */ - @Test - public void selectionAlgoTest4() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x00 }; - buffer.writeBytes(med); - pathAttribute1 = Med.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01 }; - buffer.writeBytes(med); - pathAttribute2 = Med.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = true; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(1)); - } - - /** - * secondPathAttribute has higher local preference than firstPathAttribute. - */ - @Test - public void selectionAlgoTest5() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, - 0x00, 0x01 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(locPref); - pathAttribute1 = LocalPref.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x0a }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(locPref); - pathAttribute2 = LocalPref.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = true; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(-1)); - } - - /** - * secondPathAttribute is EBGP than firstPathAttribute is IBGP. - */ - @Test - public void selectionAlgoTest6() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - int bgpId = 168427777; - short locRIBASNum = 100; - boolean isIbgp = true; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - bgpId = 536936448; - locRIBASNum = 200; - isIbgp = false; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, false, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(-1)); - } - - /** - * firstPathAttribute has lower BGPID than secondPathAttribute. - */ - @Test - public void selectionAlgoTest7() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //A0A0A00 - Integer bgpId = 168430080; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //B0A0A00 - bgpId = 185207296; - locRIBASNum = 200; - isIbgp = false; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(1)); - } - - /** - * secondPathAttribute has lowest peer address than firstPathAttribute. - */ - @Test - public void selectionAlgoTest8() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //A0A0A00 - Integer bgpId = 168430080; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //A0A0A00 - bgpId = 168430080; - locRIBASNum = 200; - isIbgp = false; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(-1)); - } - - /** - * firstPathAttribute and secondPathAttribute are same. - */ - @Test - public void selectionAlgoTest9() throws BgpParseException { - - byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes1 = new LinkedList<>(); - BgpValueType pathAttribute1; - byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute1 = Origin.read(buffer); - pathAttributes1.add(pathAttribute1); - byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute1 = AsPath.read(buffer); - pathAttributes1.add(pathAttribute1); - - IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //A0A0A00 - Integer bgpId = 168430080; - short locRIBASNum = 100; - boolean isIbgp = false; - PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); - attrList1.setIdentifier(0); - attrList1.setPathAttribute(pathAttributes1); - attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); - PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); - - peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; - LinkedList pathAttributes2 = new LinkedList<>(); - BgpValueType pathAttribute2; - origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; - buffer = ChannelBuffers.dynamicBuffer(); - buffer.writeBytes(origin); - pathAttribute2 = Origin.read(buffer); - pathAttributes2.add(pathAttribute2); - asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, - (byte) 0xe9 }; - buffer.writeBytes(asPath); - pathAttribute2 = AsPath.read(buffer); - pathAttributes2.add(pathAttribute2); - - ipAddress = IpAddress.valueOf(Version.INET, peerIp); - //A0A0A00 - bgpId = 168430080; - locRIBASNum = 200; - isIbgp = false; - PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); - attrList2.setIdentifier(0); - attrList2.setPathAttribute(pathAttributes2); - attrList2.setProtocolID(ProtocolType.OSPF_V2); - PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( - ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); - BgpSelectionAlgo algo = new BgpSelectionAlgo(); - int result = algo.compare(list1, list2); - assertThat(result, is(0)); - } -} diff --git a/framework/src/onos/bgp/pom.xml b/framework/src/onos/bgp/pom.xml deleted file mode 100755 index 941168ba..00000000 --- a/framework/src/onos/bgp/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - 4.0.0 - - - org.onosproject - onos - 1.4.0-SNAPSHOT - ../pom.xml - - - onos-bgp - pom - - ONOS BGP Protocol subsystem - - - api - ctl - bgpio - - - - - org.onosproject - onlab-misc - - - org.onosproject - onlab-junit - - - - - - - org.apache.felix - maven-bundle-plugin - - - - - diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java index ee6d31b8..2b25744b 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java @@ -119,7 +119,7 @@ public class GroupsListCommand extends AbstractShellCommand { } private void printGroups(DeviceId deviceId, List groups) { - print("deviceId=%s", deviceId); + print("deviceId=%s, groupCount=%s", deviceId, groups.size()); for (Group group : groups) { print(FORMAT, Integer.toHexString(group.id().id()), group.state(), group.type(), group.bytes(), group.packets(), group.appId().name()); diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java index 4fd9b0df..ae4e410c 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java @@ -17,6 +17,7 @@ package org.onosproject.cli.net; import com.google.common.collect.Sets; +import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; import org.onlab.packet.MacAddress; @@ -36,11 +37,15 @@ import java.util.Set; description = "Adds a new configured interface") public class InterfaceAddCommand extends AbstractShellCommand { - @Option(name = "-c", aliases = "--connectPoint", + @Argument(index = 0, name = "port", description = "Device port that the interface is associated with", required = true, multiValued = false) private String connectPoint = null; + @Argument(index = 1, name = "name", description = "Interface name", + required = true, multiValued = false) + private String name = null; + @Option(name = "-m", aliases = "--mac", description = "MAC address of the interface", required = false, multiValued = false) @@ -72,10 +77,13 @@ public class InterfaceAddCommand extends AbstractShellCommand { VlanId vlanId = vlan == null ? VlanId.NONE : VlanId.vlanId(Short.parseShort(vlan)); - Interface intf = new Interface(ConnectPoint.deviceConnectPoint(connectPoint), + Interface intf = new Interface(name, + ConnectPoint.deviceConnectPoint(connectPoint), ipAddresses, macAddr, vlanId); interfaceService.add(intf); + + print("Interface added"); } } diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java index 941a65db..0a7b5a16 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceRemoveCommand.java @@ -18,7 +18,6 @@ package org.onosproject.cli.net; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; -import org.onlab.packet.VlanId; import org.onosproject.cli.AbstractShellCommand; import org.onosproject.incubator.net.intf.InterfaceAdminService; import org.onosproject.net.ConnectPoint; @@ -35,17 +34,23 @@ public class InterfaceRemoveCommand extends AbstractShellCommand { required = true, multiValued = false) private String connectPoint = null; - @Argument(index = 1, name = "vlan", - description = "Interface vlan", + @Argument(index = 1, name = "name", + description = "Interface name", required = true, multiValued = false) - private String vlan = null; + private String name = null; @Override protected void execute() { InterfaceAdminService interfaceService = get(InterfaceAdminService.class); - interfaceService.remove(ConnectPoint.deviceConnectPoint(connectPoint), - VlanId.vlanId(Short.parseShort(vlan))); + boolean success = interfaceService.remove( + ConnectPoint.deviceConnectPoint(connectPoint), name); + + if (success) { + print("Interface removed"); + } else { + print("Unable to remove interface"); + } } } diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java index aa93eb94..fb3e68c2 100644 --- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java +++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java @@ -17,6 +17,8 @@ package org.onosproject.cli.net; import com.google.common.collect.Lists; import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; import org.onosproject.cli.AbstractShellCommand; import org.onosproject.cli.Comparators; import org.onosproject.incubator.net.intf.Interface; @@ -32,8 +34,12 @@ import java.util.List; description = "Lists all configured interfaces.") public class InterfacesListCommand extends AbstractShellCommand { - private static final String FORMAT = - "port=%s/%s, ips=%s, mac=%s, vlan=%s"; + private static final String FORMAT = "%s: port=%s/%s"; + private static final String IP_FORMAT = " ips="; + private static final String MAC_FORMAT = " mac="; + private static final String VLAN_FORMAT = " vlan="; + + private static final String NO_NAME = "(unamed)"; @Override protected void execute() { @@ -43,10 +49,32 @@ public class InterfacesListCommand extends AbstractShellCommand { Collections.sort(interfaces, Comparators.INTERFACES_COMPARATOR); - for (Interface intf : interfaces) { - print(FORMAT, intf.connectPoint().deviceId(), intf.connectPoint().port(), - intf.ipAddresses(), intf.mac(), intf.vlan()); + interfaces.forEach(this::printInterface); + } + + private void printInterface(Interface intf) { + StringBuilder formatStringBuilder = new StringBuilder(FORMAT); + + if (!intf.ipAddresses().isEmpty()) { + formatStringBuilder.append(IP_FORMAT); + formatStringBuilder.append(intf.ipAddresses().toString()); + } + + if (!intf.mac().equals(MacAddress.NONE)) { + formatStringBuilder.append(MAC_FORMAT); + formatStringBuilder.append(intf.mac().toString()); + } + + if (!intf.vlan().equals(VlanId.NONE)) { + formatStringBuilder.append(VLAN_FORMAT); + formatStringBuilder.append(intf.vlan().toString()); } + + String name = (intf.name().equals(Interface.NO_INTERFACE_NAME)) ? + NO_NAME : intf.name(); + + print(formatStringBuilder.toString(), name, intf.connectPoint().deviceId(), + intf.connectPoint().port()); } } diff --git a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 1f350c5b..b50c8bf7 100644 --- a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -358,15 +358,16 @@ - - - - + + + + + @@ -505,4 +506,6 @@ + + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java index 8c5fb790..38b599de 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java @@ -25,7 +25,6 @@ package org.onosproject.net; */ public final class AnnotationKeys { - // Prohibit instantiation private AnnotationKeys() { } @@ -80,6 +79,12 @@ public final class AnnotationKeys { */ public static final String DURABLE = "durable"; + /** + * Annotation key for link metric; used by + * {@link org.onosproject.net.topology.MetricLinkWeight} function. + */ + public static final String METRIC = "metric"; + /** * Annotation key for latency. * @@ -107,13 +112,24 @@ public final class AnnotationKeys { */ public static final String PORT_NAME = "portName"; + /** + * Annotation key for the port mac. + */ + public static final String PORT_MAC = "portMac"; + /** * Annotation key for the router ID. */ public static final String ROUTER_ID = "routerId"; + /** + * Annotation key for the static lambda. + */ public static final String STATIC_LAMBDA = "staticLambda"; + /** + * Annotation key for the static port. + */ public static final String STATIC_PORT = "staticPort"; /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java new file mode 100644 index 00000000..e605dcfd --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.net; + +import java.util.Comparator; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Comparator implementation for OchSignal. Assumes identical grid type and channel spacing. + */ +public class DefaultOchSignalComparator implements Comparator { + @Override + public int compare(OchSignal o1, OchSignal o2) { + checkNotNull(o1.gridType()); + checkNotNull(o1.channelSpacing()); + + checkArgument(o1.gridType().equals(o2.gridType())); + checkArgument(o1.channelSpacing().equals(o2.channelSpacing())); + + return o1.spacingMultiplier() * o1.slotGranularity() - o2.spacingMultiplier() * o2.slotGranularity(); + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshContextHeader.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshContextHeader.java new file mode 100644 index 00000000..745b616f --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshContextHeader.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.net; + +import java.util.Objects; + +import com.google.common.base.MoreObjects; + +/* + * Representation of NSH context header value + */ +public final class NshContextHeader { + + private final int nshContextHeader; + + /** + * Default constructor. + * + * @param nshContextHeader nsh context header value. + */ + private NshContextHeader(int nshContextHeader) { + this.nshContextHeader = nshContextHeader; + } + + /** + * Returns the NshContextHeader by setting its value. + * + * @param nshContextHeader nsh context header value. + * @return NshContextHeader + */ + public static NshContextHeader of(int nshContextHeader) { + return new NshContextHeader(nshContextHeader); + } + + + /** + * Returns nsh context header value. + * + * @return the nsh context header + */ + public int nshContextHeader() { + return nshContextHeader; + } + + + @Override + public int hashCode() { + return Objects.hash(nshContextHeader); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof NshContextHeader)) { + return false; + } + final NshContextHeader other = (NshContextHeader) obj; + return Objects.equals(this.nshContextHeader, other.nshContextHeader); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("nshContextHeader", nshContextHeader) + .toString(); + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServiceIndex.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServiceIndex.java new file mode 100644 index 00000000..7e0c914c --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServiceIndex.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.net; + +import java.util.Objects; + +import com.google.common.base.MoreObjects; + +/* + * Representation of NSH Service index + */ +public final class NshServiceIndex { + private static final short MASK = 0xFF; + private final short serviceIndex; + + /** + * Default constructor. + * + * @param serviceIndex nsh service index + */ + private NshServiceIndex(short serviceIndex) { + this.serviceIndex = (short) (serviceIndex & MASK); + } + + /** + * Returns the NshServiceIndex by setting its value. + * + * @param serviceIndex nsh service index + * @return NshServiceIndex + */ + public static NshServiceIndex of(short serviceIndex) { + return new NshServiceIndex(serviceIndex); + } + + + /** + * Returns nsh service index value. + * + * @return the nsh service index + */ + public short serviceIndex() { + return serviceIndex; + } + + + @Override + public int hashCode() { + return Objects.hash(serviceIndex); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof NshServiceIndex)) { + return false; + } + final NshServiceIndex other = (NshServiceIndex) obj; + return Objects.equals(this.serviceIndex, other.serviceIndex); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("serviceIndex", serviceIndex) + .toString(); + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServicePathId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServicePathId.java new file mode 100644 index 00000000..16fbc4e7 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NshServicePathId.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.net; + +import java.util.Objects; + +import com.google.common.base.MoreObjects; + +/* + * Representation of NSH Service path Identifier + */ +public final class NshServicePathId { + + private final int servicePathId; + + /** + * Default constructor. + * + * @param servicePathId nsh service path identifier + */ + private NshServicePathId(int servicePathId) { + this.servicePathId = servicePathId; + } + + /** + * Returns the NshServicePathId by setting its value. + * + * @param servicePathId nsh service path identifier + * @return NshServicePathId + */ + public static NshServicePathId of(int servicePathId) { + return new NshServicePathId(servicePathId); + } + + + /** + * Returns nsh context service path identifier. + * + * @return the nsh context service path id + */ + public int servicePathId() { + return servicePathId; + } + + + @Override + public int hashCode() { + return Objects.hash(servicePathId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof NshServicePathId)) { + return false; + } + final NshServicePathId other = (NshServicePathId) obj; + return Objects.equals(this.servicePathId, other.servicePathId); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("servicePathId", servicePathId) + .toString(); + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java index eb956f2a..94d4d321 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java @@ -87,7 +87,9 @@ public class OchPort extends DefaultPort { if (this == obj) { return true; } - if (obj instanceof OchPort) { + + // Subclass is considered as a change of identity, hence equals() will return false if class type don't match + if (obj != null && getClass() == obj.getClass()) { final OchPort other = (OchPort) obj; return Objects.equals(this.element().id(), other.element().id()) && Objects.equals(this.number(), other.number()) && diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java index 5a5af34a..3adc9086 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java @@ -17,6 +17,7 @@ package org.onosproject.net; import com.google.common.base.MoreObjects; import org.onlab.util.Frequency; +import org.onlab.util.Spectrum; import java.util.Objects; @@ -32,7 +33,6 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class OchSignal implements Lambda { - public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1); public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5); private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM; private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ; @@ -78,7 +78,7 @@ public class OchSignal implements Lambda { this.gridType = DEFAULT_OCH_GRIDTYPE; this.channelSpacing = DEFAULT_CHANNEL_SPACING; - this.spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz()); + this.spacingMultiplier = (int) (centerFrequency.subtract(Spectrum.CENTER_FREQUENCY).asHz() / grid.asHz()); this.slotGranularity = (int) Math.round((double) grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz()); } @@ -86,7 +86,7 @@ public class OchSignal implements Lambda { this.gridType = DEFAULT_OCH_GRIDTYPE; this.channelSpacing = channelSpacing; this.spacingMultiplier = (int) Math.round((double) centerFrequency. - subtract(OchSignal.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz()); + subtract(Spectrum.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz()); this.slotGranularity = slotGranularity; } @@ -132,7 +132,7 @@ public class OchSignal implements Lambda { * @return frequency in MHz */ public Frequency centralFrequency() { - return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier)); + return Spectrum.CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier)); } /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java index e5602f36..f51393a4 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java @@ -71,7 +71,7 @@ public class OduCltPort extends DefaultPort { if (this == obj) { return true; } - if (obj instanceof OduCltPort) { + if (obj != null && getClass() == obj.getClass()) { final OduCltPort other = (OduCltPort) obj; return Objects.equals(this.element().id(), other.element().id()) && Objects.equals(this.number(), other.number()) && diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java index 753834b5..d37fe75d 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java @@ -102,7 +102,7 @@ public class OmsPort extends DefaultPort { if (this == obj) { return true; } - if (obj instanceof OmsPort) { + if (obj != null && getClass() == obj.getClass()) { final OmsPort other = (OmsPort) obj; return Objects.equals(this.element().id(), other.element().id()) && Objects.equals(this.number(), other.number()) && diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java new file mode 100644 index 00000000..d45dd53c --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.behaviour; + +import com.google.common.annotations.Beta; +import org.onosproject.net.driver.HandlerBehaviour; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; + +/** + * Provides access to the extension selectors implemented by this driver. + */ +@Beta +public interface ExtensionSelectorResolver extends HandlerBehaviour { + + /** + * Gets an extension selector instance of the specified type, if supported + * by the driver. + * + * @param type type of extension to get + * @return extension selector + * @throws UnsupportedOperationException if the extension type is not + * supported by this driver + */ + ExtensionSelector getExtensionSelector(ExtensionSelectorType type); +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionTreatmentResolver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionTreatmentResolver.java index 85f0216d..8ca05af3 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionTreatmentResolver.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionTreatmentResolver.java @@ -22,13 +22,13 @@ import org.onosproject.net.flow.instructions.ExtensionTreatment; import org.onosproject.net.flow.instructions.ExtensionTreatmentType; /** - * Provides access to the extension implemented by this driver. + * Provides access to the extension treatments implemented by this driver. */ @Beta public interface ExtensionTreatmentResolver extends HandlerBehaviour { /** - * Gets an extension instruction instance of the specified type, if supported + * Gets an extension treatment instance of the specified type, if supported * by the driver. * * @param type type of extension to get diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/LambdaQuery.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/LambdaQuery.java new file mode 100644 index 00000000..e3b1d963 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/LambdaQuery.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.behaviour; + +import com.google.common.annotations.Beta; +import org.onosproject.net.OchSignal; +import org.onosproject.net.PortNumber; +import org.onosproject.net.driver.HandlerBehaviour; + +import java.util.SortedSet; + +/** + * A HandlerBehaviour to retrieve available wavelength resources. + */ +@Beta +public interface LambdaQuery extends HandlerBehaviour { + + // Currently returns set of FLEX GridType ochSignal instances + /** + * Returns set of Lambda instances which can be used at the port. + * + * @param port to be checked for the available resources. + * @return Set of OchSignals which can be used at the port. + */ + SortedSet queryLambdas(PortNumber port); +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java index 2fe2b2c0..92946312 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java @@ -15,13 +15,83 @@ */ package org.onosproject.net.config.basics; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.onlab.packet.IpAddress; +import org.onosproject.net.ConnectPoint; import org.onosproject.net.HostId; +import java.util.HashSet; +import java.util.Set; /** * Basic configuration for network end-station hosts. */ public class BasicHostConfig extends BasicElementConfig { + private static final String IPS = "ips"; + private static final String LOCATION = "location"; - // TODO: determine what aspects of configuration to add for hosts + @Override + public boolean isValid() { + return hasOnlyFields(IPS, LOCATION) && + this.location() != null && + this.ipAddresses() != null; + } + /** + * Gets location of the host. + * + * @return location of the host. Or null if not specified with correct format. + */ + public ConnectPoint location() { + String location = get(LOCATION, null); + + if (location != null) { + try { + return ConnectPoint.deviceConnectPoint(location); + } catch (Exception e) { + return null; + } + } + return null; + } + + /** + * Sets the location of the host. + * + * @param location location of the host. + * @return the config of the host. + */ + public BasicHostConfig setLocation(String location) { + return (BasicHostConfig) setOrClear(LOCATION, location); + } + + /** + * Gets IP addresses of the host. + * + * @return IP addresses of the host. Or null if not specified with correct format. + */ + public Set ipAddresses() { + HashSet ipAddresses = new HashSet<>(); + if (object.has(IPS)) { + ArrayNode ipNodes = (ArrayNode) object.path(IPS); + try { + ipNodes.forEach(ipNode -> { + ipAddresses.add(IpAddress.valueOf(ipNode.asText())); + }); + return ipAddresses; + } catch (Exception e) { + return null; + } + } + return null; + } + + /** + * Sets the IP addresses of the host. + * + * @param ipAddresses IP addresses of the host. + * @return the config of the host. + */ + public BasicHostConfig setIps(Set ipAddresses) { + return (BasicHostConfig) setOrClear(IPS, ipAddresses); + } } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java index e962110c..ed807b8f 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java @@ -15,22 +15,32 @@ */ package org.onosproject.net.config.basics; +import com.fasterxml.jackson.databind.JsonNode; import org.onosproject.net.Link; import org.onosproject.net.LinkKey; -import com.fasterxml.jackson.databind.JsonNode; import java.time.Duration; +import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL; + /** * Basic configuration for network infrastructure link. */ public class BasicLinkConfig extends AllowedEntityConfig { public static final String TYPE = "type"; + public static final String METRIC = "metric"; public static final String LATENCY = "latency"; public static final String BANDWIDTH = "bandwidth"; public static final String IS_DURABLE = "durable"; + @Override + public boolean isValid() { + return hasOnlyFields(TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE) && + isNumber(METRIC, OPTIONAL) && isNumber(LATENCY, OPTIONAL) && + isNumber(BANDWIDTH, OPTIONAL); + } + /** * Returns the link type. * @@ -50,6 +60,27 @@ public class BasicLinkConfig extends AllowedEntityConfig { return (BasicLinkConfig) setOrClear(TYPE, type); } + /** + * Returns link metric value for use by + * {@link org.onosproject.net.topology.MetricLinkWeight} function. + * + * @return link metric; -1 if not set + */ + public double metric() { + return get(METRIC, -1); + } + + /** + * Sets the link metric for use by + * {@link org.onosproject.net.topology.MetricLinkWeight} function. + * + * @param metric new metric; null to clear + * @return self + */ + public BasicLinkConfig metric(Double metric) { + return (BasicLinkConfig) setOrClear(METRIC, metric); + } + /** * Returns link latency in terms of nanos. * diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java new file mode 100644 index 00000000..b48d69ce --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.flow; + +import org.onosproject.net.flow.instructions.ExtensionPropertyException; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * Abstract implementation of the set/get property methods of Extension. + */ +public abstract class AbstractExtension implements Extension { + + private static final String INVALID_KEY = "Invalid property key: "; + private static final String INVALID_TYPE = "Given type does not match field type: "; + + @Override + public void setPropertyValue(String key, T value) throws + ExtensionPropertyException { + Class clazz = this.getClass(); + try { + Field field = clazz.getDeclaredField(key); + field.setAccessible(true); + field.set(this, value); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new ExtensionPropertyException(INVALID_KEY + key); + } + } + + @Override + public T getPropertyValue(String key) throws ExtensionPropertyException { + Class clazz = this.getClass(); + try { + Field field = clazz.getDeclaredField(key); + field.setAccessible(true); + @SuppressWarnings("unchecked") + T result = (T) field.get(this); + return result; + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new ExtensionPropertyException(INVALID_KEY + key); + } catch (ClassCastException e) { + throw new ExtensionPropertyException(INVALID_TYPE + key); + } + } + + @Override + public List getProperties() { + Class clazz = this.getClass(); + + List fields = new ArrayList<>(); + + for (Field field : clazz.getDeclaredFields()) { + fields.add(field.getName()); + } + + return fields; + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java index d3c2449c..0525d8fa 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java @@ -15,14 +15,8 @@ */ package org.onosproject.net.flow; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; - +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableSet; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; import org.onlab.packet.IpPrefix; @@ -30,12 +24,19 @@ import org.onlab.packet.MacAddress; import org.onlab.packet.MplsLabel; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; +import org.onosproject.net.DeviceId; import org.onosproject.net.PortNumber; import org.onosproject.net.flow.criteria.Criteria; import org.onosproject.net.flow.criteria.Criterion; +import org.onosproject.net.flow.criteria.ExtensionSelector; -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableSet; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; /** * Default traffic selector implementation. @@ -378,6 +379,12 @@ public final class DefaultTrafficSelector implements TrafficSelector { return add(Criteria.matchArpOp(arpOp)); } + @Override + public TrafficSelector.Builder extension(ExtensionSelector extensionSelector, + DeviceId deviceId) { + return add(Criteria.extension(extensionSelector, deviceId)); + } + @Override public TrafficSelector build() { return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values())); diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java index 22bff7dd..40291f57 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java @@ -488,6 +488,21 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { return add(Instructions.modUdpDst(port)); } + @Override + public Builder setArpSpa(IpAddress addr) { + return add(Instructions.modArpSpa(addr)); + } + + @Override + public Builder setArpSha(MacAddress addr) { + return add(Instructions.modArpSha(addr)); + } + + @Override + public Builder setArpOp(short op) { + return add(Instructions.modL3ArpOp(op)); + } + @Override public TrafficTreatment.Builder extension(ExtensionTreatment extension, DeviceId deviceId) { diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Extension.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Extension.java new file mode 100644 index 00000000..1d61542e --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Extension.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.flow; + +import org.onosproject.net.flow.instructions.ExtensionPropertyException; + +import java.util.List; + +/** + * An extension to the northbound APIs. + */ +public interface Extension { + + /** + * Sets a property on the extension. + * + * @param key property key + * @param value value to set for the given key + * @param class of the value + * @throws ExtensionPropertyException if the given key is not a valid + * property on this extension + */ + void setPropertyValue(String key, T value) throws ExtensionPropertyException; + + /** + * Gets a property value of an extension. + * + * @param key property key + * @param class of the value + * @return value of the property + * @throws ExtensionPropertyException if the given key is not a valid + * property on this extension + */ + T getPropertyValue(String key) throws ExtensionPropertyException; + + /** + * Gets a list of all properties on the extension. + * + * @return list of properties + */ + List getProperties(); + + /** + * Serialize the extension to a byte array. + * + * @return byte array + */ + byte[] serialize(); + + /** + * Deserialize the extension from a byte array. The properties + * of this object will be overwritten with the data in the byte array. + * + * @param data input byte array + */ + void deserialize(byte[] data); +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java index b92281f5..0d055add 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java @@ -15,8 +15,6 @@ */ package org.onosproject.net.flow; -import java.util.Set; - import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; import org.onlab.packet.IpPrefix; @@ -24,8 +22,12 @@ import org.onlab.packet.MacAddress; import org.onlab.packet.MplsLabel; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; +import org.onosproject.net.DeviceId; import org.onosproject.net.PortNumber; import org.onosproject.net.flow.criteria.Criterion; +import org.onosproject.net.flow.criteria.ExtensionSelector; + +import java.util.Set; /** * Abstraction of a slice of network traffic. @@ -426,6 +428,15 @@ public interface TrafficSelector { */ Builder matchArpOp(int arpOp); + /** + * Uses an extension selector. + * + * @param extensionSelector extension selector + * @param deviceId device ID + * @return a selection builder + */ + Builder extension(ExtensionSelector extensionSelector, DeviceId deviceId); + /** * Builds an immutable traffic selector. * diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java index 06b6ffa0..3e57925d 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java @@ -423,6 +423,30 @@ public interface TrafficTreatment { */ Builder setUdpDst(TpPort port); + /** + * Sets the arp src ip address. + * + * @param addr an ip + * @return a treatment builder + */ + Builder setArpSpa(IpAddress addr); + + /** + * Sets the arp src mac address. + * + * @param addr a macaddress + * @return a treatment builder + */ + Builder setArpSha(MacAddress addr); + + /** + * Sets the arp operation. + * + * @param op the value of arp operation. + * @return a treatment builder. + */ + Builder setArpOp(short op); + /** * Uses an extension treatment. * diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java index a28a4ab9..c94b1e02 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java @@ -23,6 +23,7 @@ import org.onlab.packet.MacAddress; import org.onlab.packet.MplsLabel; import org.onlab.packet.TpPort; import org.onlab.packet.VlanId; +import org.onosproject.net.DeviceId; import org.onosproject.net.IndexedLambda; import org.onosproject.net.Lambda; import org.onosproject.net.OchSignal; @@ -579,6 +580,33 @@ public final class Criteria { return new ArpOpCriterion(arpOp, Type.ARP_OP); } + /** + * Creates a match on PBB I-SID field using the specific value. + * + * @param pbbIsid PBB I-SID + * @return match criterion + */ + public static Criterion matchPbbIsid(int pbbIsid) { + return new PbbIsidCriterion(pbbIsid); + } + + /** + * Creates an extension criterion for the specified extension selector. + * + * @param extensionSelector extension selector + * @param deviceId device ID + * @return match criterion + */ + public static Criterion extension(ExtensionSelector extensionSelector, + DeviceId deviceId) { + return new ExtensionCriterion(extensionSelector, deviceId); + } + + /** + * Creates a dummy criterion. + * + * @return match criterion + */ public static Criterion dummy() { return new DummyCriterion(); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java index 26665246..17557b9d 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java @@ -177,6 +177,9 @@ public interface Criterion { /** ODU (Optical channel Data Unit) signal type. */ ODU_SIGTYPE, + /** Extension criterion. */ + EXTENSION, + /** An empty criterion. */ DUMMY } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java new file mode 100644 index 00000000..646b4184 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java @@ -0,0 +1,92 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.flow.criteria; + +import org.onosproject.net.DeviceId; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Criterion for implementing selector extensions. + */ +public class ExtensionCriterion implements Criterion { + + private final ExtensionSelector extensionSelector; + private final DeviceId deviceId; + + /** + * Constructor. + * + * @param extensionSelector extension selector + */ + public ExtensionCriterion(ExtensionSelector extensionSelector, DeviceId deviceId) { + this.extensionSelector = extensionSelector; + this.deviceId = deviceId; + } + + /** + * Returns the extension selector. + * + * @return extension selector + */ + public ExtensionSelector extensionSelector() { + return extensionSelector; + } + + /** + * Returns the device ID. + * + * @return device ID + */ + public DeviceId deviceId() { + return deviceId; + } + + @Override + public Type type() { + return Type.EXTENSION; + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("extensionSelector", extensionSelector.toString()) + .add("deviceId", deviceId) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type().ordinal(), extensionSelector, deviceId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ExtensionCriterion) { + ExtensionCriterion that = (ExtensionCriterion) obj; + return Objects.equals(extensionSelector, that.extensionSelector) && + Objects.equals(deviceId, that.deviceId) && + Objects.equals(this.type(), that.type()); + } + return false; + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java new file mode 100644 index 00000000..d3cebb37 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.flow.criteria; + +import org.onosproject.net.flow.Extension; + +/** + * An extension for the selector API. + */ +public interface ExtensionSelector extends Extension { + + /** + * Gets the type of the extension selector. + * + * @return type + */ + ExtensionSelectorType type(); +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java new file mode 100644 index 00000000..fa8f0923 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.flow.criteria; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; + +import java.util.Objects; + +/** + * Type of selector extensions. + */ +@Beta +public class ExtensionSelectorType { + + /** + * A list of well-known named extension selector type codes. + * These numbers have no impact on the actual OF type id. + */ + public enum ExtensionSelectorTypes { + NICIRA_MATCH_NSH_SPI(0), + NICIRA_MATCH_NSH_SI(1), + NICIRA_MATCH_NSH_CH1(2), + NICIRA_MATCH_NSH_CH2(3), + NICIRA_MATCH_NSH_CH3(4), + NICIRA_MATCH_NSH_CH4(5); + + + private ExtensionSelectorType type; + + /** + * Creates a new named extension selector type. + * + * @param type type code + */ + ExtensionSelectorTypes(int type) { + this.type = new ExtensionSelectorType(type); + } + + /** + * Gets the extension type object for this named type code. + * + * @return extension type object + */ + public ExtensionSelectorType type() { + return type; + } + } + + private final int type; + + /** + * Creates an extension type with the given int type code. + * + * @param type type code + */ + public ExtensionSelectorType(int type) { + this.type = type; + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ExtensionSelectorType) { + final ExtensionSelectorType that = (ExtensionSelectorType) obj; + return this.type == that.type; + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(ExtensionSelectorType.class) + .add("type", type) + .toString(); + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalIdCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalIdCriterion.java index cb513397..21018544 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalIdCriterion.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalIdCriterion.java @@ -74,7 +74,7 @@ public final class OduSignalIdCriterion implements Criterion { @Override public String toString() { - return toStringHelper(type().toString()) + return toStringHelper(this) .add("oduSignalId", oduSignalId) .toString(); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalTypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalTypeCriterion.java index d92880db..f4854339 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalTypeCriterion.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OduSignalTypeCriterion.java @@ -74,7 +74,7 @@ public final class OduSignalTypeCriterion implements Criterion { @Override public String toString() { - return toStringHelper(type().toString()) + return toStringHelper(this) .add("signalType", signalType) .toString(); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PbbIsidCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PbbIsidCriterion.java new file mode 100644 index 00000000..979aa6bd --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PbbIsidCriterion.java @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.net.flow.criteria; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Implementation of PBB I-SID criterion (24 bits unsigned integer). + */ +public final class PbbIsidCriterion implements Criterion { + private static final int MASK = 0xfffff; + private final int pbbIsid; // PBB I-SID: 24 bits + + /** + * Constructor. + * + * @param pbbIsid the PBB I-SID to match (24 bits) + */ + PbbIsidCriterion(int pbbIsid) { + this.pbbIsid = pbbIsid & MASK; + } + + @Override + public Criterion.Type type() { + return Criterion.Type.PBB_ISID; + } + + /** + * Gets the PBB I-SID to match. + * + * @return the PBB I-SID to match (24 bits) + */ + public int pbbIsid() { + return this.pbbIsid; + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("pbbIsid", Long.toHexString(pbbIsid)).toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type().ordinal(), pbbIsid); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PbbIsidCriterion) { + PbbIsidCriterion that = (PbbIsidCriterion) obj; + return Objects.equals(pbbIsid, that.pbbIsid) && + Objects.equals(this.type(), that.type()); + } + return false; + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java deleted file mode 100644 index ac7c771f..00000000 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.net.flow.instructions; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -/** - * Abstract implementation of the set/get property methods of ExtensionInstruction. - */ -public abstract class AbstractExtensionTreatment implements ExtensionTreatment { - - private static final String INVALID_KEY = "Invalid property key: "; - private static final String INVALID_TYPE = "Given type does not match field type: "; - - @Override - public void setPropertyValue(String key, T value) throws ExtensionPropertyException { - Class clazz = this.getClass(); - try { - Field field = clazz.getDeclaredField(key); - field.setAccessible(true); - field.set(this, value); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new ExtensionPropertyException(INVALID_KEY + key); - } - } - - @Override - public T getPropertyValue(String key) throws ExtensionPropertyException { - Class clazz = this.getClass(); - try { - Field field = clazz.getDeclaredField(key); - field.setAccessible(true); - @SuppressWarnings("unchecked") - T result = (T) field.get(this); - return result; - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new ExtensionPropertyException(INVALID_KEY + key); - } catch (ClassCastException e) { - throw new ExtensionPropertyException(INVALID_TYPE + key); - } - } - - @Override - public List getProperties() { - Class clazz = this.getClass(); - - List fields = new ArrayList<>(); - - for (Field field : clazz.getDeclaredFields()) { - fields.add(field.getName()); - } - - return fields; - } -} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java index 0e8885ed..3df152e9 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java @@ -16,63 +16,18 @@ package org.onosproject.net.flow.instructions; -import java.util.List; +import org.onosproject.net.flow.Extension; /** - * An extensible instruction type. + * An extension for the treatment API. */ -public interface ExtensionTreatment { +public interface ExtensionTreatment extends Extension { /** - * Gets the type of the extension instruction. + * Gets the type of the treatment extension. * * @return type */ ExtensionTreatmentType type(); - /** - * Sets a property on the extension instruction. - * - * @param key property key - * @param value value to set for the given key - * @param class of the value - * @throws ExtensionPropertyException if the given key is not a valid - * property on this extension instruction - */ - void setPropertyValue(String key, T value) throws ExtensionPropertyException; - - /** - * Gets a property value of an extension instruction. - * - * @param key property key - * @param class of the value - * @return value of the property - * @throws ExtensionPropertyException if the given key is not a valid - * property on this extension instruction - */ - T getPropertyValue(String key) throws ExtensionPropertyException; - - /** - * Gets a list of all properties on the extension instruction. - * - * @return list of properties - */ - List getProperties(); - - /** - * Serialize the extension instruction to a byte array. - * - * @return byte array - */ - byte[] serialize(); - - /** - * Deserialize the extension instruction from a byte array. The properties - * of this object will be overwritten with the data in the byte array. - * - * @param data input byte array - */ - void deserialize(byte[] data); - - } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java index 38fbc279..f597a46c 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java @@ -22,7 +22,7 @@ import com.google.common.base.MoreObjects; import java.util.Objects; /** - * Type of extension instructions. + * Type of treatment extensions. */ @Beta public final class ExtensionTreatmentType { @@ -32,15 +32,24 @@ public final class ExtensionTreatmentType { * These numbers have no impact on the actual OF type id. */ public enum ExtensionTreatmentTypes { - // TODO fix type numbers to include experimenter id NICIRA_SET_TUNNEL_DST(0), NICIRA_RESUBMIT(1), - NICIRA_SET_NSH_SPI(32); + NICIRA_RESUBMIT_TABLE(14), + NICIRA_SET_NSH_SPI(32), + NICIRA_SET_NSH_SI(33), + NICIRA_SET_NSH_CH1(34), + NICIRA_SET_NSH_CH2(35), + NICIRA_SET_NSH_CH3(36), + NICIRA_SET_NSH_CH4(37), + NICIRA_MOV_ARP_SHA_TO_THA(2), + NICIRA_MOV_ARP_SPA_TO_TPA(3), + NICIRA_MOV_ETH_SRC_TO_DST(4), + NICIRA_MOV_IP_SRC_TO_DST(5); private ExtensionTreatmentType type; /** - * Creates a new named extension instruction type. + * Creates a new named extension treatment type. * * @param type type code */ diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java index 4643b315..8ed882c8 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java @@ -35,6 +35,9 @@ import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSig import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType; import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlInstruction; import org.onosproject.net.flow.instructions.L4ModificationInstruction.L4SubType; @@ -298,6 +301,39 @@ public final class Instructions { return new ModTtlInstruction(L3SubType.TTL_IN); } + /** + * Creates a L3 ARP IP src modification. + * + * @param addr the ip address to modify to + * @return a L3 modification + */ + public static L3ModificationInstruction modArpSpa(IpAddress addr) { + checkNotNull(addr, "Src l3 ARP IP address cannot be null"); + return new ModArpIPInstruction(L3SubType.ARP_SPA, addr); + } + + /** + * Creates a l3 ARP Ether src modification. + * + * @param addr the mac address to modify to + * @return a l3 modification + */ + public static L3ModificationInstruction modArpSha(MacAddress addr) { + checkNotNull(addr, "Src l3 ARP address cannot be null"); + return new ModArpEthInstruction(L3SubType.ARP_SHA, addr); + } + + /** + * Creates a l3 ARP operation modification. + * + * @param op the ARP operation to modify to + * @return a l3 modification + */ + public static L3ModificationInstruction modL3ArpOp(short op) { + checkNotNull(op, "Arp operation cannot be null"); + return new ModArpOpInstruction(L3SubType.ARP_OP, op); + } + /** * Creates a push MPLS header instruction. * diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java index 41819504..0efe9a77 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java @@ -20,6 +20,7 @@ import static com.google.common.base.MoreObjects.toStringHelper; import java.util.Objects; import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; /** * Abstraction of a single traffic treatment step. @@ -68,7 +69,22 @@ public abstract class L3ModificationInstruction implements Instruction { /** * Copy TTL in. */ - TTL_IN + TTL_IN, + + /** + * ARP IP src modification. + */ + ARP_SPA, + + /** + * ARP Ether src modification. + */ + ARP_SHA, + + /** + * Arp operation modification. + */ + ARP_OP //TODO: remaining types } @@ -132,6 +148,150 @@ public abstract class L3ModificationInstruction implements Instruction { } } + /** + * Represents a L3 ARP IP src/dst modification instruction. + */ + public static final class ModArpIPInstruction extends L3ModificationInstruction { + + private final L3SubType subtype; + private final IpAddress ip; + + ModArpIPInstruction(L3SubType subType, IpAddress addr) { + + this.subtype = subType; + this.ip = addr; + } + + @Override + public L3SubType subtype() { + return this.subtype; + } + + public IpAddress ip() { + return this.ip; + } + + @Override + public String toString() { + return toStringHelper(subtype().toString()) + .add("ip", ip).toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), subtype(), ip); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ModArpIPInstruction) { + ModArpIPInstruction that = (ModArpIPInstruction) obj; + return Objects.equals(ip, that.ip) && + Objects.equals(this.subtype(), that.subtype()); + } + return false; + } + } + + /** + * Represents a L3 ARP Ether src/dst modification instruction. + */ + public static final class ModArpEthInstruction extends L3ModificationInstruction { + + private final L3SubType subtype; + private final MacAddress mac; + + ModArpEthInstruction(L3SubType subType, MacAddress addr) { + + this.subtype = subType; + this.mac = addr; + } + + @Override + public L3SubType subtype() { + return this.subtype; + } + + public MacAddress mac() { + return this.mac; + } + + @Override + public String toString() { + return toStringHelper(subtype().toString()) + .add("mac", mac).toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), subtype(), mac); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ModArpEthInstruction) { + ModArpEthInstruction that = (ModArpEthInstruction) obj; + return Objects.equals(mac, that.mac) && + Objects.equals(this.subtype(), that.subtype()); + } + return false; + } + } + + /** + * Represents a L3 ARP operation modification instruction. + */ + public static final class ModArpOpInstruction extends L3ModificationInstruction { + + private final L3SubType subtype; + private final short op; + + ModArpOpInstruction(L3SubType subType, short op) { + + this.subtype = subType; + this.op = op; + } + + @Override + public L3SubType subtype() { + return this.subtype; + } + + public long op() { + return this.op; + } + + @Override + public String toString() { + return toStringHelper(subtype().toString()) + .add("op", op).toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), subtype(), op); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ModArpOpInstruction) { + ModArpOpInstruction that = (ModArpOpInstruction) obj; + return Objects.equals(op, that.op) && + Objects.equals(this.subtype(), that.subtype()); + } + return false; + } + } + /** * Represents a L3 IPv6 Flow Label (RFC 6437) modification instruction * (20 bits unsigned integer). diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java index 06305bf7..4d9d7225 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java @@ -196,7 +196,7 @@ public final class DefaultFilteringObjective implements FilteringObjective { } @Override - public Builder setMeta(TrafficTreatment treatment) { + public Builder withMeta(TrafficTreatment treatment) { this.meta = treatment; return this; } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java index 4701589f..bd580507 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java @@ -181,7 +181,7 @@ public final class DefaultNextObjective implements NextObjective { } @Override - public Builder setMeta(TrafficSelector meta) { + public Builder withMeta(TrafficSelector meta) { this.meta = meta; return this; } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java index 29257c61..8ed793d0 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java @@ -133,7 +133,7 @@ public interface FilteringObjective extends Objective { * @param treatment traffic treatment to use * @return a filtering builder */ - Builder setMeta(TrafficTreatment treatment); + Builder withMeta(TrafficTreatment treatment); /** * Assigns an application id. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java index 08916eb2..36098d71 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java @@ -147,7 +147,7 @@ public interface NextObjective extends Objective { * @param selector match conditions * @return an objective builder */ - Builder setMeta(TrafficSelector selector); + Builder withMeta(TrafficSelector selector); /** * Builds the next objective that will be added. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentUtils.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentUtils.java new file mode 100644 index 00000000..f6e33b6b --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentUtils.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.intent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; + +/** + * Utilities for dealing with intents. + */ +public final class IntentUtils { + + private static final Logger log = LoggerFactory.getLogger(IntentUtils.class); + + private IntentUtils() { + } + + /** + * Checks if two intents represent the same value. + * + *

({@link Intent#equals(Object)} only checks ID equality)

+ * + *

Both intents must be of the same type.

+ * + * @param one first intent + * @param two second intent + * @return true if the two intents represent the same value, otherwise false + */ + public static boolean equals(Intent one, Intent two) { + if (one.getClass() != two.getClass()) { + return false; + } + + if (!(Objects.equals(one.appId(), two.appId()) && + Objects.equals(one.key(), two.key()))) { + return false; + } + + if (one instanceof SinglePointToMultiPointIntent) { + SinglePointToMultiPointIntent intent1 = (SinglePointToMultiPointIntent) one; + SinglePointToMultiPointIntent intent2 = (SinglePointToMultiPointIntent) two; + + return Objects.equals(intent1.selector(), intent2.selector()) && + Objects.equals(intent1.treatment(), intent2.treatment()) && + Objects.equals(intent1.ingressPoint(), intent2.ingressPoint()) && + Objects.equals(intent1.egressPoints(), intent2.egressPoints()); + } else if (one instanceof MultiPointToSinglePointIntent) { + MultiPointToSinglePointIntent intent1 = (MultiPointToSinglePointIntent) one; + MultiPointToSinglePointIntent intent2 = (MultiPointToSinglePointIntent) two; + + return Objects.equals(intent1.selector(), intent2.selector()) && + Objects.equals(intent1.treatment(), intent2.treatment()) && + Objects.equals(intent1.ingressPoints(), intent2.ingressPoints()) && + Objects.equals(intent1.egressPoint(), intent2.egressPoint()); + } else if (one instanceof PointToPointIntent) { + PointToPointIntent intent1 = (PointToPointIntent) one; + PointToPointIntent intent2 = (PointToPointIntent) two; + + return Objects.equals(intent1.selector(), intent2.selector()) && + Objects.equals(intent1.treatment(), intent2.treatment()) && + Objects.equals(intent1.ingressPoint(), intent2.ingressPoint()) && + Objects.equals(intent1.egressPoint(), intent2.egressPoint()); + } else { + log.error("Unimplemented intent type"); + return false; + } + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/mcast/MulticastRouteService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/mcast/MulticastRouteService.java index 56e87c55..bf65033a 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/mcast/MulticastRouteService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/mcast/MulticastRouteService.java @@ -16,6 +16,7 @@ package org.onosproject.net.mcast; import com.google.common.annotations.Beta; +import org.onosproject.event.ListenerService; import org.onosproject.net.ConnectPoint; import java.util.List; @@ -24,7 +25,8 @@ import java.util.List; * A service interface for maintaining multicast information. */ @Beta -public interface MulticastRouteService { +public interface MulticastRouteService + extends ListenerService { /** * Adds a route to the information base. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java index c0c4e34f..72f8ac01 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java @@ -18,6 +18,8 @@ package org.onosproject.net.newresource; import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; import java.util.LinkedList; import java.util.List; @@ -41,8 +43,8 @@ import static com.google.common.base.Preconditions.checkState; * A double value is associated with a continuous type value. * * Users of this class must keep the semantics of resources regarding the hierarchical structure. - * For example, resource path, Link:1/VLAN ID:100, is valid, but resource path, VLAN ID:100/Link:1 - * is not valid because a link is not a sub-component of a VLAN ID. + * For example, resource path, Device:1/Port:1/VLAN ID:100, is valid, but resource path, + * VLAN ID:100/Device:1/Port:1 is not valid because a link is not a sub-component of a VLAN ID. */ @Beta public abstract class ResourcePath { @@ -52,29 +54,73 @@ public abstract class ResourcePath { public static final Discrete ROOT = new Discrete(); + public static ResourcePath discrete(DeviceId device) { + return new Discrete(ImmutableList.of(device)); + } + /** * Creates an resource path which represents a discrete-type resource from the specified components. * - * @param components components of the path. The order represents hierarchical structure of the resource. + * @param device device ID which is the first component of the path + * @param components following components of the path. The order represents hierarchical structure of the resource. * @return resource path instance */ - public static ResourcePath discrete(Object... components) { - if (components.length == 0) { - return ROOT; - } else { - return new Discrete(ImmutableList.copyOf(components)); - } + public static ResourcePath discrete(DeviceId device, Object... components) { + return new Discrete(ImmutableList.builder() + .add(device) + .add(components) + .build()); + } + + /** + * Creates an resource path which represents a discrete-type resource from the specified components. + * + * @param device device ID which is the first component of the path + * @param port port number which is the second component of the path + * @param components following components of the path. The order represents hierarchical structure of the resource. + * @return resource path instance + */ + public static ResourcePath discrete(DeviceId device, PortNumber port, Object... components) { + return new Discrete(ImmutableList.builder() + .add(device) + .add(port) + .add(components) + .build()); } /** * Creates an resource path which represents a continuous-type resource from the specified components. * * @param value amount of the resource - * @param components components of the path. The order represents hierarchical structure of the resource. + * @param device device ID which is the first component of the path + * @param components following components of the path. The order represents hierarchical structure of the resource. + * @return resource path instance + */ + public static ResourcePath continuous(double value, DeviceId device, Object... components) { + checkArgument(components.length > 0, + "Length of components must be greater thant 0, but " + components.length); + + return new Continuous(ImmutableList.builder() + .add(device) + .add(components) + .build(), value); + } + + /** + * Creates an resource path which represents a continuous-type resource from the specified components. + * + * @param value amount of the resource + * @param device device ID which is the first component of the path. + * @param port port number which is the second component of the path. + * @param components following components of the path. The order represents hierarchical structure of the resource. * @return resource path instance */ - public static ResourcePath continuous(double value, Object... components) { - return new Continuous(ImmutableList.copyOf(components), value); + public static ResourcePath continuous(double value, DeviceId device, PortNumber port, Object... components) { + return new Continuous(ImmutableList.builder() + .add(device) + .add(port) + .add(components) + .build(), value); } /** @@ -82,7 +128,7 @@ public abstract class ResourcePath { * * @param components components of the path. The order represents hierarchical structure of the resource. */ - ResourcePath(List components) { + protected ResourcePath(List components) { checkNotNull(components); checkArgument(!components.isEmpty()); @@ -101,7 +147,7 @@ public abstract class ResourcePath { * @param parent the parent of this resource * @param last a child of the parent */ - ResourcePath(Discrete parent, Object last) { + protected ResourcePath(Discrete parent, Object last) { checkNotNull(parent); checkNotNull(last); diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java new file mode 100644 index 00000000..c966902e --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.topology; + +import org.onlab.util.GeoLocation; +import org.onosproject.net.AnnotationKeys; +import org.onosproject.net.Annotations; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceService; + +import static java.lang.Double.MAX_VALUE; + +/** + * Link weight for measuring link cost using the geo distance between link + * vertices as determined by the element longitude/latitude annotation. + */ +public class GeoDistanceLinkWeight implements LinkWeight { + + private static final double MAX_KM = 40_075 / 2.0; + + private final DeviceService deviceService; + + /** + * Creates a new link-weight with access to the specified device service. + * + * @param deviceService device service reference + */ + public GeoDistanceLinkWeight(DeviceService deviceService) { + this.deviceService = deviceService; + } + + @Override + public double weight(TopologyEdge edge) { + GeoLocation src = getLocation(edge.link().src().deviceId()); + GeoLocation dst = getLocation(edge.link().dst().deviceId()); + return src != null && dst != null ? src.kilometersTo(dst) : MAX_KM; + } + + private GeoLocation getLocation(DeviceId deviceId) { + Device d = deviceService.getDevice(deviceId); + Annotations a = d != null ? d.annotations() : null; + double latitude = getDouble(a, AnnotationKeys.LATITUDE); + double longitude = getDouble(a, AnnotationKeys.LONGITUDE); + return latitude == MAX_VALUE || longitude == MAX_VALUE ? null : + new GeoLocation(latitude, longitude); + } + + private double getDouble(Annotations a, String key) { + String value = a != null ? a.value(key) : null; + try { + return value != null ? Double.parseDouble(value) : MAX_VALUE; + } catch (NumberFormatException e) { + return MAX_VALUE; + } + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java new file mode 100644 index 00000000..c557016b --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java @@ -0,0 +1,36 @@ +package org.onosproject.net.topology; + +import static org.onosproject.net.Link.State.ACTIVE; +import static org.onosproject.net.Link.Type.INDIRECT; + +/** + * Link weight for measuring link cost as hop count with indirect links + * being as expensive as traversing the entire graph to assume the worst. + */ +public class HopCountLinkWeight implements LinkWeight { + private final int indirectLinkCost; + + /** + * Creates a new hop-count weight. + */ + public HopCountLinkWeight() { + this.indirectLinkCost = Short.MAX_VALUE; + } + + /** + * Creates a new hop-count weight with the specified cost of indirect links. + */ + public HopCountLinkWeight(int indirectLinkCost) { + this.indirectLinkCost = indirectLinkCost; + } + + @Override + public double weight(TopologyEdge edge) { + // To force preference to use direct paths first, make indirect + // links as expensive as the linear vertex traversal. + return edge.link().state() == + ACTIVE ? (edge.link().type() == + INDIRECT ? indirectLinkCost : 1) : -1; + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java new file mode 100644 index 00000000..8463e087 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java @@ -0,0 +1,36 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.topology; + +import org.onosproject.net.AnnotationKeys; + +/** + * Link weight for measuring link cost using the link metric annotation. + */ +public class MetricLinkWeight implements LinkWeight { + + @Override + public double weight(TopologyEdge edge) { + String v = edge.link().annotations().value(AnnotationKeys.METRIC); + try { + return v != null ? Double.parseDouble(v) : 1; + } catch (NumberFormatException e) { + return 1; + } + } +} + diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java new file mode 100644 index 00000000..9d077e1e --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java @@ -0,0 +1,44 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.net.topology; + +import org.onlab.graph.GraphPathSearch; + +/** + * Provides administrative abilities to tailor the path service behaviours. + */ +public interface PathAdminService { + + /** + * Sets the specified link-weight function to be used as a default. + * If null is specified, the builtin default hop-count link-weight will be + * used. + * + * @param linkWeight default link-weight function + */ + void setDefaultLinkWeight(LinkWeight linkWeight); + + /** + * Sets the specified graph path search algorightm to be used as a default. + * If null is specified, the builtin default all-shortest-paths Dijkstra + * algorithm will be used. + * + * @param graphPathSearch default graph path search algorithm + */ + void setDefaultGraphPathSearch(GraphPathSearch graphPathSearch); + +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java index 0bd4d75d..38954079 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java @@ -30,8 +30,9 @@ import java.util.Set; public interface PathService { /** - * Returns the set of all shortest paths, precomputed in terms of hop-count, - * between the specified source and destination elements. + * Returns the set of all shortest paths between the specified source and + * destination elements. The path is computed using the default edge-weight + * function, which by default is hop-count. * * @param src source element * @param dst destination element @@ -40,9 +41,9 @@ public interface PathService { Set getPaths(ElementId src, ElementId dst); /** - * Returns the set of all shortest paths, computed using the supplied - * edge-weight entity, between the specified source and destination - * network elements. + * Returns the set of all shortest paths between the specified source and + * destination network elements. The path is computed using the supplied + * edge-weight function. * * @param src source element * @param dst destination element @@ -52,8 +53,9 @@ public interface PathService { Set getPaths(ElementId src, ElementId dst, LinkWeight weight); /** - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, - * between the specified source and destination devices. + * Returns the set of all disjoint shortest path pairs between the + * specified source and destination elements. The path is computed using + * the default edge-weight function, which by default is hop-count. * * @param src source device * @param dst destination device @@ -62,8 +64,9 @@ public interface PathService { Set getDisjointPaths(ElementId src, ElementId dst); /** - * Returns the set of all disjoint shortest path pairs, computed using the supplied - * edge-weight entity, between the specified source and destination devices. + * Returns the set of all disjoint shortest path pairs between the + * specified source and destination elements. The path is computed using + * the supplied edge-weight function. * * @param src source device * @param dst destination device @@ -74,8 +77,10 @@ public interface PathService { LinkWeight weight); /** - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, - * between the specified source and destination devices. + * Returns the set of all disjoint shortest path pairs between the + * specified source and destination elements and taking into consideration + * the provided risk profile. The path is computed using the default + * edge-weight function, which by default is hop-count. * * @param src source device * @param dst destination device @@ -86,8 +91,10 @@ public interface PathService { Map riskProfile); /** - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, - * between the specified source and destination devices. + * Returns the set of all disjoint shortest path pairs between the + * specified source and destination elements and taking into consideration + * the provided risk profile. The path is computed using the supplied + * edge-weight function. * * @param src source device * @param dst destination device @@ -96,6 +103,7 @@ public interface PathService { * @return set of all shortest paths between the two devices */ Set getDisjointPaths(ElementId src, ElementId dst, - LinkWeight weight, Map riskProfile); + LinkWeight weight, + Map riskProfile); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java index 4030abdc..efe69f5f 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java @@ -131,6 +131,10 @@ public final class TopoJson { if (hh.subdued()) { n.put(SUBDUE, true); } + NodeBadge badge = hh.badge(); + if (badge != null) { + n.set(BADGE, json(badge)); + } return n; } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java index 56a6ff63..d113fb98 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java @@ -222,6 +222,12 @@ public class CriteriaTest { Criterion sameAsMatchMpls1 = Criteria.matchMplsLabel(mpls1); Criterion matchMpls2 = Criteria.matchMplsLabel(mpls2); + byte mplsTc1 = 1; + byte mplsTc2 = 2; + Criterion matchMplsTc1 = Criteria.matchMplsTc(mplsTc1); + Criterion sameAsMatchMplsTc1 = Criteria.matchMplsTc(mplsTc1); + Criterion matchMplsTc2 = Criteria.matchMplsTc(mplsTc2); + long tunnelId1 = 1; long tunnelId2 = 2; Criterion matchTunnelId1 = Criteria.matchTunnelId(tunnelId1); @@ -273,6 +279,12 @@ public class CriteriaTest { Criterion sameAsMatchOduSignalType1 = Criteria.matchOduSignalType(oduSigType1); Criterion matchOduSignalType2 = Criteria.matchOduSignalType(oduSigType2); + int pbbIsid1 = 1; + int pbbIsid2 = 2; + Criterion matchPbbIsid1 = Criteria.matchPbbIsid(pbbIsid1); + Criterion sameAsMatchPbbIsid1 = Criteria.matchPbbIsid(pbbIsid1); + Criterion matchPbbIsid2 = Criteria.matchPbbIsid(pbbIsid2); + /** * Checks that a Criterion object has the proper type, and then converts * it to the proper type. @@ -326,10 +338,12 @@ public class CriteriaTest { assertThatClassIsImmutable(IPv6NDTargetAddressCriterion.class); assertThatClassIsImmutable(IPv6NDLinkLayerAddressCriterion.class); assertThatClassIsImmutable(MplsCriterion.class); + assertThatClassIsImmutable(MplsTcCriterion.class); assertThatClassIsImmutable(IPv6ExthdrFlagsCriterion.class); assertThatClassIsImmutable(LambdaCriterion.class); assertThatClassIsImmutable(OduSignalIdCriterion.class); assertThatClassIsImmutable(OduSignalTypeCriterion.class); + assertThatClassIsImmutable(PbbIsidCriterion.class); } // PortCriterion class @@ -751,6 +765,19 @@ public class CriteriaTest { // TcpFlagsCriterion class + /** + * Test the matchTcpFlags method. + */ + @Test + public void testMatchTcpFlagsMethod() { + Criterion matchTcpFlag = Criteria.matchTcpFlags(tcpFlags1); + TcpFlagsCriterion tcpFlagsCriterion = + checkAndConvert(matchTcpFlag, + Criterion.Type.TCP_FLAGS, + TcpFlagsCriterion.class); + assertThat(tcpFlagsCriterion.flags(), is(equalTo(tcpFlags1))); + } + /** * Test the equals() method of the TcpFlagsCriterion class. */ @@ -1037,6 +1064,32 @@ public class CriteriaTest { .testEquals(); } + // MplsTcCriterion class + + /** + * Test the matchMplsTc method. + */ + @Test + public void testMatchMplsTcMethod() { + Criterion matchMplsTc = Criteria.matchMplsTc(mplsTc1); + MplsTcCriterion mplsTcCriterion = + checkAndConvert(matchMplsTc, + Criterion.Type.MPLS_TC, + MplsTcCriterion.class); + assertThat(mplsTcCriterion.tc(), is(equalTo(mplsTc1))); + } + + /** + * Test the equals() method of the MplsTcCriterion class. + */ + @Test + public void testMplsTcCriterionEquals() { + new EqualsTester() + .addEqualityGroup(matchMplsTc1, sameAsMatchMplsTc1) + .addEqualityGroup(matchMplsTc2) + .testEquals(); + } + // TunnelIdCriterion class /** @@ -1172,4 +1225,30 @@ public class CriteriaTest { .addEqualityGroup(matchOduSignalType2) .testEquals(); } + + // PbbIsidCriterion class + + /** + * Test the matchPbbIsid method. + */ + @Test + public void testMatchPbbIsidMethod() { + Criterion matchPbbIsid = Criteria.matchPbbIsid(pbbIsid1); + PbbIsidCriterion pbbIsidCriterion = + checkAndConvert(matchPbbIsid, + Criterion.Type.PBB_ISID, + PbbIsidCriterion.class); + assertThat(pbbIsidCriterion.pbbIsid(), is(equalTo(pbbIsid1))); + } + + /** + * Test the equals() method of the PbbIsidCriterion class. + */ + @Test + public void testPbbIsidCriterionEquals() { + new EqualsTester() + .addEqualityGroup(matchPbbIsid1, sameAsMatchPbbIsid1) + .addEqualityGroup(matchPbbIsid2) + .testEquals(); + } } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java index 5f448221..d21c4b1b 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java @@ -18,9 +18,7 @@ package org.onosproject.net.newresource; import com.google.common.testing.EqualsTester; import org.junit.Test; import org.onlab.packet.VlanId; -import org.onosproject.net.ConnectPoint; import org.onosproject.net.DeviceId; -import org.onosproject.net.LinkKey; import org.onosproject.net.PortNumber; import org.onosproject.net.intent.IntentId; @@ -29,18 +27,14 @@ public class ResourceAllocationTest { private static final DeviceId D1 = DeviceId.deviceId("of:001"); private static final DeviceId D2 = DeviceId.deviceId("of:002"); private static final PortNumber P1 = PortNumber.portNumber(1); - private static final ConnectPoint CP1_1 = new ConnectPoint(D1, P1); - private static final ConnectPoint CP2_1 = new ConnectPoint(D2, P1); private static final VlanId VLAN1 = VlanId.vlanId((short) 100); private static final IntentId IID1 = IntentId.valueOf(30); - private static final LinkKey LK1 = LinkKey.linkKey(CP1_1, CP2_1); - private static final LinkKey LK2 = LinkKey.linkKey(CP2_1, CP1_1); @Test public void testEquals() { - ResourceAllocation alloc1 = new ResourceAllocation(ResourcePath.discrete(LK1, VLAN1), IID1); - ResourceAllocation sameAsAlloc1 = new ResourceAllocation(ResourcePath.discrete(LK1, VLAN1), IID1); - ResourceAllocation alloc2 = new ResourceAllocation(ResourcePath.discrete(LK2, VLAN1), IID1); + ResourceAllocation alloc1 = new ResourceAllocation(ResourcePath.discrete(D1, P1, VLAN1), IID1); + ResourceAllocation sameAsAlloc1 = new ResourceAllocation(ResourcePath.discrete(D1, P1, VLAN1), IID1); + ResourceAllocation alloc2 = new ResourceAllocation(ResourcePath.discrete(D2, P1, VLAN1), IID1); new EqualsTester() .addEqualityGroup(alloc1, sameAsAlloc1) diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java index 35dcf1ec..4bbb458c 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java @@ -19,9 +19,7 @@ import com.google.common.testing.EqualsTester; import org.junit.Test; import org.onlab.packet.VlanId; import org.onlab.util.Bandwidth; -import org.onosproject.net.ConnectPoint; import org.onosproject.net.DeviceId; -import org.onosproject.net.LinkKey; import org.onosproject.net.PortNumber; import java.util.Optional; @@ -35,19 +33,17 @@ public class ResourcePathTest { private static final DeviceId D1 = DeviceId.deviceId("of:001"); private static final DeviceId D2 = DeviceId.deviceId("of:002"); private static final PortNumber P1 = PortNumber.portNumber(1); - private static final ConnectPoint CP1_1 = new ConnectPoint(D1, P1); - private static final ConnectPoint CP2_1 = new ConnectPoint(D2, P1); private static final VlanId VLAN1 = VlanId.vlanId((short) 100); private static final Bandwidth BW1 = Bandwidth.gbps(2); private static final Bandwidth BW2 = Bandwidth.gbps(1); @Test public void testEquals() { - ResourcePath resource1 = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1); - ResourcePath sameAsResource1 = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1); - ResourcePath resource2 = ResourcePath.discrete(LinkKey.linkKey(CP2_1, CP1_1), VLAN1); - ResourcePath resource3 = ResourcePath.continuous(BW1.bps(), LinkKey.linkKey(CP1_1, CP2_1), BW1); - ResourcePath sameAsResource3 = ResourcePath.continuous(BW2.bps(), LinkKey.linkKey(CP1_1, CP2_1), BW1); + ResourcePath resource1 = ResourcePath.discrete(D1, P1, VLAN1); + ResourcePath sameAsResource1 = ResourcePath.discrete(D1, P1, VLAN1); + ResourcePath resource2 = ResourcePath.discrete(D2, P1, VLAN1); + ResourcePath resource3 = ResourcePath.continuous(BW1.bps(), D1, P1, BW1); + ResourcePath sameAsResource3 = ResourcePath.continuous(BW2.bps(), D1, P1, BW1); new EqualsTester() .addEqualityGroup(resource1, sameAsResource1) @@ -56,13 +52,6 @@ public class ResourcePathTest { .testEquals(); } - @Test - public void testCreateWithZeroComponent() { - ResourcePath path = ResourcePath.discrete(); - - assertThat(path, is(ResourcePath.ROOT)); - } - @Test public void testComponents() { ResourcePath port = ResourcePath.discrete(D1, P1); @@ -72,25 +61,24 @@ public class ResourcePathTest { @Test public void testThereIsParent() { - ResourcePath path = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1); - ResourcePath parent = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1)); + ResourcePath path = ResourcePath.discrete(D1, P1, VLAN1); + ResourcePath parent = ResourcePath.discrete(D1, P1); assertThat(path.parent(), is(Optional.of(parent))); } @Test public void testNoParent() { - ResourcePath path = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1)); + ResourcePath path = ResourcePath.discrete(D1); assertThat(path.parent(), is(Optional.of(ResourcePath.ROOT))); } @Test public void testBase() { - LinkKey linkKey = LinkKey.linkKey(CP1_1, CP2_1); - ResourcePath path = ResourcePath.discrete(linkKey); + ResourcePath path = ResourcePath.discrete(D1); - LinkKey child = (LinkKey) path.last(); - assertThat(child, is(linkKey)); + DeviceId child = (DeviceId) path.last(); + assertThat(child, is(D1)); } } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/PersistenceServiceAdapter.java b/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/PersistenceServiceAdapter.java new file mode 100644 index 00000000..3edfcc73 --- /dev/null +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/PersistenceServiceAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.persistence; + +import org.onosproject.persistence.PersistenceService; +import org.onosproject.persistence.PersistentMapBuilder; +import org.onosproject.persistence.PersistentSetBuilder; + +/** + * Adapter for PersistenceService. + */ +public class PersistenceServiceAdapter implements PersistenceService { + + @Override + public PersistentMapBuilder persistentMapBuilder() { + return null; + } + + @Override + public PersistentSetBuilder persistentSetBuilder() { + return null; + } +} diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/TestPersistenceService.java b/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/TestPersistenceService.java new file mode 100644 index 00000000..a6d97458 --- /dev/null +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/store/persistence/TestPersistenceService.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.persistence; + +import java.util.Map; + +import org.onosproject.persistence.PersistentMapBuilder; +import org.onosproject.persistence.PersistentSetBuilder; +import org.onosproject.store.service.Serializer; + +import com.google.common.collect.Maps; + +/** + * PersistenceService that produces in memory maps for use in unit testing. + */ +public class TestPersistenceService extends PersistenceServiceAdapter { + @Override + public PersistentMapBuilder persistentMapBuilder() { + return new TestPersistentMapBuilder(); + } + + @Override + public PersistentSetBuilder persistentSetBuilder() { + throw new UnsupportedOperationException(); + } + + private static class TestPersistentMapBuilder implements PersistentMapBuilder { + + @Override + public PersistentMapBuilder withName(String name) { + return this; + } + + @Override + public PersistentMapBuilder withSerializer(Serializer serializer) { + return this; + } + + @Override + public Map build() { + return Maps.newConcurrentMap(); + } + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java index 33dd46a3..1852ee29 100644 --- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java @@ -127,6 +127,7 @@ public final class EncodeCriterionCodecHelper { formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown()); formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown()); formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown()); + formatMap.put(Criterion.Type.EXTENSION, new FormatUnknown()); } private interface CriterionTypeFormatter { diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java b/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java index 84cde424..c5263ed7 100644 --- a/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java @@ -43,12 +43,15 @@ import org.onosproject.net.topology.ClusterId; import org.onosproject.net.topology.DefaultTopologyCluster; import org.onosproject.net.topology.DefaultTopologyVertex; import org.onosproject.net.topology.GraphDescription; +import org.onosproject.net.topology.HopCountLinkWeight; import org.onosproject.net.topology.LinkWeight; import org.onosproject.net.topology.Topology; import org.onosproject.net.topology.TopologyCluster; import org.onosproject.net.topology.TopologyEdge; import org.onosproject.net.topology.TopologyGraph; import org.onosproject.net.topology.TopologyVertex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; @@ -61,7 +64,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static org.onlab.graph.GraphPathSearch.ALL_PATHS; import static org.onlab.util.Tools.isNullOrEmpty; import static org.onosproject.core.CoreService.CORE_PROVIDER_ID; -import static org.onosproject.net.Link.State.ACTIVE; import static org.onosproject.net.Link.State.INACTIVE; import static org.onosproject.net.Link.Type.INDIRECT; @@ -71,18 +73,22 @@ import static org.onosproject.net.Link.Type.INDIRECT; */ public class DefaultTopology extends AbstractModel implements Topology { + private static final Logger log = LoggerFactory.getLogger(DefaultTopology.class); + private static final DijkstraGraphSearch DIJKSTRA = new DijkstraGraphSearch<>(); private static final TarjanGraphSearch TARJAN = new TarjanGraphSearch<>(); - private static final SuurballeGraphSearch SUURBALLE = - new SuurballeGraphSearch<>(); + private static final SuurballeGraphSearch SUURBALLE = new SuurballeGraphSearch<>(); + private static LinkWeight defaultLinkWeight = null; + private static GraphPathSearch defaultGraphPathSearch = null; private final long time; private final long creationTime; private final long computeCost; private final TopologyGraph graph; - private final LinkWeight weight; + private final LinkWeight hopCountWeight; + private final Supplier> clusterResults; private final Supplier> clusters; private final Supplier> infrastructurePoints; @@ -90,6 +96,30 @@ public class DefaultTopology extends AbstractModel implements Topology { private final Function broadcastFunction; private final Supplier clusterIndexes; + /** + * Sets the default link-weight to be used when computing paths. If null is + * specified, the builtin default link-weight measuring hop-counts will be + * used. + * + * @param linkWeight new default link-weight + */ + public static void setDefaultLinkWeight(LinkWeight linkWeight) { + log.info("Setting new default link-weight function to {}", linkWeight); + defaultLinkWeight = linkWeight; + } + + /** + * Sets the default lpath search algorighm to be used when computing paths. + * If null is specified, the builtin default Dijkstra will be used. + * + * @param graphPathSearch new default algorithm + */ + public static void setDefaultGraphPathSearch(GraphPathSearch graphPathSearch) { + log.info("Setting new default graph path algorithm to {}", graphPathSearch); + defaultGraphPathSearch = graphPathSearch; + } + + /** * Creates a topology descriptor attributed to the specified provider. * @@ -113,7 +143,7 @@ public class DefaultTopology extends AbstractModel implements Topology { this.clusterIndexes = Suppliers.memoize(() -> buildIndexes()); - this.weight = new HopCountLinkWeight(graph.getVertexes().size()); + this.hopCountWeight = new HopCountLinkWeight(graph.getVertexes().size()); this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); this.computeCost = Math.max(0, System.nanoTime() - time); @@ -294,7 +324,7 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of shortest paths */ public Set getPaths(DeviceId src, DeviceId dst) { - return getPaths(src, dst, null); + return getPaths(src, dst, linkWeight()); } /** @@ -307,8 +337,8 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of shortest paths */ public Set getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { - final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); - final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); + DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); + DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); Set vertices = graph.getVertexes(); if (!vertices.contains(srcV) || !vertices.contains(dstV)) { // src or dst not part of the current graph @@ -316,7 +346,7 @@ public class DefaultTopology extends AbstractModel implements Topology { } GraphPathSearch.Result result = - DIJKSTRA.search(graph, srcV, dstV, weight, ALL_PATHS); + graphPathSearch().search(graph, srcV, dstV, weight, ALL_PATHS); ImmutableSet.Builder builder = ImmutableSet.builder(); for (org.onlab.graph.Path path : result.paths()) { builder.add(networkPath(path)); @@ -334,7 +364,7 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of shortest disjoint path pairs */ public Set getDisjointPaths(DeviceId src, DeviceId dst) { - return getDisjointPaths(src, dst, (LinkWeight) null); + return getDisjointPaths(src, dst, linkWeight()); } /** @@ -347,8 +377,8 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of disjoint shortest path pairs */ public Set getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) { - final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); - final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); + DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); + DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); Set vertices = graph.getVertexes(); if (!vertices.contains(srcV) || !vertices.contains(dstV)) { // src or dst not part of the current graph @@ -375,7 +405,7 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of shortest disjoint paths */ private Set disjointPaths(DeviceId src, DeviceId dst, LinkWeight weight, - Map riskProfile) { + Map riskProfile) { DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); @@ -438,7 +468,7 @@ public class DefaultTopology extends AbstractModel implements Topology { * @return set of shortest disjoint paths */ public Set getDisjointPaths(DeviceId src, DeviceId dst, Map riskProfile) { - return getDisjointPaths(src, dst, null, riskProfile); + return getDisjointPaths(src, dst, linkWeight(), riskProfile); } // Converts graph path to a network path with the same cost. @@ -499,8 +529,7 @@ public class DefaultTopology extends AbstractModel implements Topology { // Processes a map of broadcast sets for each cluster. private ImmutableSetMultimap buildBroadcastSets() { - Builder builder = ImmutableSetMultimap - .builder(); + Builder builder = ImmutableSetMultimap.builder(); for (TopologyCluster cluster : clusters.get().values()) { addClusterBroadcastSet(cluster, builder); } @@ -512,7 +541,7 @@ public class DefaultTopology extends AbstractModel implements Topology { // all other devices within the cluster. private void addClusterBroadcastSet(TopologyCluster cluster, Builder builder) { // Use the graph root search results to build the broadcast set. - Result result = DIJKSTRA.search(graph, cluster.root(), null, weight, 1); + Result result = DIJKSTRA.search(graph, cluster.root(), null, hopCountWeight, 1); for (Map.Entry> entry : result.parents().entrySet()) { TopologyVertex vertex = entry.getKey(); @@ -577,23 +606,12 @@ public class DefaultTopology extends AbstractModel implements Topology { linksBuilder.build()); } - // Link weight for measuring link cost as hop count with indirect links - // being as expensive as traversing the entire graph to assume the worst. - private static class HopCountLinkWeight implements LinkWeight { - private final int indirectLinkCost; - - HopCountLinkWeight(int indirectLinkCost) { - this.indirectLinkCost = indirectLinkCost; - } + private GraphPathSearch graphPathSearch() { + return defaultGraphPathSearch != null ? defaultGraphPathSearch : DIJKSTRA; + } - @Override - public double weight(TopologyEdge edge) { - // To force preference to use direct paths first, make indirect - // links as expensive as the linear vertex traversal. - return edge.link().state() == - ACTIVE ? (edge.link().type() == - INDIRECT ? indirectLinkCost : 1) : -1; - } + private LinkWeight linkWeight() { + return defaultLinkWeight != null ? defaultLinkWeight : hopCountWeight; } // Link weight for preventing traversal over indirect links. diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/edgeservice/impl/EdgeManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/edgeservice/impl/EdgeManager.java index e992f7a4..cd7335d6 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/edgeservice/impl/EdgeManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/edgeservice/impl/EdgeManager.java @@ -27,10 +27,10 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onosproject.event.AbstractListenerManager; -import org.onosproject.event.Event; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DeviceId; import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; import org.onosproject.net.edge.EdgePortEvent; import org.onosproject.net.edge.EdgePortListener; @@ -38,17 +38,16 @@ import org.onosproject.net.edge.EdgePortService; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.link.LinkEvent; +import org.onosproject.net.link.LinkListener; +import org.onosproject.net.link.LinkService; import org.onosproject.net.packet.DefaultOutboundPacket; import org.onosproject.net.packet.OutboundPacket; import org.onosproject.net.packet.PacketService; import org.onosproject.net.topology.Topology; -import org.onosproject.net.topology.TopologyEvent; -import org.onosproject.net.topology.TopologyListener; import org.onosproject.net.topology.TopologyService; import org.slf4j.Logger; import java.nio.ByteBuffer; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -73,7 +72,9 @@ public class EdgeManager private final Map> connectionPoints = Maps.newConcurrentMap(); - private final TopologyListener topologyListener = new InnerTopologyListener(); + private final LinkListener linkListener = new InnerLinkListener(); + + private final DeviceListener deviceListener = new InnerDeviceListener(); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected PacketService packetService; @@ -84,17 +85,23 @@ public class EdgeManager @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected TopologyService topologyService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected LinkService linkService; + @Activate public void activate() { eventDispatcher.addSink(EdgePortEvent.class, listenerRegistry); - topologyService.addListener(topologyListener); + deviceService.addListener(deviceListener); + linkService.addListener(linkListener); + loadAllEdgePorts(); log.info("Started"); } @Deactivate public void deactivate() { eventDispatcher.removeSink(EdgePortEvent.class); - topologyService.removeListener(topologyListener); + deviceService.removeListener(deviceListener); + linkService.removeListener(linkListener); log.info("Stopped"); } @@ -142,31 +149,27 @@ public class EdgeManager return new DefaultOutboundPacket(point.deviceId(), builder.build(), data); } - // Internal listener for topo events used to keep our edge-port cache - // up to date. - private class InnerTopologyListener implements TopologyListener { + private class InnerLinkListener implements LinkListener { + @Override - public void event(TopologyEvent event) { - topology = event.subject(); - List triggers = event.reasons(); - if (triggers != null) { - triggers.forEach(reason -> { - if (reason instanceof DeviceEvent) { - processDeviceEvent((DeviceEvent) reason); - } else if (reason instanceof LinkEvent) { - processLinkEvent((LinkEvent) reason); - } - }); - } else { - //FIXME special case of preexisting edgeport & no triggerless events could cause this to never hit and - //never discover an edgeport that should have been discovered. - loadAllEdgePorts(); - } + public void event(LinkEvent event) { + topology = topologyService.currentTopology(); + processLinkEvent(event); + } + } + + private class InnerDeviceListener implements DeviceListener { + + @Override + public void event(DeviceEvent event) { + topology = topologyService.currentTopology(); + processDeviceEvent(event); } } // Initial loading of the edge port cache. private void loadAllEdgePorts() { + topology = topologyService.currentTopology(); deviceService.getAvailableDevices().forEach(d -> deviceService.getPorts(d.id()) .forEach(p -> addEdgePort(new ConnectPoint(d.id(), p.number())))); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java index 5958d1f5..63ee03ec 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java @@ -436,7 +436,7 @@ public class FlowRuleManager log.debug("Adding rule in store, but not on switch {}", rule); flowMissing(rule); } catch (Exception e) { - log.debug("Can't add missing flow rule {}", e.getMessage()); + log.debug("Can't add missing flow rule:", e); continue; } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java index 5ecdc7a2..33200b1a 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java @@ -16,7 +16,6 @@ package org.onosproject.net.flowobjective.impl; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -53,9 +52,11 @@ import org.onosproject.net.group.GroupService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import static com.google.common.base.Preconditions.checkNotNull; @@ -228,8 +229,10 @@ public class FlowObjectiveManager implements FlowObjectiveService { flowObjectiveStore.getNextGroup(fwd.nextId()) == null) { log.trace("Queuing forwarding objective for nextId {}", fwd.nextId()); // TODO: change to computeIfAbsent - Set pnext = pendingForwards.putIfAbsent(fwd.nextId(), - Sets.newHashSet(new PendingNext(deviceId, fwd))); + Set newset = Collections.newSetFromMap( + new ConcurrentHashMap()); + newset.add(new PendingNext(deviceId, fwd)); + Set pnext = pendingForwards.putIfAbsent(fwd.nextId(), newset); if (pnext != null) { pnext.add(new PendingNext(deviceId, fwd)); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java index ebf681a2..ff711a02 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java @@ -34,6 +34,7 @@ import org.onosproject.net.HostId; import org.onosproject.net.Link; import org.onosproject.net.LinkKey; import org.onosproject.net.NetworkResource; +import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; @@ -302,11 +303,11 @@ public class ObjectiveTracker implements ObjectiveTrackerService { private class InternalResourceListener implements ResourceListener { @Override public void event(ResourceEvent event) { - Optional> linkEvent = event.subject().components().stream() + Optional> deviceEvent = event.subject().components().stream() .map(Object::getClass) - .filter(x -> x == LinkKey.class) + .filter(x -> x == PortNumber.class) .findFirst(); - if (linkEvent.isPresent()) { + if (deviceEvent.isPresent()) { executorService.execute(() -> { if (delegate == null) { return; diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java index 718c7bbf..5549918c 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java @@ -15,6 +15,7 @@ */ package org.onosproject.net.intent.impl.compiler; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import org.apache.felix.scr.annotations.Activate; @@ -59,9 +60,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.net.LinkKey.linkKey; @@ -120,11 +121,16 @@ public class MplsPathIntentCompiler implements IntentCompiler { return Collections.emptyMap(); } - List resources = labels.entrySet().stream() - .map(x -> ResourcePath.discrete(linkKey(x.getKey().src(), x.getKey().src()), x.getValue())) - .collect(Collectors.toList()); + // for short term solution: same label is used for both directions + // TODO: introduce the concept of Tx and Rx resources of a port + Set resources = labels.entrySet().stream() + .flatMap(x -> Stream.of( + ResourcePath.discrete(x.getKey().src().deviceId(), x.getKey().src().port(), x.getValue()), + ResourcePath.discrete(x.getKey().dst().deviceId(), x.getKey().dst().port(), x.getValue()) + )) + .collect(Collectors.toSet()); List allocations = - resourceService.allocate(intent.id(), resources); + resourceService.allocate(intent.id(), ImmutableList.copyOf(resources)); if (allocations.isEmpty()) { Collections.emptyMap(); } @@ -135,20 +141,23 @@ public class MplsPathIntentCompiler implements IntentCompiler { private Map findMplsLabels(Set links) { Map labels = new HashMap<>(); for (LinkKey link : links) { - Optional label = findMplsLabel(link); - if (label.isPresent()) { - labels.put(link, label.get()); + Set forward = findMplsLabel(link.src()); + Set backward = findMplsLabel(link.dst()); + Set common = Sets.intersection(forward, backward); + if (common.isEmpty()) { + continue; } + labels.put(link, common.iterator().next()); } return labels; } - private Optional findMplsLabel(LinkKey link) { - return resourceService.getAvailableResources(ResourcePath.discrete(link)).stream() + private Set findMplsLabel(ConnectPoint cp) { + return resourceService.getAvailableResources(ResourcePath.discrete(cp.deviceId(), cp.port())).stream() .filter(x -> x.last() instanceof MplsLabel) .map(x -> (MplsLabel) x.last()) - .findFirst(); + .collect(Collectors.toSet()); } private MplsLabel getMplsLabel(Map labels, LinkKey link) { diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java index 2941ddba..e017ac58 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java @@ -57,9 +57,9 @@ import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.google.common.base.Preconditions.checkArgument; -import static org.onosproject.net.LinkKey.linkKey; /** * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}. @@ -182,7 +182,10 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler lambdaResources = path.links().stream() - .map(x -> ResourcePath.discrete(linkKey(x.src(), x.dst()))) + .flatMap(x -> Stream.of( + ResourcePath.discrete(x.src().deviceId(), x.src().port()), + ResourcePath.discrete(x.dst().deviceId(), x.dst().port()) + )) .map(x -> x.child(minLambda)) .collect(Collectors.toList()); @@ -197,7 +200,10 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler findCommonLambdasOverLinks(List links) { return links.stream() - .map(x -> ResourcePath.discrete(linkKey(x.src(), x.dst()))) + .flatMap(x -> Stream.of( + ResourcePath.discrete(x.src().deviceId(), x.src().port()), + ResourcePath.discrete(x.dst().deviceId(), x.dst().port()) + )) .map(resourceService::getAvailableResources) .map(x -> Iterables.filter(x, r -> r.last() instanceof IndexedLambda)) .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.last())) diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java index 801092f4..ff74dbde 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java @@ -38,6 +38,7 @@ import org.slf4j.Logger; public final class BasicLinkOperator implements ConfigOperator { private static final long DEF_BANDWIDTH = -1L; + private static final double DEF_METRIC = -1; private static final Duration DEF_DURATION = Duration.ofNanos(-1L); private static final Logger log = getLogger(BasicLinkOperator.class); @@ -77,6 +78,9 @@ public final class BasicLinkOperator implements ConfigOperator { */ public static SparseAnnotations combine(BasicLinkConfig cfg, SparseAnnotations an) { DefaultAnnotations.Builder b = DefaultAnnotations.builder(); + if (cfg.metric() != DEF_METRIC) { + b.set(AnnotationKeys.METRIC, String.valueOf(cfg.metric())); + } if (cfg.latency() != DEF_DURATION) { b.set(AnnotationKeys.LATENCY, cfg.latency().toString()); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java index 4fb0d7ba..bfc6a995 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java @@ -16,19 +16,32 @@ package org.onosproject.net.newresource.impl; import com.google.common.collect.Lists; +import org.onlab.packet.MplsLabel; +import org.onlab.packet.VlanId; +import org.onlab.util.ItemNotFoundException; import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; import org.onosproject.net.Port; import org.onosproject.net.OchPort; +import org.onosproject.net.OchSignal; +import org.onosproject.net.PortNumber; import org.onosproject.net.TributarySlot; import org.onosproject.net.OduSignalType; +import org.onosproject.net.behaviour.LambdaQuery; +import org.onosproject.net.behaviour.MplsQuery; +import org.onosproject.net.behaviour.VlanQuery; import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; +import org.onosproject.net.driver.DriverHandler; +import org.onosproject.net.driver.DriverService; import org.onosproject.net.newresource.ResourceAdminService; import org.onosproject.net.newresource.ResourcePath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collections; import java.util.List; +import java.util.SortedSet; import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -42,12 +55,19 @@ final class ResourceDeviceListener implements DeviceListener { private static final Logger log = LoggerFactory.getLogger(ResourceDeviceListener.class); + private static final int MAX_VLAN_ID = VlanId.MAX_VLAN; + private static final List ENTIRE_VLAN_IDS = getEntireVlans(); + + private static final int MAX_MPLS_LABEL = 1048576; + private static final List ENTIRE_MPLS_LABELS = getEntireMplsLabels(); + private static final int TOTAL_ODU2_TRIBUTARY_SLOTS = 8; private static final int TOTAL_ODU4_TRIBUTARY_SLOTS = 80; private static final List ENTIRE_ODU2_TRIBUTARY_SLOTS = getEntireOdu2TributarySlots(); private static final List ENTIRE_ODU4_TRIBUTARY_SLOTS = getEntireOdu4TributarySlots(); private final ResourceAdminService adminService; + private final DriverService driverService; private final ExecutorService executor; /** @@ -56,8 +76,10 @@ final class ResourceDeviceListener implements DeviceListener { * @param adminService instance invoked to register resources * @param executor executor used for processing resource registration */ - ResourceDeviceListener(ResourceAdminService adminService, ExecutorService executor) { + ResourceDeviceListener(ResourceAdminService adminService, DriverService driverService, + ExecutorService executor) { this.adminService = checkNotNull(adminService); + this.driverService = checkNotNull(driverService); this.executor = checkNotNull(executor); } @@ -95,6 +117,26 @@ final class ResourceDeviceListener implements DeviceListener { executor.submit(() -> { adminService.registerResources(portPath); + // for VLAN IDs + if (isVlanEnabled(device.id(), port.number())) { + adminService.registerResources(Lists.transform(ENTIRE_VLAN_IDS, portPath::child)); + } + + // for MPLS labels + if (isMplsEnabled(device.id(), port.number())) { + adminService.registerResources(Lists.transform(ENTIRE_MPLS_LABELS, portPath::child)); + } + + // for Lambdas + SortedSet lambdas = queryLambdas(device.id(), port.number()); + if (!lambdas.isEmpty()) { + adminService.registerResources(lambdas.stream() + .map(portPath::child) + .collect(Collectors.toList())); + } + + // for Tributary slots + // TODO: need to define Behaviour to make a query about OCh port switch (port.type()) { case OCH: // register ODU TributarySlots against the OCH port @@ -124,15 +166,68 @@ final class ResourceDeviceListener implements DeviceListener { executor.submit(() -> adminService.unregisterResources(resource)); } + private SortedSet queryLambdas(DeviceId did, PortNumber port) { + try { + DriverHandler handler = driverService.createHandler(did); + if (handler == null) { + return Collections.emptySortedSet(); + } + LambdaQuery query = handler.behaviour(LambdaQuery.class); + return query.queryLambdas(port); + } catch (ItemNotFoundException e) { + return Collections.emptySortedSet(); + } + } + + private boolean isVlanEnabled(DeviceId device, PortNumber port) { + try { + DriverHandler handler = driverService.createHandler(device); + if (handler == null) { + return false; + } + + VlanQuery query = handler.behaviour(VlanQuery.class); + return query != null && query.isEnabled(port); + } catch (ItemNotFoundException e) { + return false; + } + } + + private boolean isMplsEnabled(DeviceId device, PortNumber port) { + try { + DriverHandler handler = driverService.createHandler(device); + if (handler == null) { + return false; + } + + MplsQuery query = handler.behaviour(MplsQuery.class); + return query != null && query.isEnabled(port); + } catch (ItemNotFoundException e) { + return false; + } + } + + private static List getEntireVlans() { + return IntStream.range(0, MAX_VLAN_ID) + .mapToObj(x -> VlanId.vlanId((short) x)) + .collect(Collectors.toList()); + } + + private static List getEntireMplsLabels() { + // potentially many objects are created + return IntStream.range(0, MAX_MPLS_LABEL) + .mapToObj(MplsLabel::mplsLabel) + .collect(Collectors.toList()); + } + private static List getEntireOdu2TributarySlots() { return IntStream.rangeClosed(1, TOTAL_ODU2_TRIBUTARY_SLOTS) - .mapToObj(x -> TributarySlot.of(x)) + .mapToObj(TributarySlot::of) .collect(Collectors.toList()); } private static List getEntireOdu4TributarySlots() { return IntStream.rangeClosed(1, TOTAL_ODU4_TRIBUTARY_SLOTS) - .mapToObj(x -> TributarySlot.of(x)) + .mapToObj(TributarySlot::of) .collect(Collectors.toList()); } - } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java deleted file mode 100644 index 9d2e06f5..00000000 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.net.newresource.impl; - -import com.google.common.collect.Lists; -import org.onlab.packet.MplsLabel; -import org.onlab.packet.VlanId; -import org.onlab.util.ItemNotFoundException; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.Link; -import org.onosproject.net.LinkKey; -import org.onosproject.net.behaviour.MplsQuery; -import org.onosproject.net.behaviour.VlanQuery; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.net.driver.DriverService; -import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.link.LinkListener; -import org.onosproject.net.newresource.ResourceAdminService; -import org.onosproject.net.newresource.ResourcePath; - -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * An implementation of LinkListener registering links as resources. - */ -final class ResourceLinkListener implements LinkListener { - - private static final int TOTAL_VLANS = 1024; - private static final List ENTIRE_VLAN_IDS = getEntireVlans(); - - private static final int TOTAL_MPLS_LABELS = 1048576; - private static final List ENTIRE_MPLS_LABELS = getEntireMplsLabels(); - - private final ResourceAdminService adminService; - private final DriverService driverService; - private final ExecutorService executor; - - /** - * Creates an instance with the specified ResourceAdminService and ExecutorService. - * - * @param adminService instance invoked to register resources - * @param driverService driver service instance - * @param executor executor used for processing resource registration - */ - ResourceLinkListener(ResourceAdminService adminService, DriverService driverService, ExecutorService executor) { - this.adminService = checkNotNull(adminService); - this.driverService = checkNotNull(driverService); - this.executor = checkNotNull(executor); - } - - @Override - public void event(LinkEvent event) { - Link link = event.subject(); - switch (event.type()) { - case LINK_ADDED: - registerLinkResource(link); - break; - case LINK_REMOVED: - unregisterLinkResource(link); - break; - default: - break; - } - } - - private void registerLinkResource(Link link) { - executor.submit(() -> { - // register the link - LinkKey linkKey = LinkKey.linkKey(link); - adminService.registerResources(ResourcePath.discrete(linkKey)); - - ResourcePath linkPath = ResourcePath.discrete(linkKey); - // register VLAN IDs against the link - if (isEnabled(link, this::isVlanEnabled)) { - adminService.registerResources(Lists.transform(ENTIRE_VLAN_IDS, linkPath::child)); - } - - // register MPLS labels against the link - if (isEnabled(link, this::isMplsEnabled)) { - adminService.registerResources(Lists.transform(ENTIRE_MPLS_LABELS, linkPath::child)); - } - }); - } - - private void unregisterLinkResource(Link link) { - LinkKey linkKey = LinkKey.linkKey(link); - executor.submit(() -> adminService.unregisterResources(ResourcePath.discrete(linkKey))); - } - - private boolean isEnabled(Link link, Predicate predicate) { - return predicate.test(link.src()) && predicate.test(link.dst()); - } - - private boolean isVlanEnabled(ConnectPoint cp) { - try { - DriverHandler handler = driverService.createHandler(cp.deviceId()); - if (handler == null) { - return false; - } - - VlanQuery query = handler.behaviour(VlanQuery.class); - return query != null && query.isEnabled(cp.port()); - } catch (ItemNotFoundException e) { - return false; - } - } - - private boolean isMplsEnabled(ConnectPoint cp) { - try { - DriverHandler handler = driverService.createHandler(cp.deviceId()); - if (handler == null) { - return false; - } - - MplsQuery query = handler.behaviour(MplsQuery.class); - return query != null && query.isEnabled(cp.port()); - } catch (ItemNotFoundException e) { - return false; - } - } - - private static List getEntireVlans() { - return IntStream.range(0, TOTAL_VLANS) - .mapToObj(x -> VlanId.vlanId((short) x)) - .collect(Collectors.toList()); - } - - private static List getEntireMplsLabels() { - // potentially many objects are created - return IntStream.range(0, TOTAL_MPLS_LABELS) - .mapToObj(MplsLabel::mplsLabel) - .collect(Collectors.toList()); - } -} diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java index 143f8c2b..e8042661 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java @@ -24,8 +24,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; import org.onosproject.net.driver.DriverService; -import org.onosproject.net.link.LinkListener; -import org.onosproject.net.link.LinkService; import org.onosproject.net.newresource.ResourceAdminService; import java.util.concurrent.ExecutorService; @@ -49,25 +47,18 @@ public final class ResourceRegistrar { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkService linkService; - private DeviceListener deviceListener; - private LinkListener linkListener; private final ExecutorService executor = Executors.newSingleThreadExecutor(groupedThreads("onos/resource", "registrar")); @Activate public void activate() { - deviceListener = new ResourceDeviceListener(adminService, executor); + deviceListener = new ResourceDeviceListener(adminService, driverService, executor); deviceService.addListener(deviceListener); - linkListener = new ResourceLinkListener(adminService, driverService, executor); - linkService.addListener(linkListener); } @Deactivate public void deactivate() { deviceService.removeListener(deviceListener); - linkService.removeListener(linkListener); } } diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/edgeservice/impl/EdgeManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/edgeservice/impl/EdgeManagerTest.java index 319412fe..70be5deb 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/edgeservice/impl/EdgeManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/edgeservice/impl/EdgeManagerTest.java @@ -22,7 +22,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.onosproject.common.event.impl.TestEventDispatcher; -import org.onosproject.event.Event; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DefaultPort; import org.onosproject.net.Device; @@ -31,15 +30,17 @@ import org.onosproject.net.NetTestTools; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceServiceAdapter; import org.onosproject.net.edge.EdgePortEvent; import org.onosproject.net.edge.EdgePortListener; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.link.LinkEvent; +import org.onosproject.net.link.LinkListener; +import org.onosproject.net.link.LinkServiceAdapter; import org.onosproject.net.packet.OutboundPacket; import org.onosproject.net.packet.PacketServiceAdapter; import org.onosproject.net.topology.Topology; -import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; import org.onosproject.net.topology.TopologyServiceAdapter; @@ -58,7 +59,6 @@ import static org.onosproject.net.edge.EdgePortEvent.Type.EDGE_PORT_ADDED; import static org.onosproject.net.edge.EdgePortEvent.Type.EDGE_PORT_REMOVED; import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; -import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; /** * Test of the edge port manager. Each device has ports '0' through 'numPorts - 1' @@ -74,6 +74,8 @@ public class EdgeManagerTest { private final Map devices = Maps.newConcurrentMap(); private Set packets = Sets.newConcurrentHashSet(); private final EdgePortListener testListener = new TestListener(events); + private TestLinkManager testLinkManager; + private TestDeviceManager testDeviceManager; private TestTopologyManager testTopologyManager; @Before @@ -82,8 +84,11 @@ public class EdgeManagerTest { injectEventDispatcher(mgr, new TestEventDispatcher()); testTopologyManager = new TestTopologyManager(infrastructurePorts); mgr.topologyService = testTopologyManager; - mgr.deviceService = new TestDeviceManager(devices); + testDeviceManager = new TestDeviceManager(devices); + mgr.deviceService = testDeviceManager; mgr.packetService = new TestPacketManager(); + testLinkManager = new TestLinkManager(); + mgr.linkService = testLinkManager; mgr.activate(); mgr.addListener(testListener); @@ -108,11 +113,11 @@ public class EdgeManagerTest { assertFalse("no ports expected", mgr.getEdgePoints().iterator().hasNext()); assertFalse("Expected isEdge to return false", - mgr.isEdgePoint(NetTestTools.connectPoint(Integer.toString(1), 1))); + mgr.isEdgePoint(NetTestTools.connectPoint(Integer.toString(1), 1))); removeInfraPort(NetTestTools.connectPoint(Integer.toString(1), 1)); assertTrue("Expected isEdge to return false", - mgr.isEdgePoint(NetTestTools.connectPoint(Integer.toString(1), 1))); + mgr.isEdgePoint(NetTestTools.connectPoint(Integer.toString(1), 1))); } @Test @@ -121,69 +126,57 @@ public class EdgeManagerTest { ConnectPoint testPoint, referencePoint; //Testing link removal - List eventsToAdd = Lists.newArrayList(); - eventsToAdd.add(new LinkEvent(LINK_REMOVED, NetTestTools.link("a", 1, "b", 2))); - TopologyEvent event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); + testLinkManager.listener.event(new LinkEvent(LINK_REMOVED, NetTestTools.link("a", 1, "b", 2))); assertTrue("The list contained an unexpected number of events", events.size() == 2); assertTrue("The first element is of the wrong type.", - events.get(0).type() == EDGE_PORT_ADDED); - assertTrue("The second element is of the wrong type.", - events.get(1).type() == EDGE_PORT_ADDED); + events.get(0).type() == EDGE_PORT_ADDED); testPoint = events.get(0).subject(); referencePoint = NetTestTools.connectPoint("a", 1); assertTrue("The port numbers of the first element are incorrect", - testPoint.port().toLong() == referencePoint.port().toLong()); + testPoint.port().toLong() == referencePoint.port().toLong()); assertTrue("The device id of the first element is incorrect.", - testPoint.deviceId().equals(referencePoint.deviceId())); + testPoint.deviceId().equals(referencePoint.deviceId())); testPoint = events.get(1).subject(); referencePoint = NetTestTools.connectPoint("b", 2); assertTrue("The port numbers of the second element are incorrect", - testPoint.port().toLong() == referencePoint.port().toLong()); + testPoint.port().toLong() == referencePoint.port().toLong()); assertTrue("The device id of the second element is incorrect.", - testPoint.deviceId().equals(referencePoint.deviceId())); + testPoint.deviceId().equals(referencePoint.deviceId())); //Rebroadcast event to ensure it results in no additional events - testTopologyManager.listener.event(event); + testLinkManager.listener.event(new LinkEvent(LINK_REMOVED, NetTestTools.link("a", 1, "b", 2))); assertTrue("The list contained an unexpected number of events", events.size() == 2); //Testing link adding when links to remove exist - eventsToAdd.clear(); events.clear(); - eventsToAdd.add(new LinkEvent(LINK_ADDED, NetTestTools.link("a", 1, "b", 2))); - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); + testLinkManager.listener.event(new LinkEvent(LINK_ADDED, NetTestTools.link("a", 1, "b", 2))); assertTrue("The list contained an unexpected number of events", events.size() == 2); assertTrue("The first element is of the wrong type.", - events.get(0).type() == EDGE_PORT_REMOVED); + events.get(0).type() == EDGE_PORT_REMOVED); assertTrue("The second element is of the wrong type.", - events.get(1).type() == EDGE_PORT_REMOVED); + events.get(1).type() == EDGE_PORT_REMOVED); testPoint = events.get(0).subject(); referencePoint = NetTestTools.connectPoint("a", 1); assertTrue("The port numbers of the first element are incorrect", - testPoint.port().toLong() == referencePoint.port().toLong()); + testPoint.port().toLong() == referencePoint.port().toLong()); assertTrue("The device id of the first element is incorrect.", - testPoint.deviceId().equals(referencePoint.deviceId())); + testPoint.deviceId().equals(referencePoint.deviceId())); testPoint = events.get(1).subject(); referencePoint = NetTestTools.connectPoint("b", 2); assertTrue("The port numbers of the second element are incorrect", - testPoint.port().toLong() == referencePoint.port().toLong()); + testPoint.port().toLong() == referencePoint.port().toLong()); assertTrue("The device id of the second element is incorrect.", - testPoint.deviceId().equals(referencePoint.deviceId())); + testPoint.deviceId().equals(referencePoint.deviceId())); //Apparent duplicate of previous method tests removal when the elements have already been removed - eventsToAdd.clear(); events.clear(); - eventsToAdd.add(new LinkEvent(LINK_ADDED, NetTestTools.link("a", 1, "b", 2))); - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); - + testLinkManager.listener.event(new LinkEvent(LINK_ADDED, NetTestTools.link("a", 1, "b", 2))); assertTrue("The list should contain no events, the removed elements don't exist.", events.size() == 0); } @@ -192,8 +185,7 @@ public class EdgeManagerTest { //Setup Device referenceDevice; - TopologyEvent event; - List eventsToAdd = Lists.newArrayList(); + DeviceEvent event; int numDevices = 10; int numInfraPorts = 5; totalPorts = 10; @@ -201,14 +193,13 @@ public class EdgeManagerTest { //Test response to device added events referenceDevice = NetTestTools.device("1"); - eventsToAdd.add(new DeviceEvent(DEVICE_ADDED, referenceDevice, - new DefaultPort(referenceDevice, PortNumber.portNumber(1), true))); - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); + event = new DeviceEvent(DEVICE_ADDED, referenceDevice, + new DefaultPort(referenceDevice, PortNumber.portNumber(1), true)); + testDeviceManager.listener.event(event); //Check that ports were populated correctly assertTrue("Unexpected number of new ports added", - mgr.deviceService.getPorts(NetTestTools.did("1")).size() == 10); + mgr.deviceService.getPorts(NetTestTools.did("1")).size() == 10); //Check that of the ten ports the half that are infrastructure ports aren't added assertEquals("Unexpected number of new edge ports added", (totalPorts - numInfraPorts), events.size()); @@ -219,15 +210,15 @@ public class EdgeManagerTest { //Names here are irrelevant, the first 5 ports are populated as infrastructure, 6-10 are edge for (int index = 0; index < events.size(); index++) { assertEquals("Port added had unexpected port number.", - events.get(index).subject().port(), - NetTestTools.connectPoint("a", index + numInfraPorts + 1).port()); + events.get(index).subject().port(), + NetTestTools.connectPoint("a", index + numInfraPorts + 1).port()); } events.clear(); //Repost the event to test repeated posts - testTopologyManager.listener.event(event); + testDeviceManager.listener.event(event); assertEquals("The redundant notification should not have created additional notifications.", - 0, events.size()); + 0, events.size()); //Calculate the size of the returned iterable of edge points. Iterable pts = mgr.getEdgePoints(); Iterator pointIterator = pts.iterator(); @@ -238,45 +229,41 @@ public class EdgeManagerTest { assertEquals("Unexpected number of edge points", totalPorts - numInfraPorts, count); //Testing device removal events.clear(); - eventsToAdd.clear(); - eventsToAdd.add(new DeviceEvent(DEVICE_REMOVED, referenceDevice, - new DefaultPort(referenceDevice, PortNumber.portNumber(1), true))); - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); + event = (new DeviceEvent(DEVICE_REMOVED, referenceDevice, + new DefaultPort(referenceDevice, PortNumber.portNumber(1), true))); + testDeviceManager.listener.event(event); assertEquals("There should be five new events from removal of edge points", - totalPorts - numInfraPorts, events.size()); + totalPorts - numInfraPorts, events.size()); for (int index = 0; index < events.size(); index++) { //Assert that the correct port numbers were removed in the correct order assertEquals("Port removed had unexpected port number.", - events.get(index).subject().port(), - (NetTestTools.connectPoint("a", index + numInfraPorts + 1).port())); + events.get(index).subject().port(), + (NetTestTools.connectPoint("a", index + numInfraPorts + 1).port())); //Assert that the events are of the correct type assertEquals("Unexpected type of event", events.get(index).type(), EDGE_PORT_REMOVED); } events.clear(); //Rebroadcast event to check that it triggers no new behavior - testTopologyManager.listener.event(event); + testDeviceManager.listener.event(event); assertEquals("Rebroadcast of removal event should not produce additional events", - 0, events.size()); + 0, events.size()); //Testing device status change, changed from unavailable to available events.clear(); - eventsToAdd.clear(); //Make sure that the devicemanager shows the device as available. addDevice(referenceDevice, "1", 5); devices.put(referenceDevice.id(), referenceDevice); - eventsToAdd.add(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, referenceDevice)); - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); + event = new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, referenceDevice); + testDeviceManager.listener.event(event); //An earlier setup set half of the reference device ports to infrastructure assertEquals("An unexpected number of events were generated.", totalPorts - numInfraPorts, events.size()); for (int i = 0; i < 5; i++) { assertEquals("The event was not of the right type", events.get(i).type(), EDGE_PORT_ADDED); } events.clear(); - testTopologyManager.listener.event(event); + testDeviceManager.listener.event(event); assertEquals("No events should have been generated for a set of existing ports.", 0, events.size()); //Test removal when state changes when the device becomes unavailable @@ -288,21 +275,20 @@ public class EdgeManagerTest { no events will be generated since no ports will be provided in getPorts() to EdgeManager. */ alwaysReturnPorts = true; - testTopologyManager.listener.event(event); + testDeviceManager.listener.event(event); alwaysReturnPorts = false; assertEquals("An unexpected number of events were created.", totalPorts - numInfraPorts, events.size()); for (int i = 0; i < 5; i++) { EdgePortEvent edgeEvent = events.get(i); assertEquals("The event is of an unexpected type.", - EdgePortEvent.Type.EDGE_PORT_REMOVED, edgeEvent.type()); + EdgePortEvent.Type.EDGE_PORT_REMOVED, edgeEvent.type()); assertEquals("The event pertains to an unexpected port", PortNumber.portNumber(i + numInfraPorts + 1), - edgeEvent.subject().port()); + edgeEvent.subject().port()); } } @Test public void testInternalCache() { - List eventsToAdd = Lists.newArrayList(); int numDevices = 10; //Number of infrastructure ports per device int numPorts = 5; @@ -312,11 +298,8 @@ public class EdgeManagerTest { for (int i = 0; i < numDevices; i++) { Device newDevice = NetTestTools.device(Integer.toString(i)); devices.put(newDevice.id(), newDevice); - eventsToAdd.add(new DeviceEvent(DEVICE_ADDED, newDevice)); + testDeviceManager.listener.event(new DeviceEvent(DEVICE_ADDED, newDevice)); } - TopologyEvent event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); - //Check all ports have correct designations ConnectPoint testPoint; for (int deviceNum = 0; deviceNum < numDevices; deviceNum++) { @@ -334,7 +317,7 @@ public class EdgeManagerTest { count++; } assertEquals("There are an unexpeceted number of edge points returned.", - (totalPorts - numPorts) * numDevices, count); + (totalPorts - numPorts) * numDevices, count); for (int deviceNumber = 0; deviceNumber < numDevices; deviceNumber++) { count = 0; for (ConnectPoint ignored : mgr.getEdgePoints(NetTestTools.did("1"))) { @@ -349,8 +332,7 @@ public class EdgeManagerTest { public void testEmit() { byte[] arr = new byte[10]; Device referenceDevice; - TopologyEvent event; - List eventsToAdd = Lists.newArrayList(); + DeviceEvent event; int numDevices = 10; int numInfraPorts = 5; totalPorts = 10; @@ -360,16 +342,16 @@ public class EdgeManagerTest { } for (int i = 0; i < numDevices; i++) { referenceDevice = NetTestTools.device(Integer.toString(i)); - eventsToAdd.add(new DeviceEvent(DEVICE_ADDED, referenceDevice, - new DefaultPort(referenceDevice, PortNumber.portNumber(1), true))); + testDeviceManager.listener.event(new DeviceEvent(DEVICE_ADDED, referenceDevice, + new DefaultPort(referenceDevice, + PortNumber.portNumber(1), + true))); } - event = new TopologyEvent(TOPOLOGY_CHANGED, null, eventsToAdd); - testTopologyManager.listener.event(event); mgr.emitPacket(ByteBuffer.wrap(arr), Optional.empty()); assertEquals("There were an unexpected number of emitted packets", - (totalPorts - numInfraPorts) * numDevices, packets.size()); + (totalPorts - numInfraPorts) * numDevices, packets.size()); Iterator packetIter = packets.iterator(); OutboundPacket packet; while (packetIter.hasNext()) { @@ -381,7 +363,7 @@ public class EdgeManagerTest { mgr.emitPacket(NetTestTools.did(Integer.toString(1)), ByteBuffer.wrap(arr), Optional.empty()); assertEquals("Unexpected number of outbound packets were emitted.", - totalPorts - numInfraPorts, packets.size()); + totalPorts - numInfraPorts, packets.size()); packetIter = packets.iterator(); while (packetIter.hasNext()) { packet = packetIter.next(); @@ -455,6 +437,7 @@ public class EdgeManagerTest { } private class TestDeviceManager extends DeviceServiceAdapter { + private DeviceListener listener; private Map devices; @@ -490,6 +473,17 @@ public class EdgeManagerTest { public Iterable getAvailableDevices() { return devices.values(); } + + + @Override + public void addListener(DeviceListener listener) { + this.listener = listener; + } + + @Override + public void removeListener(DeviceListener listener) { + this.listener = null; + } } private class TestPacketManager extends PacketServiceAdapter { @@ -499,6 +493,15 @@ public class EdgeManagerTest { } } + private class TestLinkManager extends LinkServiceAdapter { + private LinkListener listener; + + @Override + public void addListener(LinkListener listener) { + this.listener = listener; + } + } + private class TestListener implements EdgePortListener { private List events; diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java index eb7f2ccd..7cee0d0e 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java @@ -29,8 +29,10 @@ import org.onlab.junit.TestUtils.TestUtilsException; import org.onosproject.core.IdGenerator; import org.onosproject.event.Event; import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; import org.onosproject.net.Link; import org.onosproject.net.NetworkResource; +import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.intent.Intent; @@ -52,7 +54,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.onosproject.net.LinkKey.linkKey; import static org.onosproject.net.newresource.ResourceEvent.Type.*; import static org.onosproject.net.NetTestTools.APP_ID; import static org.onosproject.net.NetTestTools.device; @@ -231,7 +232,7 @@ public class ObjectiveTrackerTest { @Test public void testResourceEvent() throws Exception { ResourceEvent event = new ResourceEvent(RESOURCE_ADDED, - ResourcePath.discrete(linkKey(link("a", 1, "b", 1)))); + ResourcePath.discrete(DeviceId.deviceId("a"), PortNumber.portNumber(1))); resourceListener.event(event); assertThat( diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java index c6d300c9..af2bb74d 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java @@ -20,6 +20,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Maps; + import org.onlab.util.HexString; import org.onlab.util.SharedExecutors; import org.onlab.util.Tools; @@ -33,6 +34,7 @@ import org.onosproject.store.service.Versioned; import org.slf4j.Logger; import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; @@ -92,18 +94,25 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap keyCache = CacheBuilder.newBuilder() + // String representation of serialized byte[] -> original key Object + private final LoadingCache keyCache = CacheBuilder.newBuilder() .softValues() - .build(new CacheLoader() { + .build(new CacheLoader() { @Override - public String load(K key) { - return HexString.toHexString(serializer.encode(key)); + public K load(String key) { + return serializer.decode(HexString.fromHexString(key)); } }); + protected String sK(K key) { + String s = HexString.toHexString(serializer.encode(key)); + keyCache.put(s, key); + return s; + } + protected K dK(String key) { - return serializer.decode(HexString.fromHexString(key)); + return keyCache.getUnchecked(key); } public DefaultAsyncConsistentMap(String name, @@ -207,7 +216,7 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap containsKey(K key) { checkNotNull(key, ERROR_NULL_KEY); final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_KEY); - return database.mapContainsKey(name, keyCache.getUnchecked(key)) + return database.mapContainsKey(name, sK(key)) .whenComplete((r, e) -> timer.stop(e)); } @@ -223,7 +232,7 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap> get(K key) { checkNotNull(key, ERROR_NULL_KEY); final MeteringAgent.Context timer = monitor.startTimer(GET); - return database.mapGet(name, keyCache.getUnchecked(key)) + return database.mapGet(name, sK(key)) .whenComplete((r, e) -> timer.stop(e)) .thenApply(v -> v != null ? v.map(serializer::decode) : null); } @@ -328,10 +337,7 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap> keySet() { final MeteringAgent.Context timer = monitor.startTimer(KEY_SET); return database.mapKeySet(name) - .thenApply(s -> s - .stream() - .map(this::dK) - .collect(Collectors.toSet())) + .thenApply(s -> newMappingKeySet(s)) .whenComplete((r, e) -> timer.stop(e)); } @@ -351,10 +357,7 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap timer.stop(e)) - .thenApply(s -> s - .stream() - .map(this::mapRawEntry) - .collect(Collectors.toSet())); + .thenApply(s -> newMappingEntrySet(s)); } @Override @@ -413,17 +416,31 @@ public class DefaultAsyncConsistentMap implements AsyncConsistentMap newMappingKeySet(Set s) { + return new MappingSet<>(s, Collections::unmodifiableSet, + this::sK, this::dK); + } + + private Set>> newMappingEntrySet(Set>> s) { + return new MappingSet<>(s, Collections::unmodifiableSet, + this::reverseMapRawEntry, this::mapRawEntry); + } + private Map.Entry> mapRawEntry(Map.Entry> e) { return Maps.immutableEntry(dK(e.getKey()), e.getValue().map(serializer::decode)); } + private Map.Entry> reverseMapRawEntry(Map.Entry> e) { + return Maps.immutableEntry(sK(e.getKey()), e.getValue().map(serializer::encode)); + } + private CompletableFuture> updateAndGet(K key, Match oldValueMatch, Match oldVersionMatch, V value) { beforeUpdate(key); return database.mapUpdate(name, - keyCache.getUnchecked(key), + sK(key), oldValueMatch.map(serializer::encode), oldVersionMatch, value == null ? null : serializer.encode(value)) diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java new file mode 100644 index 00000000..9bf80a73 --- /dev/null +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java @@ -0,0 +1,131 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.consistent.impl; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.google.common.collect.Iterators; + +/** + * Set view backed by Set with element type {@code } but returns + * element as {@code } for convenience. + * + * @param Backing {@link Set} element type. + * MappingSet will follow this type's equality behavior. + * @param external facing element type. + * MappingSet will ignores equality defined by this type. + */ +class MappingSet implements Set { + + private final Set backedSet; + private final Function toBack; + private final Function toOut; + + public MappingSet(Set backedSet, + Function, Set> supplier, + Function toBack, Function toOut) { + this.backedSet = supplier.apply(backedSet); + this.toBack = toBack; + this.toOut = toOut; + } + + @Override + public int size() { + return backedSet.size(); + } + + @Override + public boolean isEmpty() { + return backedSet.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return backedSet.contains(toBack.apply((OUT) o)); + } + + @Override + public Iterator iterator() { + return Iterators.transform(backedSet.iterator(), toOut::apply); + } + + @Override + public Object[] toArray() { + return backedSet.stream() + .map(toOut) + .toArray(); + } + + @Override + public T[] toArray(T[] a) { + return backedSet.stream() + .map(toOut) + .toArray(size -> { + if (size < a.length) { + return (T[]) new Object[size]; + } else { + Arrays.fill(a, null); + return a; + } + }); + } + + @Override + public boolean add(OUT e) { + return backedSet.add(toBack.apply(e)); + } + + @Override + public boolean remove(Object o) { + return backedSet.remove(toBack.apply((OUT) o)); + } + + @Override + public boolean containsAll(Collection c) { + return c.stream() + .map(e -> toBack.apply((OUT) e)) + .allMatch(backedSet::contains); + } + + @Override + public boolean addAll(Collection c) { + return backedSet.addAll(c.stream().map(toBack).collect(Collectors.toList())); + } + + @Override + public boolean retainAll(Collection c) { + return backedSet.retainAll(c.stream() + .map(x -> toBack.apply((OUT) x)) + .collect(Collectors.toList())); + } + + @Override + public boolean removeAll(Collection c) { + return backedSet.removeAll(c.stream() + .map(x -> toBack.apply((OUT) x)) + .collect(Collectors.toList())); + } + + @Override + public void clear() { + backedSet.clear(); + } +} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java index 83319c3e..cc32a735 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java @@ -350,7 +350,7 @@ public class DistributedGroupStore // Check if a group is existing with the same key Group existingGroup = getGroup(groupDesc.deviceId(), groupDesc.appCookie()); if (existingGroup != null) { - log.warn("Group already exists with the same key {} in dev:{} with id:{}", + log.warn("Group already exists with the same key {} in dev:{} with id:0x{}", groupDesc.appCookie(), groupDesc.deviceId(), Integer.toHexString(existingGroup.id().id())); return; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java new file mode 100644 index 00000000..836a3c22 --- /dev/null +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java @@ -0,0 +1,265 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.host.impl; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.Annotations; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultHost; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Host; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.host.HostEvent; +import org.onosproject.net.host.HostStore; +import org.onosproject.net.host.HostStoreDelegate; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.AbstractStore; +import org.onosproject.store.serializers.KryoNamespaces; +import org.onosproject.store.service.ConsistentMap; +import org.onosproject.store.service.MapEvent; +import org.onosproject.store.service.MapEventListener; +import org.onosproject.store.service.Serializer; +import org.onosproject.store.service.StorageService; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.onosproject.net.DefaultAnnotations.merge; +import static org.onosproject.net.host.HostEvent.Type.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Manages the inventory of hosts using a {@code EventuallyConsistentMap}. + */ +@Component(immediate = true) +@Service +public class DistributedHostStore + extends AbstractStore + implements HostStore { + + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + private ConsistentMap host; + private Map hosts; + + private final ConcurrentHashMap prevHosts = + new ConcurrentHashMap<>(); + + private MapEventListener hostLocationTracker = + new HostLocationTracker(); + + @Activate + public void activate() { + KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() + .register(KryoNamespaces.API); + + host = storageService.consistentMapBuilder() + .withName("onos-hosts") + .withRelaxedReadConsistency() + .withSerializer(Serializer.using(hostSerializer.build())) + .build(); + + hosts = host.asJavaMap(); + + host.addListener(hostLocationTracker); + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + host.removeListener(hostLocationTracker); + prevHosts.clear(); + + log.info("Stopped"); + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent createOrUpdateHost(ProviderId providerId, + HostId hostId, + HostDescription hostDescription, + boolean replaceIPs) { + // TODO: We need a way to detect conflicting changes and abort update. + // (BOC) Compute might do this for us. + + hosts.compute(hostId, (id, existingHost) -> { + HostLocation location = hostDescription.location(); + + final Set addresses; + if (existingHost == null || replaceIPs) { + addresses = ImmutableSet.copyOf(hostDescription.ipAddress()); + } else { + addresses = Sets.newHashSet(existingHost.ipAddresses()); + addresses.addAll(hostDescription.ipAddress()); + } + + final Annotations annotations; + if (existingHost != null) { + annotations = merge((DefaultAnnotations) existingHost.annotations(), + hostDescription.annotations()); + } else { + annotations = hostDescription.annotations(); + } + + return new DefaultHost(providerId, + hostId, + hostDescription.hwAddress(), + hostDescription.vlan(), + location, + addresses, + annotations); + }); + + return null; + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent removeHost(HostId hostId) { + hosts.remove(hostId); + return null; + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent removeIp(HostId hostId, IpAddress ipAddress) { + hosts.compute(hostId, (id, existingHost) -> { + if (existingHost != null) { + checkState(Objects.equals(hostId.mac(), existingHost.mac()), + "Existing and new MAC addresses differ."); + checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()), + "Existing and new VLANs differ."); + + Set addresses = existingHost.ipAddresses(); + if (addresses != null && addresses.contains(ipAddress)) { + addresses = new HashSet<>(existingHost.ipAddresses()); + addresses.remove(ipAddress); + return new DefaultHost(existingHost.providerId(), + hostId, + existingHost.mac(), + existingHost.vlan(), + existingHost.location(), + ImmutableSet.copyOf(addresses), + existingHost.annotations()); + } else { + return existingHost; + } + } + return null; + }); + return null; + } + + @Override + public int getHostCount() { + return hosts.size(); + } + + @Override + public Iterable getHosts() { + return ImmutableSet.copyOf(hosts.values()); + } + + @Override + public Host getHost(HostId hostId) { + return hosts.get(hostId); + } + + @Override + public Set getHosts(VlanId vlanId) { + return filter(hosts.values(), host -> Objects.equals(host.vlan(), vlanId)); + } + + @Override + public Set getHosts(MacAddress mac) { + return filter(hosts.values(), host -> Objects.equals(host.mac(), mac)); + } + + @Override + public Set getHosts(IpAddress ip) { + return filter(hosts.values(), host -> host.ipAddresses().contains(ip)); + } + + @Override + public Set getConnectedHosts(ConnectPoint connectPoint) { + Set filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().equals(connectPoint)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + return ImmutableSet.copyOf(filtered); + } + + @Override + public Set getConnectedHosts(DeviceId deviceId) { + Set filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().deviceId().equals(deviceId)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + return ImmutableSet.copyOf(filtered); + } + + private Set filter(Collection collection, Predicate predicate) { + return collection.stream().filter(predicate).collect(Collectors.toSet()); + } + + private class HostLocationTracker implements MapEventListener { + @Override + public void event(MapEvent event) { + DefaultHost host = checkNotNull(event.value().value()); + if (event.type() == MapEvent.Type.INSERT) { + Host prevHost = prevHosts.put(host.id(), host); + if (prevHost == null) { + notifyDelegate(new HostEvent(HOST_ADDED, host)); + } else if (!Objects.equals(prevHost.location(), host.location())) { + notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost)); + } else if (!Objects.equals(prevHost, host)) { + notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost)); + } + } else if (event.type() == MapEvent.Type.REMOVE) { + if (prevHosts.remove(host.id()) != null) { + notifyDelegate(new HostEvent(HOST_REMOVED, host)); + } + } + } + } +} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java deleted file mode 100644 index 20124576..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.host.impl; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; -import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED; -import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED; -import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.packet.IpAddress; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.Annotations; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultHost; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.host.HostDescription; -import org.onosproject.net.host.HostEvent; -import org.onosproject.net.host.HostStore; -import org.onosproject.net.host.HostStoreDelegate; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; - -/** - * Manages the inventory of hosts using a {@code EventuallyConsistentMap}. - */ -@Component(immediate = true) -@Service -public class ECHostStore - extends AbstractStore - implements HostStore { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LogicalClockService clockService; - - private EventuallyConsistentMap hosts; - - private final ConcurrentHashMap prevHosts = - new ConcurrentHashMap<>(); - - private EventuallyConsistentMapListener hostLocationTracker = - new HostLocationTracker(); - - @Activate - public void activate() { - KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API); - - hosts = storageService.eventuallyConsistentMapBuilder() - .withName("onos-hosts") - .withSerializer(hostSerializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - - hosts.addListener(hostLocationTracker); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - hosts.removeListener(hostLocationTracker); - hosts.destroy(); - prevHosts.clear(); - - log.info("Stopped"); - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent createOrUpdateHost(ProviderId providerId, - HostId hostId, - HostDescription hostDescription, - boolean replaceIPs) { - // TODO: We need a way to detect conflicting changes and abort update. - // (BOC) Compute might do this for us. - - hosts.compute(hostId, (id, existingHost) -> { - HostLocation location = hostDescription.location(); - - final Set addresses; - if (existingHost == null || replaceIPs) { - addresses = ImmutableSet.copyOf(hostDescription.ipAddress()); - } else { - addresses = Sets.newHashSet(existingHost.ipAddresses()); - addresses.addAll(hostDescription.ipAddress()); - } - - final Annotations annotations; - if (existingHost != null) { - annotations = merge((DefaultAnnotations) existingHost.annotations(), - hostDescription.annotations()); - } else { - annotations = hostDescription.annotations(); - } - - return new DefaultHost(providerId, - hostId, - hostDescription.hwAddress(), - hostDescription.vlan(), - location, - addresses, - annotations); - }); - - return null; - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent removeHost(HostId hostId) { - hosts.remove(hostId); - return null; - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent removeIp(HostId hostId, IpAddress ipAddress) { - hosts.compute(hostId, (id, existingHost) -> { - if (existingHost != null) { - checkState(Objects.equals(hostId.mac(), existingHost.mac()), - "Existing and new MAC addresses differ."); - checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()), - "Existing and new VLANs differ."); - - Set addresses = existingHost.ipAddresses(); - if (addresses != null && addresses.contains(ipAddress)) { - addresses = new HashSet<>(existingHost.ipAddresses()); - addresses.remove(ipAddress); - return new DefaultHost(existingHost.providerId(), - hostId, - existingHost.mac(), - existingHost.vlan(), - existingHost.location(), - ImmutableSet.copyOf(addresses), - existingHost.annotations()); - } else { - return existingHost; - } - } - return null; - }); - return null; - } - - @Override - public int getHostCount() { - return hosts.size(); - } - - @Override - public Iterable getHosts() { - return ImmutableSet.copyOf(hosts.values()); - } - - @Override - public Host getHost(HostId hostId) { - return hosts.get(hostId); - } - - @Override - public Set getHosts(VlanId vlanId) { - return filter(hosts.values(), host -> Objects.equals(host.vlan(), vlanId)); - } - - @Override - public Set getHosts(MacAddress mac) { - return filter(hosts.values(), host -> Objects.equals(host.mac(), mac)); - } - - @Override - public Set getHosts(IpAddress ip) { - return filter(hosts.values(), host -> host.ipAddresses().contains(ip)); - } - - @Override - public Set getConnectedHosts(ConnectPoint connectPoint) { - Set filtered = hosts.entrySet().stream() - .filter(entry -> entry.getValue().location().equals(connectPoint)) - .map(Map.Entry::getValue) - .collect(Collectors.toSet()); - return ImmutableSet.copyOf(filtered); - } - - @Override - public Set getConnectedHosts(DeviceId deviceId) { - Set filtered = hosts.entrySet().stream() - .filter(entry -> entry.getValue().location().deviceId().equals(deviceId)) - .map(Map.Entry::getValue) - .collect(Collectors.toSet()); - return ImmutableSet.copyOf(filtered); - } - - private Set filter(Collection collection, Predicate predicate) { - return collection.stream().filter(predicate).collect(Collectors.toSet()); - } - - private class HostLocationTracker implements EventuallyConsistentMapListener { - @Override - public void event(EventuallyConsistentMapEvent event) { - DefaultHost host = checkNotNull(event.value()); - if (event.type() == PUT) { - Host prevHost = prevHosts.put(host.id(), host); - if (prevHost == null) { - notifyDelegate(new HostEvent(HOST_ADDED, host)); - } else if (!Objects.equals(prevHost.location(), host.location())) { - notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost)); - } else if (!Objects.equals(prevHost, host)) { - notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost)); - } - } else if (event.type() == REMOVE) { - if (prevHosts.remove(host.id()) != null) { - notifyDelegate(new HostEvent(HOST_REMOVED, host)); - } - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java index 851185b5..4d7e7f33 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java @@ -113,7 +113,7 @@ public class DistributedProxyArpStore implements ProxyArpStore { @Override public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) { - NodeId nodeId = mastershipService.getMasterFor(outPort.deviceId()); + /*NodeId nodeId = mastershipService.getMasterFor(outPort.deviceId()); if (nodeId.equals(localNodeId)) { if (delegate != null) { delegate.emitResponse(outPort, packet); @@ -122,7 +122,10 @@ public class DistributedProxyArpStore implements ProxyArpStore { log.info("Forwarding ARP response from {} to {}", subject.id(), outPort); commService.unicast(new ArpResponseMessage(outPort, subject, packet.array()), ARP_RESPONSE_MESSAGE, serializer::encode, nodeId); - } + }*/ + //FIXME: Code above may be unnecessary and therefore cluster messaging + // and pendingMessages could be pruned as well. + delegate.emitResponse(outPort, packet); } @Override diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java index da4e3cc4..2641635d 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java @@ -15,44 +15,43 @@ */ package org.onosproject.store.topology.impl; -import static com.google.common.base.Preconditions.checkArgument; -import static org.onlab.util.Tools.isNullOrEmpty; -import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Collections; -import java.util.Map; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; +import org.onlab.graph.GraphPathSearch; import org.onlab.util.KryoNamespace; +import org.onosproject.cfg.ComponentConfigService; import org.onosproject.common.DefaultTopology; import org.onosproject.event.Event; import org.onosproject.mastership.MastershipService; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; +import org.onosproject.net.DisjointPath; import org.onosproject.net.Link; import org.onosproject.net.Path; -import org.onosproject.net.DisjointPath; +import org.onosproject.net.device.DeviceService; import org.onosproject.net.provider.ProviderId; import org.onosproject.net.topology.ClusterId; import org.onosproject.net.topology.DefaultGraphDescription; +import org.onosproject.net.topology.GeoDistanceLinkWeight; import org.onosproject.net.topology.GraphDescription; import org.onosproject.net.topology.LinkWeight; +import org.onosproject.net.topology.MetricLinkWeight; +import org.onosproject.net.topology.PathAdminService; import org.onosproject.net.topology.Topology; import org.onosproject.net.topology.TopologyCluster; +import org.onosproject.net.topology.TopologyEdge; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyGraph; import org.onosproject.net.topology.TopologyStore; import org.onosproject.net.topology.TopologyStoreDelegate; +import org.onosproject.net.topology.TopologyVertex; import org.onosproject.store.AbstractStore; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.EventuallyConsistentMap; @@ -60,8 +59,23 @@ import org.onosproject.store.service.EventuallyConsistentMapEvent; import org.onosproject.store.service.EventuallyConsistentMapListener; import org.onosproject.store.service.LogicalClockService; import org.onosproject.store.service.StorageService; +import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; +import java.util.Collections; +import java.util.Dictionary; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.onlab.util.Tools.get; +import static org.onlab.util.Tools.isNullOrEmpty; +import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; +import static org.slf4j.LoggerFactory.getLogger; + /** * Manages inventory of topology snapshots using trivial in-memory * structures implementation. @@ -73,9 +87,12 @@ import org.slf4j.Logger; @Service public class DistributedTopologyStore extends AbstractStore - implements TopologyStore { + implements TopologyStore, PathAdminService { private final Logger log = getLogger(getClass()); + + private static final String FORMAT = "Settings: linkWeightFunction={}"; + private volatile DefaultTopology current = new DefaultTopology(ProviderId.NONE, new DefaultGraphDescription(0L, System.currentTimeMillis(), @@ -91,6 +108,21 @@ public class DistributedTopologyStore @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected MastershipService mastershipService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ComponentConfigService configService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + private static final String HOP_COUNT = "hopCount"; + private static final String LINK_METRIC = "linkMetric"; + private static final String GEO_DISTANCE = "geoDistance"; + + private static final String DEFAULT_LINK_WEIGHT_FUNCTION = "hopCount"; + @Property(name = "linkWeightFunction", value = DEFAULT_LINK_WEIGHT_FUNCTION, + label = "Default link-weight function: hopCount, linkMetric, geoDistance") + private String linkWeightFunction = DEFAULT_LINK_WEIGHT_FUNCTION; + // Cluster root to broadcast points bindings to allow convergence to // a shared broadcast tree; node that is the master of the cluster root // is the primary. @@ -100,7 +132,8 @@ public class DistributedTopologyStore new InternalBroadcastPointListener(); @Activate - public void activate() { + protected void activate() { + configService.registerProperties(getClass()); KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() .register(KryoNamespaces.API); @@ -114,12 +147,30 @@ public class DistributedTopologyStore } @Deactivate - public void deactivate() { + protected void deactivate() { + configService.unregisterProperties(getClass(), false); broadcastPoints.removeListener(listener); broadcastPoints.destroy(); log.info("Stopped"); } + @Modified + protected void modified(ComponentContext context) { + Dictionary properties = context.getProperties(); + + String newLinkWeightFunction = get(properties, "linkWeightFunction"); + if (newLinkWeightFunction != null && + !Objects.equals(newLinkWeightFunction, linkWeightFunction)) { + linkWeightFunction = newLinkWeightFunction; + LinkWeight weight = linkWeightFunction.equals(LINK_METRIC) ? + new MetricLinkWeight() : + linkWeightFunction.equals(GEO_DISTANCE) ? + new GeoDistanceLinkWeight(deviceService) : null; + setDefaultLinkWeight(weight); + } + log.info(FORMAT, linkWeightFunction); + } + @Override public Topology currentTopology() { return current; @@ -263,6 +314,16 @@ public class DistributedTopologyStore return (DefaultTopology) topology; } + @Override + public void setDefaultLinkWeight(LinkWeight linkWeight) { + DefaultTopology.setDefaultLinkWeight(linkWeight); + } + + @Override + public void setDefaultGraphPathSearch(GraphPathSearch graphPathSearch) { + DefaultTopology.setDefaultGraphPathSearch(graphPathSearch); + } + private class InternalBroadcastPointListener implements EventuallyConsistentMapListener> { @Override diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java new file mode 100644 index 00000000..3f6402c5 --- /dev/null +++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java @@ -0,0 +1,369 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.consistent.impl; + +import static java.util.Collections.unmodifiableCollection; +import static java.util.Collections.unmodifiableSet; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.*; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.DefaultApplicationId; +import org.onosproject.store.service.Serializer; +import org.onosproject.store.service.Transaction; +import org.onosproject.store.service.Versioned; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import net.kuujo.copycat.Task; +import net.kuujo.copycat.cluster.Cluster; +import net.kuujo.copycat.resource.ResourceState; + +/** + * + */ +public class DefaultAsyncConsistentMapTest { + + private static final ApplicationId APP_ID = new DefaultApplicationId(42, "what"); + + private static final TestData KEY1A = new TestData("One", "a"); + private static final TestData KEY1B = new TestData("One", "b"); + + private static final TestData VALUE2A = new TestData("Two", "a"); + private static final TestData VALUE2B = new TestData("Two", "b"); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testKeySet() throws Exception { + DefaultAsyncConsistentMap map; + String name = "map_name"; + Database database = new TestDatabase(); + Serializer serializer = Serializer.forTypes(TestData.class); + + map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer, + false, false, false); + map.put(KEY1A, VALUE2A); + map.put(KEY1B, VALUE2A); + + Set set = map.keySet().get(); + assertEquals("Should contain 2 keys", + 2, set.size()); + assertThat(set.contains(KEY1A), is(true)); + assertThat(set.contains(KEY1B), is(true)); + assertThat(set.contains(new TestData("One", "a")), is(true)); + } + + @Test + public void testEntrySet() throws Exception { + DefaultAsyncConsistentMap map; + String name = "map_name"; + Database database = new TestDatabase(); + Serializer serializer = Serializer.forTypes(TestData.class); + + map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer, + false, false, false); + map.put(KEY1A, VALUE2A); + map.put(KEY1B, VALUE2A); + + assertEquals("Should contain 2 entry", + 2, + map.entrySet().get().size()); + } + + /** + * Object to be used as a test data. + * + * {@link Object#equals(Object)} use only part of it's fields. + * + * As a result there can be 2 instances which the + * serialized bytes are not-equal but + * {@link Object#equals(Object)}-wise they are equal. + */ + public static class TestData { + + private final String theKey; + + @SuppressWarnings("unused") + private final String notUsedForEquals; + + public TestData(String theKey, String notUsedForEquals) { + this.theKey = theKey; + this.notUsedForEquals = notUsedForEquals; + } + + @Override + public int hashCode() { + return Objects.hashCode(theKey); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TestData) { + TestData that = (TestData) obj; + return Objects.equals(this.theKey, that.theKey); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("theKey", theKey) + .add("notUsedForEquals", notUsedForEquals) + .toString(); + } + } + + /** + * {@link Database} implementation for testing. + * + * There is only 1 backing Map, {@code mapName} will be ignored. + */ + public class TestDatabase implements Database { + + Map> map = new ConcurrentHashMap<>(); + + @Override + public CompletableFuture> maps() { + return CompletableFuture.completedFuture(ImmutableSet.of()); + } + + @Override + public CompletableFuture> counters() { + return CompletableFuture.completedFuture(ImmutableMap.of()); + } + + @Override + public CompletableFuture mapSize(String mapName) { + return CompletableFuture.completedFuture(map.size()); + } + + @Override + public CompletableFuture mapIsEmpty(String mapName) { + return CompletableFuture.completedFuture(map.isEmpty()); + } + + @Override + public CompletableFuture mapContainsKey(String mapName, + String key) { + return CompletableFuture.completedFuture(map.containsKey(key)); + } + + @Override + public CompletableFuture mapContainsValue(String mapName, + byte[] value) { + return CompletableFuture.completedFuture(map.containsValue(value)); + } + + @Override + public CompletableFuture> mapGet(String mapName, + String key) { + return CompletableFuture.completedFuture(map.get(key)); + } + + @Override + public synchronized CompletableFuture>> mapUpdate(String mapName, + String key, + Match valueMatch, + Match versionMatch, + byte[] value) { + + boolean updated = false; + final Versioned oldValue; + final Versioned newValue; + + Versioned old = map.getOrDefault(key, new Versioned(null, 0)); + if (valueMatch.matches(old.value()) && versionMatch.matches(old.version())) { + updated = true; + oldValue = old; + newValue = new Versioned<>(value, old.version() + 1); + map.put(key, newValue); + } else { + updated = false; + oldValue = old; + newValue = old; + } + return CompletableFuture.completedFuture( + Result.ok(new UpdateResult(updated, + mapName, key, oldValue, newValue))); + } + + @Override + public CompletableFuture> mapClear(String mapName) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture> mapKeySet(String mapName) { + return CompletableFuture.completedFuture(unmodifiableSet(map.keySet())); + } + + @Override + public CompletableFuture>> mapValues(String mapName) { + return CompletableFuture.completedFuture(unmodifiableCollection(map.values())); + } + + @Override + public CompletableFuture>>> mapEntrySet(String mapName) { + return CompletableFuture.completedFuture(unmodifiableSet(map.entrySet())); + } + + @Override + public CompletableFuture counterAddAndGet(String counterName, + long delta) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture counterGetAndAdd(String counterName, + long delta) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture counterSet(String counterName, + long value) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture counterCompareAndSet(String counterName, + long expectedValue, + long update) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture counterGet(String counterName) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture queueSize(String queueName) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture queuePush(String queueName, + byte[] entry) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture queuePop(String queueName) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture queuePeek(String queueName) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture prepareAndCommit(Transaction transaction) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture prepare(Transaction transaction) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture commit(Transaction transaction) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture rollback(Transaction transaction) { + throw new UnsupportedOperationException(); + } + + @Override + public String name() { + return "name"; + } + + @Override + public ResourceState state() { + return ResourceState.HEALTHY; + } + + @Override + public Cluster cluster() { + throw new UnsupportedOperationException(); + } + + @Override + public Database addStartupTask(Task> task) { + throw new UnsupportedOperationException(); + } + + @Override + public Database addShutdownTask(Task> task) { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture open() { + return CompletableFuture.completedFuture(this); + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public CompletableFuture close() { + return CompletableFuture.completedFuture(null); + } + + @Override + public boolean isClosed() { + return false; + } + + @Override + public void registerConsumer(Consumer consumer) { + } + + @Override + public void unregisterConsumer(Consumer consumer) { + } + } + +} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java index ef8d9924..b74aa370 100644 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java +++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java @@ -42,12 +42,13 @@ import org.onosproject.cluster.ControllerNode; import org.onosproject.cluster.DefaultControllerNode; import org.onosproject.cluster.NodeId; import org.onosproject.event.AbstractEvent; -import org.onosproject.persistence.impl.PersistenceManager; +import org.onosproject.persistence.PersistenceService; import org.onosproject.store.Timestamp; import org.onosproject.store.cluster.messaging.ClusterCommunicationService; import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter; import org.onosproject.store.cluster.messaging.MessageSubject; import org.onosproject.store.impl.LogicalTimestamp; +import org.onosproject.store.persistence.TestPersistenceService; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.serializers.KryoSerializer; import org.onosproject.store.service.EventuallyConsistentMap; @@ -82,7 +83,7 @@ public class EventuallyConsistentMapImplTest { private EventuallyConsistentMap ecMap; - private PersistenceManager persistenceService; + private PersistenceService persistenceService; private ClusterService clusterService; private ClusterCommunicationService clusterCommunicator; private SequentialClockService clockService; @@ -138,8 +139,7 @@ public class EventuallyConsistentMapImplTest { clusterCommunicator = createMock(ClusterCommunicationService.class); - persistenceService = new PersistenceManager(); - persistenceService.activate(); + persistenceService = new TestPersistenceService(); // Add expectation for adding cluster message subscribers which // delegate to our ClusterCommunicationService implementation. This // allows us to get a reference to the map's internal cluster message diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java new file mode 100644 index 00000000..0732126d --- /dev/null +++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.host.impl; + +import junit.framework.TestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onosproject.net.Host; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.host.DefaultHostDescription; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.service.TestStorageService; + +import java.util.HashSet; +import java.util.Set; + +/** + * Tests for the ECHostStore. + */ +public class DistributedHostStoreTest extends TestCase { + + private DistributedHostStore ecXHostStore; + + private static final HostId HOSTID = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a")); + + private static final IpAddress IP1 = IpAddress.valueOf("10.2.0.2"); + private static final IpAddress IP2 = IpAddress.valueOf("10.2.0.3"); + + private static final ProviderId PID = new ProviderId("of", "foo"); + + @Before + public void setUp() { + ecXHostStore = new DistributedHostStore(); + + ecXHostStore.storageService = new TestStorageService(); + ecXHostStore.activate(); + } + + @After + public void tearDown() { + ecXHostStore.deactivate(); + } + + /** + * Tests the removeIp method call. + */ + @Test + public void testRemoveIp() { + Set ips = new HashSet<>(); + ips.add(IP1); + ips.add(IP2); + + HostDescription description = new DefaultHostDescription(HOSTID.mac(), + HOSTID.vlanId(), + HostLocation.NONE, + ips); + ecXHostStore.createOrUpdateHost(PID, HOSTID, description, false); + ecXHostStore.removeIp(HOSTID, IP1); + Host host = ecXHostStore.getHost(HOSTID); + + assertFalse(host.ipAddresses().contains(IP1)); + assertTrue(host.ipAddresses().contains(IP2)); + } + +} \ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/ECHostStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/ECHostStoreTest.java deleted file mode 100644 index a7077a81..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/ECHostStoreTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.host.impl; - -import junit.framework.TestCase; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.packet.IpAddress; -import org.onlab.packet.MacAddress; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.host.DefaultHostDescription; -import org.onosproject.net.host.HostDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.Timestamp; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.TestStorageService; - -import java.util.HashSet; -import java.util.Set; - -/** - * Tests for the ECHostStore. - */ -public class ECHostStoreTest extends TestCase { - - private ECHostStore ecXHostStore; - - private static final HostId HOSTID = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a")); - - private static final IpAddress IP1 = IpAddress.valueOf("10.2.0.2"); - private static final IpAddress IP2 = IpAddress.valueOf("10.2.0.3"); - - private static final ProviderId PID = new ProviderId("of", "foo"); - - @Before - public void setUp() { - ecXHostStore = new ECHostStore(); - - ecXHostStore.storageService = new TestStorageService(); - ecXHostStore.clockService = new TestLogicalClockService(); - ecXHostStore.activate(); - } - - @After - public void tearDown() { - ecXHostStore.deactivate(); - } - - /** - * Tests the removeIp method call. - */ - @Test - public void testRemoveIp() { - Set ips = new HashSet<>(); - ips.add(IP1); - ips.add(IP2); - - HostDescription description = new DefaultHostDescription(HOSTID.mac(), - HOSTID.vlanId(), - HostLocation.NONE, - ips); - ecXHostStore.createOrUpdateHost(PID, HOSTID, description, false); - ecXHostStore.removeIp(HOSTID, IP1); - Host host = ecXHostStore.getHost(HOSTID); - - assertFalse(host.ipAddresses().contains(IP1)); - assertTrue(host.ipAddresses().contains(IP2)); - } - - /** - * Mocks the LogicalClockService class. - */ - class TestLogicalClockService implements LogicalClockService { - @Override - public Timestamp getTimestamp() { - return null; - } - } -} \ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java index 3428bce1..05c577c0 100644 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java +++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java @@ -47,7 +47,6 @@ import static org.slf4j.LoggerFactory.getLogger; public class PersistenceManager implements PersistenceService { private static final String DATABASE_PATH = "../data/localDB"; - private static final String ENCLOSING_FOLDER = "../data"; static final String MAP_PREFIX = "map:"; diff --git a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java b/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java index 45b4da1a..7df518e2 100644 --- a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java +++ b/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java @@ -374,13 +374,13 @@ public class KryoSerializerTest { @Test public void testResourcePath() { - testSerializedEquals(ResourcePath.discrete(LinkKey.linkKey(CP1, CP2), VLAN1)); + testSerializedEquals(ResourcePath.discrete(DID1, P1, VLAN1)); } @Test public void testResourceAllocation() { testSerializedEquals(new org.onosproject.net.newresource.ResourceAllocation( - ResourcePath.discrete(LinkKey.linkKey(CP1, CP2), VLAN1), + ResourcePath.discrete(DID1, P1, VLAN1), IntentId.valueOf(30))); } diff --git a/framework/src/onos/docs/external-excludes b/framework/src/onos/docs/external-excludes index 1890de18..8b8a3d50 100644 --- a/framework/src/onos/docs/external-excludes +++ b/framework/src/onos/docs/external-excludes @@ -52,3 +52,5 @@ org.onosproject.cord* org.onosproject.mfwd* org.onosproject.mcast* org.onosproject.flowanalyzer +org.onosproject.grpc* +protobuf.* diff --git a/framework/src/onos/docs/external.xml b/framework/src/onos/docs/external.xml index 37463c34..aac47eb5 100644 --- a/framework/src/onos/docs/external.xml +++ b/framework/src/onos/docs/external.xml @@ -46,7 +46,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.3 package @external-excludes @@ -72,7 +71,7 @@ - rsModel + onos.rsModel m Json model for REST api: diff --git a/framework/src/onos/docs/internal-excludes b/framework/src/onos/docs/internal-excludes index 9876ccea..2ae8a261 100644 --- a/framework/src/onos/docs/internal-excludes +++ b/framework/src/onos/docs/internal-excludes @@ -3,3 +3,5 @@ org.onlab.stc* org.onlab.thirdparty org.onosproject.oecfg org.onosproject.maven +org.onosproject.grpc* +protobuf.* diff --git a/framework/src/onos/docs/internal.xml b/framework/src/onos/docs/internal.xml index d1525aaa..569da1b8 100644 --- a/framework/src/onos/docs/internal.xml +++ b/framework/src/onos/docs/internal.xml @@ -46,7 +46,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.3 package true @@ -128,7 +127,7 @@ - rsModel + onos.rsModel m Json model for REST api: diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java new file mode 100644 index 00000000..140a8167 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java @@ -0,0 +1,146 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import java.util.Map; +import java.util.Objects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Maps; + +/** + * Default implementation of Move treatment. + */ +public class DefaultMoveExtensionTreatment extends AbstractExtension + implements MoveExtensionTreatment { + + private int srcOfs; + private int dstOfs; + private int nBits; + private int src; + private int dst; + private ExtensionTreatmentType type; + + private final KryoNamespace appKryo = new KryoNamespace.Builder() + .register(byte[].class).register(Integer.class).register(Map.class) + .build(); + + /** + * Creates a new move Treatment. + * + * @param srcOfs source offset + * @param dstOfs destination offset + * @param nBits nbits + * @param src source + * @param dst destination + * @param type extension treatment type + */ + public DefaultMoveExtensionTreatment(int srcOfs, int dstOfs, int nBits, + int src, int dst, ExtensionTreatmentType type) { + this.srcOfs = srcOfs; + this.dstOfs = dstOfs; + this.nBits = nBits; + this.src = src; + this.dst = dst; + this.type = type; + } + + @Override + public ExtensionTreatmentType type() { + return type; + } + + @Override + public byte[] serialize() { + Map values = Maps.newHashMap(); + values.put("srcOfs", srcOfs); + values.put("dstOfs", dstOfs); + values.put("nBits", nBits); + values.put("src", src); + values.put("dst", dst); + values.put("type", ExtensionTreatmentType.ExtensionTreatmentTypes.valueOf(type.toString()).ordinal()); + return appKryo.serialize(values); + } + + @Override + public void deserialize(byte[] data) { + Map values = appKryo.deserialize(data); + srcOfs = values.get("srcOfs"); + dstOfs = values.get("dstOfs"); + nBits = values.get("nBits"); + src = values.get("src"); + dst = values.get("dst"); + type = new ExtensionTreatmentType(values.get("type").intValue()); + } + + @Override + public int srcOffset() { + return srcOfs; + } + + @Override + public int dstOffset() { + return dstOfs; + } + + @Override + public int src() { + return src; + } + + @Override + public int dst() { + return dst; + } + + @Override + public int nBits() { + return nBits; + } + + @Override + public int hashCode() { + return Objects.hash(srcOfs, dstOfs, src, dst, nBits); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof DefaultMoveExtensionTreatment) { + DefaultMoveExtensionTreatment that = (DefaultMoveExtensionTreatment) obj; + return Objects.equals(srcOfs, that.srcOfs) + && Objects.equals(dstOfs, that.dstOfs) + && Objects.equals(src, that.src) + && Objects.equals(dst, that.dst) + && Objects.equals(nBits, that.nBits); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).add("srcOfs", srcOfs) + .add("dstOfs", dstOfs).add("nBits", nBits).add("src", src) + .add("dst", dst).toString(); + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java new file mode 100644 index 00000000..b67e1bed --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java @@ -0,0 +1,59 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import org.onosproject.net.flow.instructions.ExtensionTreatment; + +/** + * The abstraction of Move Treatment. + */ +public interface MoveExtensionTreatment extends ExtensionTreatment { + + /** + * Returns SRC_OFS field of move extension action. + * + * @return SRC_OFS + */ + int srcOffset(); + + /** + * Returns DST_OFS field of move extension action. + * + * @return DST_OFS + */ + int dstOffset(); + + /** + * Returns SRC field of move extension action. + * + * @return SRC + */ + int src(); + + /** + * Returns DST field of move extension action. + * + * @return DST + */ + int dst(); + + /** + * Returns N_BITS field of move extension action. + * + * @return N_BITS + */ + int nBits(); +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java new file mode 100644 index 00000000..9f302991 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java @@ -0,0 +1,102 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.driver.extensions; + +import org.onosproject.net.behaviour.ExtensionSelectorResolver; +import org.onosproject.net.driver.AbstractHandlerBehaviour; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; +import org.onosproject.openflow.controller.ExtensionSelectorInterpreter; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.oxm.OFOxm; + +/** + * Interpreter for Nicira OpenFlow selector extensions. + */ +public class NiciraExtensionSelectorInterpreter + extends AbstractHandlerBehaviour + implements ExtensionSelectorInterpreter, ExtensionSelectorResolver { + + @Override + public boolean supported(ExtensionSelectorType extensionSelectorType) { + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { + return true; + } + return false; + } + + @Override + public OFOxm mapSelector(OFFactory factory, ExtensionSelector extensionSelector) { + ExtensionSelectorType type = extensionSelector.type(); + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { + // TODO + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { + // TODO + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) { + // TODO + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) { + // TODO + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) { + // TODO + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { + // TODO + } + return null; + } + + @Override + public ExtensionSelector mapOxm(OFOxm oxm) { + return null; + } + + @Override + public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) { + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { + return new NiciraMatchNshSpi(); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { + return new NiciraMatchNshSi(); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type()) + || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type()) + || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type()) + || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { + return new NiciraMatchNshContextHeader(type); + } + return null; + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java index a7f70f98..5e374d9b 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java @@ -31,7 +31,7 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst; import org.projectfloodlight.openflow.types.IPv4Address; /** - * Interpreter for Nicira OpenFlow extensions. + * Interpreter for Nicira OpenFlow treatment extensions. */ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviour implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver { @@ -46,8 +46,42 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { return true; } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { + return true; + } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { + return true; + } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) { + return true; + } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) { + return true; + } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) { + return true; + } + if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { + return true; + } if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { + return true; + } + if (extensionTreatmentType.equals( + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) { + return true; + } + if (extensionTreatmentType.equals( + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) { + return true; + } + if (extensionTreatmentType.equals( + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) { + return true; + } + if (extensionTreatmentType.equals( + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { return true; } return false; @@ -62,11 +96,35 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou IPv4Address.of(tunnelDst.tunnelDst().toInt()))); } if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { - // TODO this will be implemented later + // TODO this will be implemented later } if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { // TODO this will be implemented later } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { + // TODO this will be implemented later + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { + // TODO this will be implemented later + } return null; } @@ -95,9 +153,33 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { return new NiciraResubmit(); } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { + return new NiciraResubmitTable(); + } if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { return new NiciraSetNshSpi(); } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { + return new NiciraSetNshSi(); + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type()) + || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { + return new NiciraSetNshContextHeader(type); + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) { + return NiciraMoveTreatmentFactory.createNiciraMovArpShaToTha(); + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) { + return NiciraMoveTreatmentFactory.createNiciraMovArpSpaToTpa(); + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) { + return NiciraMoveTreatmentFactory.createNiciraMovEthSrcToDst(); + } + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { + return NiciraMoveTreatmentFactory.createNiciraMovIpSrcToDst(); + } throw new UnsupportedOperationException( "Driver does not support extension type " + type.toString()); } diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java new file mode 100644 index 00000000..5f37247f --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java @@ -0,0 +1,95 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.NshContextHeader; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; +/** + * Implementation of Nsh context header criterion. + */ +public final class NiciraMatchNshContextHeader extends AbstractExtension implements ExtensionSelector { + private NshContextHeader nshContextHeader; + private ExtensionSelectorType type; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Constructor to create Nsh context header. + * + * @param type extension selector type + */ + public NiciraMatchNshContextHeader(ExtensionSelectorType type) { + this.nshContextHeader = null; + this.type = type; + } + + /** + * Gets the nsh context header to match. + * + * @return the nsh context header to match + */ + public NshContextHeader nshContextHeader() { + return nshContextHeader; + } + + @Override + public byte[] serialize() { + return appKryo.serialize(nshContextHeader.nshContextHeader()); + } + + @Override + public void deserialize(byte[] data) { + nshContextHeader = nshContextHeader.of(appKryo.deserialize(data)); + + } + + @Override + public ExtensionSelectorType type() { + return type; + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("nshContextHeader", nshContextHeader.toString()) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), nshContextHeader); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchNshContextHeader) { + NiciraMatchNshContextHeader that = (NiciraMatchNshContextHeader) obj; + return Objects.equals(nshContextHeader, that.nshContextHeader) && + Objects.equals(this.type(), that.type()); + } + return false; + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java new file mode 100644 index 00000000..c98a584a --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.NshServiceIndex; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; +/** + * Implementation of NSH Service Index(SI). + */ +public final class NiciraMatchNshSi extends AbstractExtension implements ExtensionSelector { + + private NshServiceIndex nshSi; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Default constructor. + * + */ + public NiciraMatchNshSi() { + this.nshSi = null; + } + + /** + * Gets the nsh service index to match. + * + * @return the si to match + */ + public NshServiceIndex nshSi() { + return nshSi; + } + + @Override + public byte[] serialize() { + return appKryo.serialize(nshSi.serviceIndex()); + } + + @Override + public void deserialize(byte[] data) { + nshSi = NshServiceIndex.of(appKryo.deserialize(data)); + } + + @Override + public ExtensionSelectorType type() { + return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type(); + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("nshSi", nshSi.toString()) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), nshSi); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchNshSi) { + NiciraMatchNshSi that = (NiciraMatchNshSi) obj; + return Objects.equals(nshSi, that.nshSi); + } + return false; + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java new file mode 100644 index 00000000..42bb78d4 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static com.google.common.base.MoreObjects.toStringHelper; + +import java.util.Objects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.NshServicePathId; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; + +/** + * Implementation of NSH Service Path Id selector. + */ +public final class NiciraMatchNshSpi extends AbstractExtension implements ExtensionSelector { + private NshServicePathId nshSpi; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Default constructor. + */ + public NiciraMatchNshSpi() { + this.nshSpi = null; + } + + /** + * Gets the network service path id to match. + * + * @return the nshSpi to match + */ + public NshServicePathId nshSpi() { + return nshSpi; + } + + @Override + public ExtensionSelectorType type() { + return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type(); + } + + @Override + public byte[] serialize() { + return appKryo.serialize(nshSpi); + } + + @Override + public void deserialize(byte[] data) { + nshSpi = NshServicePathId.of(appKryo.deserialize(data)); + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("nshSpi", nshSpi.toString()) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type(), nshSpi); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchNshSpi) { + NiciraMatchNshSpi that = (NiciraMatchNshSpi) obj; + return Objects.equals(nshSpi, that.nshSpi) && + Objects.equals(this.type(), that.type()); + } + return false; + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java new file mode 100644 index 00000000..ac42a3b2 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java @@ -0,0 +1,100 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +/** + * The factory of move treatment. + */ +public final class NiciraMoveTreatmentFactory { + + /** + * Public constructor is prohibited. + */ + private NiciraMoveTreatmentFactory() { + + } + + /** + * Creates a move treatment that move arp sha to tha. + * + * @return ExtensionTreatment + */ + public static ExtensionTreatment createNiciraMovArpShaToTha() { + int srcOfs = 0; + int dstOfs = 0; + int nBits = 48; + int srcSha = 0x00012206; + int dstTha = 0x00012406; + return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSha, + dstTha, + ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ARP_SHA_TO_THA.type()); + } + + /** + * Creates a move treatment that move arp spa to tpa. + * + * @return ExtensionTreatment + */ + public static ExtensionTreatment createNiciraMovArpSpaToTpa() { + int srcOfs = 0; + int dstOfs = 0; + int nBits = 32; + int srcSpa = 0x00002004; + int dstTpa = 0x00002204; + return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSpa, + dstTpa, + ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ARP_SPA_TO_TPA.type()); + } + + /** + * Creates a move treatment that move eth src to dst. + * + * @return ExtensionTreatment + */ + public static ExtensionTreatment createNiciraMovEthSrcToDst() { + int srcOfs = 0; + int dstOfs = 0; + int nBits = 48; + int srcEth = 0x00000406; + int dstEth = 0x00000206; + return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcEth, + dstEth, + ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_ETH_SRC_TO_DST.type()); + } + + /** + * Creates a move treatment that move ip src to dst. + * + * @return ExtensionTreatment + */ + public static ExtensionTreatment createNiciraMovIpSrcToDst() { + int srcOfs = 0; + int dstOfs = 0; + int nBits = 32; + int srcIp = 0x00000e04; + int dstIp = 0x00001006; + return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcIp, + dstIp, + ExtensionTreatmentType.ExtensionTreatmentTypes + .NICIRA_MOV_IP_SRC_TO_DST.type()); + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java index 481b6f9c..b85af4f2 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java @@ -19,7 +19,8 @@ package org.onosproject.driver.extensions; import com.google.common.base.MoreObjects; import org.onlab.util.KryoNamespace; import org.onosproject.net.PortNumber; -import org.onosproject.net.flow.instructions.AbstractExtensionTreatment; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; import org.onosproject.net.flow.instructions.ExtensionTreatmentType; import org.onosproject.store.serializers.PortNumberSerializer; @@ -30,7 +31,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Nicira resubmit extension instruction. */ -public class NiciraResubmit extends AbstractExtensionTreatment { +public class NiciraResubmit extends AbstractExtension implements ExtensionTreatment { private PortNumber inPort; diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java new file mode 100644 index 00000000..4743d217 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java @@ -0,0 +1,114 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.driver.extensions; + +import com.google.common.base.MoreObjects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.PortNumber; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; +import org.onosproject.store.serializers.PortNumberSerializer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Nicira resubmit-table extension instruction. + */ +public class NiciraResubmitTable extends AbstractExtension implements + ExtensionTreatment { + + //the list of the in port number(PortNumber) and the table(short) + private List inPortAndTable = new ArrayList(); + + private final KryoNamespace appKryo = new KryoNamespace.Builder() + .register(ArrayList.class) + .register(new PortNumberSerializer(), PortNumber.class) + .register(short.class) + .register(byte[].class) + .build(); + + /** + * Creates a new resubmit-table instruction. + */ + NiciraResubmitTable() { + inPortAndTable = null; + } + + /** + * Creates a new resubmit-table instruction with a particular inPort and table. + * + * @param inPortAndTable the list of in port number and table + */ + public NiciraResubmitTable(List inPortAndTable) { + checkNotNull(inPortAndTable); + this.inPortAndTable = inPortAndTable; + } + + /** + * Gets the inPortAndTable. + * + * @return inPortAndTable + */ + public List inPortAndTable() { + return inPortAndTable; + } + + @Override + public ExtensionTreatmentType type() { + return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type(); + } + + @Override + public void deserialize(byte[] data) { + inPortAndTable = appKryo.deserialize(data); + } + + @Override + public byte[] serialize() { + return appKryo.serialize(inPortAndTable); + } + + @Override + public int hashCode() { + return Objects.hash(inPortAndTable); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraResubmitTable) { + NiciraResubmitTable that = (NiciraResubmitTable) obj; + return Objects.equals(inPortAndTable, that.inPortAndTable); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("inPortAndTable", inPortAndTable).toString(); + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java new file mode 100644 index 00000000..c8267984 --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java @@ -0,0 +1,108 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.driver.extensions; + +import com.google.common.base.MoreObjects; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +import java.util.Objects; + +/** + * Nicira set NSH Context header extension instruction. + */ +public class NiciraSetNshContextHeader extends AbstractExtension implements + ExtensionTreatment { + + private int nshCh; + private ExtensionTreatmentType type; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new set nsh context header instruction. + * + * @param type extension treatment type + */ + NiciraSetNshContextHeader(ExtensionTreatmentType type) { + this.nshCh = 0; + this.type = type; + } + + /** + * Creates a new set nsh context header instruction. + * + * @param nshCh nsh context header + * @param type extension treatment type + */ + NiciraSetNshContextHeader(int nshCh, ExtensionTreatmentType type) { + this.nshCh = nshCh; + this.type = type; + } + + /** + * Gets the nsh context header. + * + * @return nsh context header + */ + public int nshCh() { + return nshCh; + } + + @Override + public ExtensionTreatmentType type() { + return type; + } + + @Override + public void deserialize(byte[] data) { + nshCh = appKryo.deserialize(data); + } + + @Override + public byte[] serialize() { + return appKryo.serialize(nshCh); + } + + @Override + public int hashCode() { + return Objects.hash(nshCh, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraSetNshContextHeader) { + NiciraSetNshContextHeader that = (NiciraSetNshContextHeader) obj; + return Objects.equals(nshCh, that.nshCh) && Objects.equals(type, that.type); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("nshCh", nshCh) + .add("type", type) + .toString(); + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java new file mode 100644 index 00000000..1480508e --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java @@ -0,0 +1,101 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.driver.extensions; + +import com.google.common.base.MoreObjects; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +import java.util.Objects; + +/** + * Nicira set NSH SI extension instruction. + */ +public class NiciraSetNshSi extends AbstractExtension implements + ExtensionTreatment { + + private byte nshSi; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new set nsh si instruction. + */ + NiciraSetNshSi() { + nshSi = 0; + } + + /** + * Creates a new set nsh si instruction with given si. + * + * @param nshSi nsh service index + */ + NiciraSetNshSi(byte nshSi) { + this.nshSi = nshSi; + } + + /** + * Gets the nsh service index. + * + * @return nsh service index + */ + public byte nshSi() { + return nshSi; + } + + @Override + public ExtensionTreatmentType type() { + return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type(); + } + + @Override + public void deserialize(byte[] data) { + nshSi = appKryo.deserialize(data); + } + + @Override + public byte[] serialize() { + return appKryo.serialize(nshSi); + } + + @Override + public int hashCode() { + return Objects.hash(nshSi); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraSetNshSi) { + NiciraSetNshSi that = (NiciraSetNshSi) obj; + return Objects.equals(nshSi, that.nshSi); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("nshSi", nshSi) + .toString(); + } +} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java index 25358702..1a47173e 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java @@ -16,26 +16,23 @@ package org.onosproject.driver.extensions; -import java.util.Objects; - +import com.google.common.base.MoreObjects; import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.instructions.AbstractExtensionTreatment; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.store.serializers.Ip4AddressSerializer; -import com.google.common.base.MoreObjects; +import java.util.Objects; /** * Nicira set NSH SPI extension instruction. */ -public class NiciraSetNshSpi extends AbstractExtensionTreatment { +public class NiciraSetNshSpi extends AbstractExtension implements + ExtensionTreatment { private int nshSpi; - private final KryoNamespace appKryo = new KryoNamespace.Builder() - .register(new Ip4AddressSerializer(), Integer.class) - .register(byte[].class) - .build(); + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); /** * Creates a new set nsh spi instruction. diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java index ec23a9e0..e28a1e24 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java @@ -19,7 +19,8 @@ package org.onosproject.driver.extensions; import com.google.common.base.MoreObjects; import org.onlab.packet.Ip4Address; import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.instructions.AbstractExtensionTreatment; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; import org.onosproject.net.flow.instructions.ExtensionTreatmentType; import org.onosproject.store.serializers.Ip4AddressSerializer; @@ -30,7 +31,8 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Nicira set tunnel destination extension instruction. */ -public class NiciraSetTunnelDst extends AbstractExtensionTreatment { +public class NiciraSetTunnelDst extends AbstractExtension implements + ExtensionTreatment { private Ip4Address tunnelDst; diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java index df4dfa53..270008f3 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java @@ -17,7 +17,14 @@ package org.onosproject.driver.handshaker; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import org.onlab.util.Spectrum; +import org.onosproject.net.ChannelSpacing; +import org.onosproject.net.DefaultOchSignalComparator; import org.onosproject.net.Device; +import org.onosproject.net.GridType; +import org.onosproject.net.OchSignal; +import org.onosproject.net.PortNumber; +import org.onosproject.net.behaviour.LambdaQuery; import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; import org.onosproject.openflow.controller.PortDescPropertyType; import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; @@ -41,9 +48,24 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.IntStream; -public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch { +/** + * Driver for Calient S160 Optical Circuit Switch. Untested on Calient S320 but probably works ok. + * + * Driver implements custom handshaker, and rewrites flow stats as expected by the device. Port stats are currently + * not supported. + * + * The device consists of OMS ports only, and each port exposes lambda resources covering the whole + * usable optical spectrum (U to O band, see {@link Spectrum} for spectrum definitions). + */ +public class CalientFiberSwitchHandshaker + extends AbstractOpenFlowSwitch + implements OpenFlowOpticalSwitch, LambdaQuery { private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); private List fiberPorts = new ArrayList<>(); @@ -178,4 +200,22 @@ public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch impleme super.sendMsg(newMsg); } + + @Override + public SortedSet queryLambdas(PortNumber port) { + // S160 data sheet + // Wavelength range: 1260 - 1630 nm + long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() / + ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); + long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() / + ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); + List lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier) + .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1)) + .collect(Collectors.toList()); + + SortedSet result = new TreeSet<>(new DefaultOchSignalComparator()); + result.addAll(lambdas); + + return result; + } } diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java index f91e2a7e..23378e95 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java @@ -16,7 +16,13 @@ package org.onosproject.driver.handshaker; import com.google.common.collect.ImmutableSet; +import org.onosproject.net.ChannelSpacing; +import org.onosproject.net.DefaultOchSignalComparator; import org.onosproject.net.Device; +import org.onosproject.net.GridType; +import org.onosproject.net.OchSignal; +import org.onosproject.net.PortNumber; +import org.onosproject.net.behaviour.LambdaQuery; import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; import org.onosproject.openflow.controller.PortDescPropertyType; import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; @@ -42,7 +48,6 @@ import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId; import org.projectfloodlight.openflow.types.CircuitSignalID; -import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.U8; import java.io.IOException; @@ -51,7 +56,11 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * LINC-OE Optical Emulator switch class. @@ -65,10 +74,13 @@ import java.util.concurrent.atomic.AtomicBoolean; * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}. * + * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz. + * */ public class OfOpticalSwitchImplLinc13 - extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch { + extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch, LambdaQuery { + private static final int LAMBDA_COUNT = 80; private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); private long barrierXidToWaitFor = -1; @@ -267,13 +279,13 @@ public class OfOpticalSwitchImplLinc13 /** * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port. * - * @param port given OF port + * @param port given port number * @return true if the port is a tap (OCh), false otherwise (OMS port) */ - private boolean hasPort(OFPort port) { + private boolean isOChPort(long port) { for (OFPortDescStatsReply reply : this.ports) { for (OFPortDesc p : reply.getEntries()) { - if (p.getPortNo().equals(port)) { + if (p.getPortNo().getPortNumber() == port) { return true; } } @@ -328,7 +340,7 @@ public class OfOpticalSwitchImplLinc13 short signalType; // FIXME: use constants once loxi has full optical extensions - if (hasPort(p.getPortNo())) { + if (isOChPort(p.getPortNo().getPortNumber())) { signalType = 5; // OCH port } else { signalType = 2; // OMS port @@ -351,4 +363,23 @@ public class OfOpticalSwitchImplLinc13 public Set getPortTypes() { return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT); } + + @Override + public SortedSet queryLambdas(PortNumber port) { + // OCh ports don't have lambdas + if (isOChPort(port.toLong())) { + return Collections.emptySortedSet(); + } + + // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency. + // We report these with a spacing of 12.5 GHz. + List lambdas = IntStream.range(0, LAMBDA_COUNT) + .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1)) + .collect(Collectors.toList()); + + SortedSet result = new TreeSet<>(new DefaultOchSignalComparator()); + result.addAll(lambdas); + + return result; + } } diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java index 937c9ac8..02522cf1 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java @@ -39,7 +39,9 @@ import org.onosproject.net.flow.FlowRuleOperations; import org.onosproject.net.flow.FlowRuleOperationsContext; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.criteria.Criteria; import org.onosproject.net.flow.criteria.Criterion; +import org.onosproject.net.flow.criteria.EthCriterion; import org.onosproject.net.flow.criteria.EthTypeCriterion; import org.onosproject.net.flow.criteria.IPCriterion; import org.onosproject.net.flow.criteria.MplsBosCriterion; @@ -62,6 +64,14 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { private final Logger log = getLogger(getClass()); + /* + * Cpqd emulation does not require the non-OF standard rules for + * matching untagged packets. + * + * (non-Javadoc) + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processVlanIdFilter + */ + @Override protected List processVlanIdFilter(PortCriterion portCriterion, VlanIdCriterion vidCriterion, @@ -122,16 +132,101 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { return rules; } + /* + * Cpqd emulation does not handle vlan tags and mpls labels correctly. + * Workaround requires popping off the VLAN tags in the TMAC table. + * + * (non-Javadoc) + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthDstFilter + */ @Override - protected Collection processSpecific(ForwardingObjective fwd) { + protected List processEthDstFilter(PortCriterion portCriterion, + EthCriterion ethCriterion, + VlanIdCriterion vidCriterion, + VlanId assignedVlan, + ApplicationId applicationId) { + //handling untagged packets via assigned VLAN + if (vidCriterion.vlanId() == VlanId.NONE) { + vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); + } + // ofdpa cannot match on ALL portnumber, so we need to use separate + // rules for each port. + List portnums = new ArrayList(); + if (portCriterion.port() == PortNumber.ALL) { + for (Port port : deviceService.getPorts(deviceId)) { + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { + portnums.add(port.number()); + } + } + } else { + portnums.add(portCriterion.port()); + } + + List rules = new ArrayList(); + for (PortNumber pnum : portnums) { + // for unicast IP packets + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); + selector.matchInPort(pnum); + selector.matchVlanId(vidCriterion.vlanId()); + selector.matchEthType(Ethernet.TYPE_IPV4); + selector.matchEthDst(ethCriterion.mac()); + /* + * Note: CpqD switches do not handle MPLS-related operation properly + * for a packet with VLAN tag. We pop VLAN here as a workaround. + * Side effect: HostService learns redundant hosts with same MAC but + * different VLAN. No known side effect on the network reachability. + */ + treatment.popVlan(); + treatment.transition(UNICAST_ROUTING_TABLE); + FlowRule rule = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(selector.build()) + .withTreatment(treatment.build()) + .withPriority(DEFAULT_PRIORITY) + .fromApp(applicationId) + .makePermanent() + .forTable(TMAC_TABLE).build(); + rules.add(rule); + //for MPLS packets + selector = DefaultTrafficSelector.builder(); + treatment = DefaultTrafficTreatment.builder(); + selector.matchInPort(pnum); + selector.matchVlanId(vidCriterion.vlanId()); + selector.matchEthType(Ethernet.MPLS_UNICAST); + selector.matchEthDst(ethCriterion.mac()); + // workaround here again + treatment.popVlan(); + treatment.transition(MPLS_TABLE_0); + rule = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(selector.build()) + .withTreatment(treatment.build()) + .withPriority(DEFAULT_PRIORITY) + .fromApp(applicationId) + .makePermanent() + .forTable(TMAC_TABLE).build(); + rules.add(rule); + } + return rules; + } + + /* + * Cpqd emulation allows MPLS ecmp. + * + * (non-Javadoc) + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific + */ + @Override + protected Collection processEthTypeSpecific(ForwardingObjective fwd) { TrafficSelector selector = fwd.selector(); EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); if ((ethType == null) || (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { - log.warn("processSpecific: Unsupported " - + "forwarding objective criteraia"); + log.warn("processSpecific: Unsupported forwarding objective criteria" + + "ethType:{} in dev:{}", ethType, deviceId); fail(fwd, ObjectiveError.UNSUPPORTED); return Collections.emptySet(); } @@ -143,8 +238,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { .matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); forTableId = UNICAST_ROUTING_TABLE; - log.debug("processing IPv4 specific forwarding objective {} hash{} in dev:{}", - fwd.id(), fwd.hashCode(), deviceId); + log.debug("processing IPv4 specific forwarding objective {} -> next:{}" + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId); } else { filteredSelector .matchEthType(Ethernet.MPLS_UNICAST) @@ -156,8 +251,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { filteredSelector.matchMplsBos(bos.mplsBos()); } forTableId = MPLS_TABLE_1; - log.debug("processing MPLS specific forwarding objective {} hash:{} in dev {}", - fwd.id(), fwd.hashCode(), deviceId); + log.debug("processing MPLS specific forwarding objective {} -> next:{}" + + " in dev {}", fwd.id(), fwd.nextId(), deviceId); } TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); @@ -197,7 +292,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { return Collections.singletonList(ruleBuilder.build()); } - @Override protected void initializePipeline() { processPortTable(); @@ -210,7 +304,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { processAclTable(); } - @Override protected void processPortTable() { FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); @@ -239,7 +332,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { })); } - @Override protected void processTmacTable() { //table miss entry FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); @@ -270,7 +362,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { })); } - @Override protected void processIpTable() { //table miss entry FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); @@ -278,6 +369,7 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); selector = DefaultTrafficSelector.builder(); treatment = DefaultTrafficTreatment.builder(); + treatment.deferred().setOutput(PortNumber.CONTROLLER); treatment.transition(ACL_TABLE); FlowRule rule = DefaultFlowRule.builder() .forDevice(deviceId) @@ -301,7 +393,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { })); } - @Override protected void processMplsTable() { //table miss entry FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); @@ -374,7 +465,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { })); } - @Override protected void processAclTable() { //table miss entry - catch all to executed action-set FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java index 863caebb..5f84b43a 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java @@ -18,7 +18,6 @@ package org.onosproject.driver.pipeline; import static org.onlab.util.Tools.groupedThreads; import static org.slf4j.LoggerFactory.getLogger; -import java.nio.ByteBuffer; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -28,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -35,14 +35,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Data; import org.onlab.packet.Ethernet; -import org.onlab.packet.IPv4; -import org.onlab.packet.IpPrefix; -import org.onlab.packet.MPLS; import org.onlab.packet.MacAddress; import org.onlab.packet.MplsLabel; -import org.onlab.packet.UDP; import org.onlab.packet.VlanId; import org.onlab.util.KryoNamespace; import org.onosproject.core.ApplicationId; @@ -99,10 +94,6 @@ import org.onosproject.net.group.GroupEvent; import org.onosproject.net.group.GroupKey; import org.onosproject.net.group.GroupListener; import org.onosproject.net.group.GroupService; -import org.onosproject.net.packet.DefaultOutboundPacket; -import org.onosproject.net.packet.OutboundPacket; -import org.onosproject.net.packet.PacketContext; -import org.onosproject.net.packet.PacketProcessor; import org.onosproject.net.packet.PacketService; import org.onosproject.store.serializers.KryoNamespaces; import org.slf4j.Logger; @@ -160,7 +151,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline protected ApplicationId driverId; protected PacketService packetService; protected DeviceService deviceService; - private InternalPacketProcessor processor = new InternalPacketProcessor(); protected KryoNamespace appKryo = new KryoNamespace.Builder() .register(KryoNamespaces.API) .register(GroupKey.class) @@ -170,7 +160,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline .register(ArrayDeque.class) .build(); - private Cache pendingNextObjectives; + private Cache> pendingNextObjectives; private ConcurrentHashMap> pendingGroups; private ScheduledExecutorService groupChecker = @@ -196,10 +186,12 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline pendingNextObjectives = CacheBuilder.newBuilder() .expireAfterWrite(20, TimeUnit.SECONDS) .removalListener(( - RemovalNotification notification) -> { + RemovalNotification> notification) -> { if (notification.getCause() == RemovalCause.EXPIRED) { - fail(notification.getValue().nextObjective(), - ObjectiveError.GROUPINSTALLATIONFAILED); + notification.getValue().forEach(ofdpaNextGrp -> + fail(ofdpaNextGrp.nextObj, + ObjectiveError.GROUPINSTALLATIONFAILED)); + } }).build(); @@ -212,7 +204,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline flowObjectiveStore = context.store(); packetService = serviceDirectory.get(PacketService.class); deviceService = serviceDirectory.get(DeviceService.class); - packetService.addProcessor(processor, PacketProcessor.director(2)); groupService.addListener(new InnerGroupListener()); driverId = coreService.registerApplication( @@ -271,7 +262,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline log.warn("Unknown forwarding type {}", fwd.op()); } - flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { @Override public void onSuccess(FlowRuleOperations ops) { @@ -283,7 +273,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); } })); - } @Override @@ -697,17 +686,57 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline * returned if there is an issue in processing the objective. */ protected Collection processSpecific(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if ((ethType == null) || - (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { - log.warn("processSpecific: Unsupported " - + "forwarding objective criteraia"); + log.trace("Processing specific fwd objective:{} in dev:{} with next:{}", + fwd.id(), deviceId, fwd.nextId()); + boolean isEthTypeObj = isSupportedEthTypeObjective(fwd); + boolean isEthDstObj = isSupportedEthDstObjective(fwd); + + if (isEthTypeObj) { + return processEthTypeSpecific(fwd); + } else if (isEthDstObj) { + return processEthDstSpecific(fwd); + } else { + log.warn("processSpecific: Unsupported forwarding objective " + + "criteria fwd:{} in dev:{}", fwd.nextId(), deviceId); fail(fwd, ObjectiveError.UNSUPPORTED); return Collections.emptySet(); } + } + + private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) { + TrafficSelector selector = fwd.selector(); + EthTypeCriterion ethType = (EthTypeCriterion) selector + .getCriterion(Criterion.Type.ETH_TYPE); + if ((ethType == null) || + ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && + (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) { + return false; + } + return true; + } + + private boolean isSupportedEthDstObjective(ForwardingObjective fwd) { + TrafficSelector selector = fwd.selector(); + EthCriterion ethDst = (EthCriterion) selector + .getCriterion(Criterion.Type.ETH_DST); + VlanIdCriterion vlanId = (VlanIdCriterion) selector + .getCriterion(Criterion.Type.VLAN_VID); + if (ethDst == null && vlanId == null) { + return false; + } + return true; + } + + /** + * Handles forwarding rules to the IP and MPLS tables. + * + * @param fwd the forwarding objective + * @return A collection of flow rules, or an empty set + */ + protected Collection processEthTypeSpecific(ForwardingObjective fwd) { + TrafficSelector selector = fwd.selector(); + EthTypeCriterion ethType = + (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); int forTableId = -1; TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder(); @@ -716,8 +745,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline .matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); forTableId = UNICAST_ROUTING_TABLE; - log.debug("processing IPv4 specific forwarding objective {} in dev:{}", - fwd.id(), deviceId); + log.debug("processing IPv4 specific forwarding objective {} -> next:{}" + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId); } else { filteredSelector .matchEthType(Ethernet.MPLS_UNICAST) @@ -729,8 +758,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline filteredSelector.matchMplsBos(bos.mplsBos()); } forTableId = MPLS_TABLE_1; - log.debug("processing MPLS specific forwarding objective {} in dev {}", - fwd.id(), deviceId); + log.debug("processing MPLS specific forwarding objective {} -> next:{}" + + " in dev {}", fwd.id(), fwd.nextId(), deviceId); } TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); @@ -754,6 +783,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline // MPLS interface, or a MPLS SWAP (with-same) but that would // have to be handled in the next-objective. Also the pop-mpls // logic used here won't work in non-BoS case. + fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); return Collections.emptySet(); } @@ -762,7 +792,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline // we only need the top level group's key to point the flow to it Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); if (group == null) { - log.warn("The group left!"); + log.warn("Group with key:{} for next-id:{} not found in dev:{}", + gkeys.get(0).peekFirst(), fwd.nextId(), deviceId); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } @@ -786,6 +817,88 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline return Collections.singletonList(ruleBuilder.build()); } + /** + * Handles forwarding rules to the L2 bridging table. Flow actions are not + * allowed in the bridging table - instead we use L2 Interface group or + * L2 flood group + * + * @param fwd the forwarding objective + * @return A collection of flow rules, or an empty set + */ + protected Collection processEthDstSpecific(ForwardingObjective fwd) { + List rules = new ArrayList<>(); + + // Build filtered selector + TrafficSelector selector = fwd.selector(); + EthCriterion ethCriterion = (EthCriterion) selector + .getCriterion(Criterion.Type.ETH_DST); + VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector + .getCriterion(Criterion.Type.VLAN_VID); + + if (vlanIdCriterion == null) { + log.warn("Forwarding objective for bridging requires vlan. Not " + + "installing fwd:{} in dev:{}", fwd.id(), deviceId); + fail(fwd, ObjectiveError.BADPARAMS); + return Collections.emptySet(); + } + + TrafficSelector.Builder filteredSelectorBuilder = + DefaultTrafficSelector.builder(); + // Do not match MacAddress for subnet broadcast entry + if (!ethCriterion.mac().equals(MacAddress.NONE)) { + filteredSelectorBuilder.matchEthDst(ethCriterion.mac()); + log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}", + fwd.id(), fwd.nextId(), deviceId); + } else { + log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} " + + "in dev:{} for vlan:{}", + fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId()); + } + filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId()); + TrafficSelector filteredSelector = filteredSelectorBuilder.build(); + + if (fwd.treatment() != null) { + log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table" + + "for dev:{}. Expecting only nextId", fwd.id(), deviceId); + } + + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); + if (fwd.nextId() != null) { + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); + if (next != null) { + List> gkeys = appKryo.deserialize(next.data()); + // we only need the top level group's key to point the flow to it + Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); + if (group != null) { + treatmentBuilder.deferred().group(group.id()); + } else { + log.warn("Group with key:{} for next-id:{} not found in dev:{}", + gkeys.get(0).peekFirst(), fwd.nextId(), deviceId); + fail(fwd, ObjectiveError.GROUPMISSING); + return Collections.emptySet(); + } + } + } + treatmentBuilder.immediate().transition(ACL_TABLE); + TrafficTreatment filteredTreatment = treatmentBuilder.build(); + + // Build bridging table entries + FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder(); + flowRuleBuilder.fromApp(fwd.appId()) + .withPriority(fwd.priority()) + .forDevice(deviceId) + .withSelector(filteredSelector) + .withTreatment(filteredTreatment) + .forTable(BRIDGING_TABLE); + if (fwd.permanent()) { + flowRuleBuilder.makePermanent(); + } else { + flowRuleBuilder.makeTemporary(fwd.timeout()); + } + rules.add(flowRuleBuilder.build()); + return rules; + } + private void pass(Objective obj) { if (obj.context().isPresent()) { obj.context().get().onSuccess(obj); @@ -842,9 +955,26 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline * @param nextObj the nextObjective of type SIMPLE */ private void processSimpleNextObjective(NextObjective nextObj) { - // break up simple next objective to GroupChain objects TrafficTreatment treatment = nextObj.next().iterator().next(); + // determine if plain L2 or L3->L2 + boolean plainL2 = true; + for (Instruction ins : treatment.allInstructions()) { + if (ins.type() == Instruction.Type.L2MODIFICATION) { + L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; + if (l2ins.subtype() == L2SubType.ETH_DST || + l2ins.subtype() == L2SubType.ETH_SRC) { + plainL2 = false; + break; + } + } + } + + if (plainL2) { + createL2InterfaceGroup(nextObj); + return; + } + // break up simple next objective to GroupChain objects GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), nextObj.appId(), false, nextObj.meta()); @@ -860,8 +990,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline Collections.singletonList(gkeyChain), nextObj); - // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it - pendingNextObjectives.put(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp); + // store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it + updatePendingNextObjective(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp); // now we are ready to send the l2 groupDescription (inner), as all the stores // that will get async replies have been updated. By waiting to update @@ -869,6 +999,98 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline groupService.addGroup(groupInfo.innerGrpDesc); } + private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) { + List nextList = new CopyOnWriteArrayList(); + nextList.add(value); + List ret = pendingNextObjectives.asMap() + .putIfAbsent(key, nextList); + if (ret != null) { + ret.add(value); + } + } + + /** + * Creates a simple L2 Interface Group. + * + * @param nextObj the next Objective + */ + private void createL2InterfaceGroup(NextObjective nextObj) { + // only allowed actions are vlan pop and outport + TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder(); + PortNumber portNum = null; + for (Instruction ins : nextObj.next().iterator().next().allInstructions()) { + if (ins.type() == Instruction.Type.L2MODIFICATION) { + L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; + switch (l2ins.subtype()) { + case VLAN_POP: + ttb.add(l2ins); + break; + default: + break; + } + } else if (ins.type() == Instruction.Type.OUTPUT) { + portNum = ((OutputInstruction) ins).port(); + ttb.add(ins); + } else { + log.warn("Driver does not handle this type of TrafficTreatment" + + " instruction in simple nextObjectives: {}", ins.type()); + } + } + //use the vlanid associated with the port + VlanId vlanid = port2Vlan.get(portNum); + + if (vlanid == null && nextObj.meta() != null) { + // use metadata vlan info if available + Criterion vidCriterion = nextObj.meta().getCriterion(Type.VLAN_VID); + if (vidCriterion != null) { + vlanid = ((VlanIdCriterion) vidCriterion).vlanId(); + } + } + + if (vlanid == null) { + log.error("Driver cannot process an L2/L3 group chain without " + + "egress vlan information for dev: {} port:{}", + deviceId, portNum); + return; + } + + // assemble information for ofdpa l2interface group + Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum.toLong(); + // a globally unique groupkey that is different for ports in the same devices + // but different for the same portnumber on different devices. Also different + // for the various group-types created out of the same next objective. + int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong()); + final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); + + // create group description for the l2interfacegroup + GroupBucket l2interfaceGroupBucket = + DefaultGroupBucket.createIndirectGroupBucket(ttb.build()); + GroupDescription l2groupDescription = + new DefaultGroupDescription( + deviceId, + GroupDescription.Type.INDIRECT, + new GroupBuckets(Collections.singletonList( + l2interfaceGroupBucket)), + l2groupkey, + l2groupId, + nextObj.appId()); + log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}", + deviceId, Integer.toHexString(l2groupId), + l2groupkey, nextObj.id()); + + // create object for local and distributed storage + Deque singleKey = new ArrayDeque<>(); + singleKey.addFirst(l2groupkey); + OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup( + Collections.singletonList(singleKey), + nextObj); + + // store l2groupkey for the nextObjective that depends on it + updatePendingNextObjective(l2groupkey, ofdpaGrp); + // send the group description to the group service + groupService.addGroup(l2groupDescription); + } + /** * Creates one of two possible group-chains from the treatment * passed in. Depending on the MPLS boolean, this method either creates @@ -895,6 +1117,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder(); VlanId vlanid = null; long portNum = 0; + boolean setVlan = false, popVlan = false; for (Instruction ins : treatment.allInstructions()) { if (ins.type() == Instruction.Type.L2MODIFICATION) { L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; @@ -908,9 +1131,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline case VLAN_ID: vlanid = ((ModVlanIdInstruction) l2ins).vlanId(); outerTtb.setVlanId(vlanid); + setVlan = true; break; case VLAN_POP: innerTtb.popVlan(); + popVlan = true; break; case DEC_MPLS_TTL: case MPLS_LABEL: @@ -935,12 +1160,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline vlanid = port2Vlan.get(PortNumber.portNumber(portNum)); } - if (vlanid == null) { - // use metadata - for (Criterion metaCriterion : meta.criteria()) { - if (metaCriterion.type() == Type.VLAN_VID) { - vlanid = ((VlanIdCriterion) metaCriterion).vlanId(); - } + if (vlanid == null && meta != null) { + // use metadata if available + Criterion vidCriterion = meta.getCriterion(Type.VLAN_VID); + if (vidCriterion != null) { + vlanid = ((VlanIdCriterion) vidCriterion).vlanId(); } } @@ -951,6 +1175,14 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline return null; } + if (!setVlan && !popVlan) { + // untagged outgoing port + TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder(); + temp.popVlan(); + innerTtb.build().allInstructions().forEach(i -> temp.add(i)); + innerTtb = temp; + } + // assemble information for ofdpa l2interface group Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum; // a globally unique groupkey that is different for ports in the same devices @@ -1077,6 +1309,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline } // also ensure that all ports are in the same vlan + // XXX maybe HA issue here? VlanId thisvlanid = port2Vlan.get(portNum); if (vlanid == null) { vlanid = thisvlanid; @@ -1151,7 +1384,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline // store l2floodgroupkey with the ofdpaGroupChain for the nextObjective // that depends on it - pendingNextObjectives.put(l2floodgroupkey, ofdpaGrp); + updatePendingNextObjective(l2floodgroupkey, ofdpaGrp); for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) { // store all l2groupkeys with the groupChainElem for the l2floodgroup @@ -1336,7 +1569,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline // store l3ecmpGroupKey with the ofdpaGroupChain for the nextObjective // that depends on it - pendingNextObjectives.put(l3ecmpGroupKey, ofdpaGrp); + updatePendingNextObjective(l3ecmpGroupKey, ofdpaGrp); log.debug("Trying L3ECMP: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(l3ecmpGroupId), @@ -1422,16 +1655,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline processGroupChain(gce); } } else { - OfdpaNextGroup obj = pendingNextObjectives.getIfPresent(key); - if (obj != null) { - log.info("Group service processed group key {} in device:{}. " - + "Done implementing next objective: {} <<-->> gid:{}", - key, deviceId, obj.nextObjective().id(), - Integer.toHexString(groupService.getGroup(deviceId, key) - .givenGroupId())); - pass(obj.nextObjective()); + List objList = pendingNextObjectives.getIfPresent(key); + if (objList != null) { pendingNextObjectives.invalidate(key); - flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); + objList.forEach(obj -> { + log.info("Group service processed group key {} in device:{}. " + + "Done implementing next objective: {} <<-->> gid:{}", + key, deviceId, obj.nextObjective().id(), + Integer.toHexString(groupService.getGroup(deviceId, key) + .givenGroupId())); + pass(obj.nextObjective()); + flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); + }); } } }); @@ -1455,16 +1690,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline processGroupChain(gce); } } else { - OfdpaNextGroup obj = pendingNextObjectives.getIfPresent(key); - if (obj != null) { - log.info("group ADDED with key {} in dev {}.. Done implementing next " - + "objective: {} <<-->> gid:{}", - key, deviceId, obj.nextObjective().id(), - Integer.toHexString(groupService.getGroup(deviceId, key) - .givenGroupId())); - pass(obj.nextObjective()); + List objList = pendingNextObjectives.getIfPresent(key); + if (objList != null) { pendingNextObjectives.invalidate(key); - flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); + objList.forEach(obj -> { + log.info("group ADDED with key {} in dev {}.. Done implementing next " + + "objective: {} <<-->> gid:{}", + key, deviceId, obj.nextObjective().id(), + Integer.toHexString(groupService.getGroup(deviceId, key) + .givenGroupId())); + pass(obj.nextObjective()); + flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); + }); } } } @@ -1550,418 +1787,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline " waiting-on-groups: " + waitOnGroups.get() + " device: " + deviceId); } - - } - - ////////////////////////////////////// - // Test code to be used for future - // static-flow-pusher app - ////////////////////////////////////// - - public void processStaticFlows() { - //processPortTable(); - processGroupTable(); - processVlanTable(); - processTmacTable(); - processIpTable(); - //processMcastTable(); - //processBridgingTable(); - processAclTable(); - sendPackets(); - processMplsTable(); - } - - protected void processGroupTable() { - TrafficTreatment.Builder act = DefaultTrafficTreatment.builder(); - - act.popVlan(); // to send out untagged packets - act.setOutput(PortNumber.portNumber(24)); - GroupBucket bucket = - DefaultGroupBucket.createIndirectGroupBucket(act.build()); - final GroupKey groupkey = new DefaultGroupKey(appKryo.serialize(500)); - Integer groupId = 0x00c80018; //l2 interface, vlan 200, port 24 - GroupDescription groupDescription = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList(bucket)), - groupkey, - groupId, - driverId); - groupService.addGroup(groupDescription); - - TrafficTreatment.Builder act2 = DefaultTrafficTreatment.builder(); - act2.setOutput(PortNumber.portNumber(40)); - GroupBucket bucket2 = DefaultGroupBucket.createIndirectGroupBucket(act2.build()); - final GroupKey groupkey2 = new DefaultGroupKey(appKryo.serialize(502)); - Integer groupId2 = 0x00c50028; //l2 interface, vlan 197, port 40 - GroupDescription groupDescription2 = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList(bucket2)), - groupkey2, - groupId2, - driverId); - groupService.addGroup(groupDescription2); - - while (groupService.getGroup(deviceId, groupkey2) == null) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - //Now for L3 Unicast group - TrafficTreatment.Builder act3 = DefaultTrafficTreatment.builder(); - act3.setEthDst(MacAddress.valueOf(0x2020)); - act3.setEthSrc(MacAddress.valueOf(0x1010)); - act3.setVlanId(VlanId.vlanId((short) 200)); - act3.group(new DefaultGroupId(0x00c80018)); // point to L2 interface - // MPLS interface group - does not work for popping single label - //Integer secGroupId = MPLSINTERFACEMASK | 38; // 0x90000026 - Integer groupId3 = L3UNICASTMASK | 1; // 0x20000001 - GroupBucket bucket3 = - DefaultGroupBucket.createIndirectGroupBucket(act3.build()); - final GroupKey groupkey3 = new DefaultGroupKey(appKryo.serialize(503)); - GroupDescription groupDescription3 = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList(bucket3)), - groupkey3, - groupId3, - driverId); - groupService.addGroup(groupDescription3); - - //Another L3 Unicast group - TrafficTreatment.Builder act4 = DefaultTrafficTreatment.builder(); - act4.setEthDst(MacAddress.valueOf(0x3030)); - act4.setEthSrc(MacAddress.valueOf(0x1010)); - act4.setVlanId(VlanId.vlanId((short) 197)); - act4.group(new DefaultGroupId(0x00c50028)); // point to L2 interface - Integer groupId4 = L3UNICASTMASK | 2; // 0x20000002 - GroupBucket bucket4 = - DefaultGroupBucket.createIndirectGroupBucket(act4.build()); - final GroupKey groupkey4 = new DefaultGroupKey(appKryo.serialize(504)); - GroupDescription groupDescription4 = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList(bucket4)), - groupkey4, - groupId4, - driverId); - groupService.addGroup(groupDescription4); - - while (groupService.getGroup(deviceId, groupkey4) == null) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - // L3 ecmp group - TrafficTreatment.Builder act5 = DefaultTrafficTreatment.builder(); - act5.group(new DefaultGroupId(0x20000001)); - TrafficTreatment.Builder act6 = DefaultTrafficTreatment.builder(); - act6.group(new DefaultGroupId(0x20000002)); - GroupBucket buckete1 = - DefaultGroupBucket.createSelectGroupBucket(act5.build()); - GroupBucket buckete2 = - DefaultGroupBucket.createSelectGroupBucket(act6.build()); - List bktlist = new ArrayList(); - bktlist.add(buckete1); - bktlist.add(buckete2); - final GroupKey groupkey5 = new DefaultGroupKey(appKryo.serialize(505)); - Integer groupId5 = L3ECMPMASK | 5; // 0x70000005 - GroupDescription groupDescription5 = new DefaultGroupDescription(deviceId, - GroupDescription.Type.SELECT, - new GroupBuckets(bktlist), - groupkey5, - groupId5, - driverId); - groupService.addGroup(groupDescription5); - - - } - - @SuppressWarnings("deprecation") - protected void processMplsTable() { - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - selector.matchEthType(Ethernet.MPLS_UNICAST); - selector.matchMplsLabel(MplsLabel.mplsLabel(0xff)); //255 - selector.matchMplsBos(true); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - treatment.decMplsTtl(); // nw_ttl does not work - treatment.copyTtlIn(); - treatment.popMpls(Ethernet.TYPE_IPV4); - treatment.deferred().group(new DefaultGroupId(0x20000001)); // point to L3 Unicast - //treatment.deferred().group(new DefaultGroupId(0x70000005)); // point to L3 ECMP - treatment.transition(ACL_TABLE); - FlowRule test = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector.build()).withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY).fromApp(driverId).makePermanent() - .forTable(24).build(); - ops = ops.add(test); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized mpls table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize mpls table"); - } - })); - - } - - protected void processPortTable() { - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - selector.matchInPort(PortNumber.portNumber(0)); // should be maskable? - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - treatment.transition(VLAN_TABLE); - FlowRule tmisse = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(PORT_TABLE).build(); - ops = ops.add(tmisse); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized port table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize port table"); - } - })); - - } - - private void processVlanTable() { - // Table miss entry is not required as ofdpa default is to drop - // In OF terms, the absence of a t.m.e. also implies drop - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(PortNumber.portNumber(12)); - selector.matchVlanId(VlanId.vlanId((short) 100)); - treatment.transition(TMAC_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(VLAN_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized vlan table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize vlan table"); - } - })); - } - - protected void processTmacTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(PortNumber.portNumber(12)); - selector.matchVlanId(VlanId.vlanId((short) 100)); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02")); - treatment.transition(UNICAST_ROUTING_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - ops = ops.add(rule); - - selector.matchEthType(Ethernet.MPLS_UNICAST); - treatment.transition(MPLS_TABLE_0); - FlowRule rulempls = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - ops = ops.add(rulempls); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized tmac table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize tmac table"); - } - })); - } - - protected void processIpTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(IpPrefix.valueOf("2.0.0.0/16")); - treatment.deferred().group(new DefaultGroupId(0x20000001)); - treatment.transition(ACL_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(30000) - .fromApp(driverId) - .makePermanent() - .forTable(UNICAST_ROUTING_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized IP table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize unicast IP table"); - } - })); - } - - protected void processAclTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02")); - treatment.deferred().group(new DefaultGroupId(0x20000001)); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(60000) - .fromApp(driverId) - .makePermanent() - .forTable(ACL_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized Acl table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize Acl table"); - } - })); - } - - private void sendPackets() { - Ethernet eth = new Ethernet(); - eth.setDestinationMACAddress("00:00:00:00:00:02"); - eth.setSourceMACAddress("00:00:00:11:22:33"); - eth.setVlanID((short) 100); - eth.setEtherType(Ethernet.MPLS_UNICAST); - MPLS mplsPkt = new MPLS(); - mplsPkt.setLabel(255); - mplsPkt.setTtl((byte) 5); - - IPv4 ipv4 = new IPv4(); - - ipv4.setDestinationAddress("4.0.5.6"); - ipv4.setSourceAddress("1.0.2.3"); - ipv4.setTtl((byte) 64); - ipv4.setChecksum((short) 0); - - UDP udp = new UDP(); - udp.setDestinationPort(666); - udp.setSourcePort(333); - udp.setPayload(new Data(new byte[]{(byte) 1, (byte) 2})); - udp.setChecksum((short) 0); - - ipv4.setPayload(udp); - mplsPkt.setPayload(ipv4); - eth.setPayload(mplsPkt); - - TrafficTreatment treatment = DefaultTrafficTreatment.builder() - .setOutput(PortNumber.portNumber(24)) - .build(); - OutboundPacket packet = new DefaultOutboundPacket(deviceId, - treatment, - ByteBuffer.wrap(eth.serialize())); - - - Ethernet eth2 = new Ethernet(); - eth2.setDestinationMACAddress("00:00:00:00:00:02"); - eth2.setSourceMACAddress("00:00:00:11:22:33"); - eth2.setVlanID((short) 100); - eth2.setEtherType(Ethernet.TYPE_IPV4); - - IPv4 ipv42 = new IPv4(); - ipv42.setDestinationAddress("2.0.0.2"); - ipv42.setSourceAddress("1.0.9.9"); - ipv42.setTtl((byte) 64); - ipv42.setChecksum((short) 0); - - UDP udp2 = new UDP(); - udp2.setDestinationPort(999); - udp2.setSourcePort(333); - udp2.setPayload(new Data(new byte[]{(byte) 1, (byte) 2})); - udp2.setChecksum((short) 0); - - ipv42.setPayload(udp2); - eth2.setPayload(ipv42); - - TrafficTreatment treatment2 = DefaultTrafficTreatment.builder() - .setOutput(PortNumber.portNumber(26)) - .build(); - OutboundPacket packet2 = new DefaultOutboundPacket(deviceId, - treatment2, - ByteBuffer.wrap(eth2.serialize())); - - - log.info("Emitting packets now"); - packetService.emit(packet); - packetService.emit(packet); - packetService.emit(packet2); - packetService.emit(packet); - packetService.emit(packet); - log.info("Done emitting packets"); - } - - private class InternalPacketProcessor implements PacketProcessor { - - @Override - public void process(PacketContext context) { - - - } } } diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java new file mode 100644 index 00000000..7a92b4fa --- /dev/null +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java @@ -0,0 +1,286 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.pipeline; + +import org.onlab.osgi.ServiceDirectory; +import org.onlab.packet.Ethernet; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.DeviceId; +import org.onosproject.net.behaviour.Pipeliner; +import org.onosproject.net.behaviour.PipelinerContext; +import org.onosproject.net.flow.DefaultFlowRule; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.flow.FlowRuleOperations; +import org.onosproject.net.flow.FlowRuleOperationsContext; +import org.onosproject.net.flow.FlowRuleService; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.criteria.Criterion; +import org.onosproject.net.flow.criteria.EthTypeCriterion; +import org.onosproject.net.flow.criteria.UdpPortCriterion; +import org.onosproject.net.flowobjective.FilteringObjective; +import org.onosproject.net.flowobjective.FlowObjectiveStore; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.NextObjective; +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.flowobjective.ObjectiveError; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.Collections; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Driver for OpenstackSwitching. + */ +public class OpenstackPipeline extends DefaultSingleTablePipeline + implements Pipeliner { + + private final Logger log = getLogger(getClass()); + private CoreService coreService; + private ServiceDirectory serviceDirectory; + protected FlowObjectiveStore flowObjectiveStore; + protected DeviceId deviceId; + protected ApplicationId appId; + protected FlowRuleService flowRuleService; + + protected static final int VNI_TABLE = 0; + protected static final int FORWARDING_TABLE = 1; + + private static final int DROP_PRIORITY = 0; + private static final int TIME_OUT = 0; + private static final int DHCP_SERVER_PORT = 67; + private static final int DHCP_CLIENT_PORT = 68; + + + @Override + public void init(DeviceId deviceId, PipelinerContext context) { + super.init(deviceId, context); + this.serviceDirectory = context.directory(); + this.deviceId = deviceId; + + coreService = serviceDirectory.get(CoreService.class); + flowRuleService = serviceDirectory.get(FlowRuleService.class); + flowObjectiveStore = context.store(); + + appId = coreService.registerApplication( + "org.onosproject.driver.OpenstackPipeline"); + + initializePipeline(); + } + + @Override + public void filter(FilteringObjective filteringObjective) { + super.filter(filteringObjective); + } + + @Override + public void next(NextObjective nextObjective) { + super.next(nextObjective); + } + + @Override + public void forward(ForwardingObjective forwardingObjective) { + Collection rules; + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); + + rules = processForward(forwardingObjective); + + switch (forwardingObjective.op()) { + case ADD: + rules.stream() + .filter(rule -> rule != null) + .forEach(flowOpsBuilder::add); + break; + case REMOVE: + rules.stream() + .filter(rule -> rule != null) + .forEach(flowOpsBuilder::remove); + break; + default: + fail(forwardingObjective, ObjectiveError.UNKNOWN); + log.warn("Unknown forwarding type {}"); + } + + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { + @Override + public void onSuccess(FlowRuleOperations ops) { + pass(forwardingObjective); + } + + @Override + public void onError(FlowRuleOperations ops) { + fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED); + } + })); + } + + private void initializePipeline() { + processVNITable(true); + processForwardingTable(true); + } + + private void processVNITable(boolean install) { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); + + treatment.transition(FORWARDING_TABLE); + + FlowRule flowRule = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(selector.build()) + .withTreatment(treatment.build()) + .withPriority(DROP_PRIORITY) + .fromApp(appId) + .makePermanent() + .forTable(VNI_TABLE) + .build(); + + applyRules(install, flowRule); + } + + private void processForwardingTable(boolean install) { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); + + treatment.drop(); + + FlowRule flowRule = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(selector.build()) + .withTreatment(treatment.build()) + .withPriority(DROP_PRIORITY) + .fromApp(appId) + .makePermanent() + .forTable(FORWARDING_TABLE) + .build(); + + applyRules(install, flowRule); + } + + private void applyRules(boolean install, FlowRule flowRule) { + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); + + flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule); + + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { + @Override + public void onSuccess(FlowRuleOperations ops) { + log.debug("Provisioned vni or forwarding table"); + } + + @Override + public void onError(FlowRuleOperations ops) { + log.debug("Failed to privision vni or forwarding table"); + } + })); + } + + private Collection processForward(ForwardingObjective forwardingObjective) { + switch (forwardingObjective.flag()) { + case SPECIFIC: + return processSpecific(forwardingObjective); + case VERSATILE: + return processVersatile(forwardingObjective); + default: + fail(forwardingObjective, ObjectiveError.UNKNOWN); + log.warn("Unknown forwarding flag {}", forwardingObjective.flag()); + } + return Collections.emptySet(); + } + + private Collection processVersatile(ForwardingObjective forwardingObjective) { + log.debug("Processing versatile forwarding objective"); + + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(forwardingObjective.selector()) + .withTreatment(forwardingObjective.treatment()) + .withPriority(forwardingObjective.priority()) + .fromApp(forwardingObjective.appId()); + + if (forwardingObjective.permanent()) { + ruleBuilder.makePermanent(); + } else { + ruleBuilder.makeTemporary(TIME_OUT); + } + + //ARP & DHCP Rule + EthTypeCriterion ethCriterion = + (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE); + UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective + .selector().getCriterion(Criterion.Type.UDP_DST); + if (ethCriterion != null) { + if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP || + ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) { + ruleBuilder.forTable(VNI_TABLE); + return Collections.singletonList(ruleBuilder.build()); + } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) { + ruleBuilder.forTable(VNI_TABLE); + return Collections.singletonList(ruleBuilder.build()); + } + } + return Collections.emptySet(); + } + + private Collection processSpecific(ForwardingObjective forwardingObjective) { + log.debug("Processing specific forwarding objective"); + + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() + .forDevice(deviceId) + .withSelector(forwardingObjective.selector()) + .withTreatment(forwardingObjective.treatment()) + .withPriority(forwardingObjective.priority()) + .fromApp(forwardingObjective.appId()); + + if (forwardingObjective.permanent()) { + ruleBuilder.makePermanent(); + } else { + ruleBuilder.makeTemporary(TIME_OUT); + } + + //VNI Table Rule + if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) { + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); + forwardingObjective.treatment().allInstructions().forEach(tBuilder::add); + tBuilder.transition(FORWARDING_TABLE); + ruleBuilder.withTreatment(tBuilder.build()); + ruleBuilder.forTable(VNI_TABLE); + } else { + ruleBuilder.forTable(FORWARDING_TABLE); + } + + return Collections.singletonList(ruleBuilder.build()); + } + + + private void pass(Objective obj) { + if (obj.context().isPresent()) { + obj.context().get().onSuccess(obj); + } + } + + private void fail(Objective obj, ObjectiveError error) { + if (obj.context().isPresent()) { + obj.context().get().onError(obj, error); + } + } +} + diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java index 8ac5eec8..dba4557a 100644 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java +++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java @@ -287,24 +287,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour case SIMPLE: Collection treatments = nextObjective.next(); if (treatments.size() == 1) { - TrafficTreatment treatment = treatments.iterator().next(); - GroupBucket bucket = DefaultGroupBucket - .createIndirectGroupBucket(treatment); - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective - .id())); - GroupDescription groupDescription = new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets( - Collections.singletonList(bucket)), - key, - null, - nextObjective.appId()); - log.debug("Creating SIMPLE group for next objective id {} " - + "in dev:{}", nextObjective.id(), deviceId); - pendingGroups.put(key, nextObjective); - groupService.addGroup(groupDescription); + // Spring Open TTP converts simple nextObjective to flow-actions + // in a dummy group + TrafficTreatment treatment = nextObjective.next().iterator().next(); + log.debug("Converting SIMPLE group for next objective id {} " + + "to {} flow-actions in device:{}", nextObjective.id(), + treatment.allInstructions().size(), deviceId); + flowObjectiveStore.putNextGroup(nextObjective.id(), + new SpringOpenGroup(null, treatment)); } break; case HASHED: @@ -624,8 +614,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour if (next != null) { SpringOpenGroup soGroup = appKryo.deserialize(next.data()); if (soGroup.dummy) { - log.debug("Adding flow-actions for fwd. obj. {} " - + "in dev: {}", fwd.id(), deviceId); + log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} " + + "in dev: {}", soGroup.treatment.allInstructions().size(), + fwd.id(), fwd.nextId(), deviceId); for (Instruction ins : soGroup.treatment.allInstructions()) { treatmentBuilder.add(ins); } @@ -639,7 +630,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour } treatmentBuilder.deferred().group(group.id()); log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " - + "in dev: {}", group.id(), fwd.id(), deviceId); + + "for next:{} in dev: {}", group.id(), fwd.id(), + fwd.nextId(), deviceId); } } else { log.warn("processSpecific: No associated next objective object"); @@ -705,10 +697,11 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour if (next != null) { SpringOpenGroup soGrp = appKryo.deserialize(next.data()); if (soGrp.dummy) { - log.debug("Adding flow-actions for fwd. obj. {} " - + "in dev: {}", fwd.id(), deviceId); + log.debug("Adding {} flow-actions for fwd. obj. {} " + + "in dev: {}", soGrp.treatment.allInstructions().size(), + fwd.id(), deviceId); for (Instruction ins : soGrp.treatment.allInstructions()) { - treatmentBuilder.add(ins); + treatmentBuilder.deferred().add(ins); } } else { GroupKey key = soGrp.key; @@ -773,6 +766,12 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour return rules; } + /* + * Note: CpqD switches do not handle MPLS-related operation properly + * for a packet with VLAN tag. We pop VLAN here as a workaround. + * Side effect: HostService learns redundant hosts with same MAC but + * different VLAN. No known side effect on the network reachability. + */ protected List processEthDstFilter(EthCriterion ethCriterion, VlanIdCriterion vlanIdCriterion, FilteringObjective filt, @@ -783,12 +782,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); } - /* - * Note: CpqD switches do not handle MPLS-related operation properly - * for a packet with VLAN tag. We pop VLAN here as a workaround. - * Side effect: HostService learns redundant hosts with same MAC but - * different VLAN. No known side effect on the network reachability. - */ List rules = new ArrayList<>(); TrafficSelector.Builder selectorIp = DefaultTrafficSelector .builder(); diff --git a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml index a172c18b..2494e123 100644 --- a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml +++ b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml @@ -36,6 +36,10 @@ impl="org.onosproject.driver.extensions.NiciraExtensionTreatmentInterpreter" /> + + + @@ -131,6 +137,8 @@ swVersion="ocs switch"> + diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java new file mode 100644 index 00000000..45d6d941 --- /dev/null +++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import org.junit.Test; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +import com.google.common.testing.EqualsTester; + +/** + * Unit tests for NiciraSetNshContextHeader class. + */ +public class NiciraSetNshContextHeaderTest { + + final NiciraSetNshContextHeader nshCh1 = new NiciraSetNshContextHeader(10, + ExtensionTreatmentType. + ExtensionTreatmentTypes. + NICIRA_SET_NSH_CH1.type()); + final NiciraSetNshContextHeader sameAsNshCh1 = new NiciraSetNshContextHeader(10, + ExtensionTreatmentType. + ExtensionTreatmentTypes. + NICIRA_SET_NSH_CH1.type()); + final NiciraSetNshContextHeader nshCh2 = new NiciraSetNshContextHeader(20, + ExtensionTreatmentType. + ExtensionTreatmentTypes. + NICIRA_SET_NSH_CH1.type()); + + /** + * Checks the operation of equals() methods. + */ + @Test + public void testEquals() { + new EqualsTester().addEqualityGroup(nshCh1, sameAsNshCh1).addEqualityGroup(nshCh2).testEquals(); + } + + /** + * Checks the construction of a NiciraSetNshSi object. + */ + @Test + public void testConstruction() { + final NiciraSetNshContextHeader niciraSetNshCh = new NiciraSetNshContextHeader(10, + ExtensionTreatmentType. + ExtensionTreatmentTypes. + NICIRA_SET_NSH_CH1.type()); + assertThat(niciraSetNshCh, is(notNullValue())); + assertThat(niciraSetNshCh.nshCh(), is(10)); + assertThat(niciraSetNshCh.type(), is(ExtensionTreatmentType. + ExtensionTreatmentTypes. + NICIRA_SET_NSH_CH1.type())); + } +} diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java new file mode 100644 index 00000000..8541e9f0 --- /dev/null +++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Unit tests for NiciraSetNshSi class. + */ +public class NiciraSetNshSiTest { + + final NiciraSetNshSi nshSi1 = new NiciraSetNshSi((byte) 10); + final NiciraSetNshSi sameAsNshSi1 = new NiciraSetNshSi((byte) 10); + final NiciraSetNshSi nshSi2 = new NiciraSetNshSi((byte) 20); + + /** + * Checks the operation of equals() methods. + */ + @Test + public void testEquals() { + new EqualsTester().addEqualityGroup(nshSi1, sameAsNshSi1).addEqualityGroup(nshSi2).testEquals(); + } + + /** + * Checks the construction of a NiciraSetNshSi object. + */ + @Test + public void testConstruction() { + final NiciraSetNshSi niciraSetNshSi = new NiciraSetNshSi((byte) 15); + assertThat(niciraSetNshSi, is(notNullValue())); + assertThat(niciraSetNshSi.nshSi(), is((byte) 15)); + } +} diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java new file mode 100644 index 00000000..197e3bf9 --- /dev/null +++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.driver.extensions; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Unit tests for NiciraSetNshSpi class. + */ +public class NiciraSetNshSpiTest { + + final NiciraSetNshSpi nshSpi1 = new NiciraSetNshSpi(10); + final NiciraSetNshSpi sameAsNshSpi1 = new NiciraSetNshSpi(10); + final NiciraSetNshSpi nshSpi2 = new NiciraSetNshSpi(20); + + /** + * Checks the operation of equals() methods. + */ + @Test + public void testEquals() { + new EqualsTester().addEqualityGroup(nshSpi1, sameAsNshSpi1).addEqualityGroup(nshSpi2).testEquals(); + } + + /** + * Checks the construction of a NiciraSetNshSpi object. + */ + @Test + public void testConstruction() { + final NiciraSetNshSpi niciraSetNshSpi = new NiciraSetNshSpi(10); + assertThat(niciraSetNshSpi, is(notNullValue())); + assertThat(niciraSetNshSpi.nshSpi(), is(10)); + } +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java index 9f2d4105..5246f313 100644 --- a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java @@ -28,6 +28,7 @@ import org.onosproject.net.ConnectPoint; import org.onosproject.net.config.Config; import org.onosproject.net.host.InterfaceIpAddress; +import java.util.Iterator; import java.util.Set; /** @@ -35,6 +36,7 @@ import java.util.Set; */ @Beta public class InterfaceConfig extends Config { + public static final String NAME = "name"; public static final String IPS = "ips"; public static final String MAC = "mac"; public static final String VLAN = "vlan"; @@ -52,6 +54,8 @@ public class InterfaceConfig extends Config { try { for (JsonNode intfNode : array) { + String name = intfNode.path(NAME).asText(null); + Set ips = getIps(intfNode); String mac = intfNode.path(MAC).asText(); @@ -59,7 +63,7 @@ public class InterfaceConfig extends Config { VlanId vlan = getVlan(intfNode); - interfaces.add(new Interface(subject, ips, macAddr, vlan)); + interfaces.add(new Interface(name, subject, ips, macAddr, vlan)); } } catch (IllegalArgumentException e) { throw new ConfigException(CONFIG_VALUE_ERROR, e); @@ -76,6 +80,8 @@ public class InterfaceConfig extends Config { public void addInterface(Interface intf) { ObjectNode intfNode = array.addObject(); + intfNode.put(NAME, intf.name()); + if (intf.mac() != null) { intfNode.put(MAC, intf.mac().toString()); } @@ -92,12 +98,14 @@ public class InterfaceConfig extends Config { /** * Removes an interface from the config. * - * @param intf interface to remove + * @param name name of the interface to remove */ - public void removeInterface(Interface intf) { - for (int i = 0; i < array.size(); i++) { - if (intf.vlan().equals(getVlan(node))) { - array.remove(i); + public void removeInterface(String name) { + Iterator it = array.iterator(); + while (it.hasNext()) { + JsonNode node = it.next(); + if (node.path(NAME).asText().equals(name)) { + it.remove(); break; } } diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/Alarm.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/Alarm.java new file mode 100644 index 00000000..765fbfef --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/Alarm.java @@ -0,0 +1,211 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import org.onosproject.net.DeviceId; + +/** + * Representation of an Alarm. At a given instant there can be only one alarm + * with the same deviceId + description + source combination. + */ +public interface Alarm { + + /** + * Returns the unique alarm id within this ONOS instance. + * + * @return alarm identifier + */ + AlarmId id(); + + /** + * The device to which this alarm is related. + * + * @return a device id + */ + DeviceId deviceId(); + + /** + * Returns a description of alarm. + *

+ * It may encapsulate Event Type as described by ITU Recommendation X.736 + * ITU, Quoting https://tools.ietf.org/html/rfc3877 these include: other, + * communicationsAlarm, qualityOfServiceAlarm, processingErrorAlarm, + * equipmentAlarm, environmentalAlarm, integrityViolation, + * operationalViolation, physicalViolation, + * securityServiceOrMechanismViolation, timeDomainViolation + *

+ * It may encapsulate Probable Cause as described by ITU Recommendation + * X.736 ITU, Quoting + * https://www.iana.org/assignments/ianaitualarmtc-mib/ianaitualarmtc-mib + * these include : aIS, callSetUpFailure, degradedSignal, + * farEndReceiverFailure, framingError, and hundreds more constants. + *

+ * It may encapsulate a vendor-specific description of the underlying fault. + * + * @return description of alarm + */ + String description(); + + /** + * Returns an entity within the context of this alarm's device. It may be + * null if deviceId sufficiently identifies the location. As an example, the + * source may indicate a port number + * + * @return source of alarm within the alarm's referenced Device. + */ + AlarmEntityId source(); + + /** + * Returns the time when raised. + * + * @return time when raised, in milliseconds since start of epoch + */ + long timeRaised(); + + /** + * Returns time at which the alarm was updated most recently, due to some + * change in the device, or ONOS. If the alarm has been cleared, this is the + * time at which the alarm was cleared. + * + * @return time when last updated, in milliseconds since start of epoch + */ + long timeUpdated(); + + /** + * Returns the time when cleared. Null indicated no clear time, i.e. the + * alarm is still active. + * + * @return time when cleared, in milliseconds since start of epoch or null + * if uncleared. + */ + Long timeCleared(); + + /** + * Returns the severity. Note, that cleared alarms may have EITHER + * SeverityLevel = CLEARED, or may be not present; both scenarios should be + * handled. + * + * @return severity of the alarm + */ + SeverityLevel severity(); + + /** + * Returns true if alarm is service affecting Note: Whilst X.733 combines + * service-affecting state with severity (where severities of critical and + * major are deemed service-affecting) ONOS keeps these attributes separate. + * + * @return whether service affecting (true indicates it is) + */ + boolean serviceAffecting(); + + /** + * Returns a flag to indicate if this alarm has been acknowledged. All + * alarms are unacknowledged until and unless an ONOS user takes action to + * indicate so. + * + * @return whether alarm is currently acknowledged (true indicates it is) + */ + boolean acknowledged(); + + /** + * Returns a flag to indicate if this alarm is manually-cleared by a user action within ONOS. Some stateless events + * e.g. backup-failure or upgrade-failure, may be mapped by ONOS to alarms, and these may be deemed manually- + * clearable. The more typical case is that an alarm represents a persistent fault on or related to a device and + * such alarms are never manually clearable, i.e. a configuration or operational state must occur for the alarm to + * clear. + * + * @return whether it may be cleared by a user action (true indicates it is) + */ + boolean manuallyClearable(); + + /** + * Returns the user to whom this alarm is assigned; this is for future use + * and always returns null in this release. It is anticipated that in future ONOS + * releases, the existing JAAS user/key/role configuration will be extended + * to include a mechanism whereby some groups of users may allocate alarms + * to other users for bookkeeping and administrative purposes, and that ONOS + * will additionally provide a REST based mechanism, to retrieve from JAAS, + * the set of users to whom alarm assignment is possible for the current + * user. + * + * @return the assigned user; always null in this release. + */ + String assignedUser(); + + /** + * Represents the severity level on an alarm, as per ITU-T X.733 + * specifications. + *

+ * The precedence is as follows for : Critical > Major > Minor > Warning. + */ + enum SeverityLevel { + + /** + * From X.733: This indicates the clearing of one or more previously + * reported alarms. This alarm clears all alarms for this managed object + * that have the same Alarm type, Probable cause and Specific problems + * (if given). Multiple associated notifications may be cleared by using + * the Correlated notifications parameter (defined below). This + * Recommendation | International Standard does not require that the + * clearing of previously reported alarms be reported. Therefore, a + * managing system cannot assume that the absence of an alarm with the + * Cleared severity level means that the condition that caused the + * generation of previous alarms is still present. Managed object + * definers shall state if, and under which conditions, the Cleared + * severity level is used. + */ + CLEARED, + /** + * From X.733: This indicates that the severity level cannot be + * determined. + */ + INDETERMINATE, + /** + * From X.733: This indicates that a service affecting condition has + * occurred and an immediate corrective action is required. Such a + * severity can be reported, for example, when a managed object becomes + * totally out of service and its capability must be restored. + */ + CRITICAL, + /** + * X.733 definition: This indicates that a service affecting condition + * has developed and an urgent corrective action is required. Such a + * severity can be reported, for example, when there is a severe + * degradation in the capability of the managed object and its full + * capability must be restored. + */ + MAJOR, + /** + * From X.733: This indicates the existence of a non-service affecting + * fault condition and that corrective action should be taken in order + * to prevent a more serious (for example, service affecting) fault. + * Such a severity can be reported, for example, when the detected alarm + * condition is not currently degrading the capacity of the managed + * object. + */ + MINOR, + /** + * From X.733: This indicates the detection of a potential or impending + * service affecting fault, before any significant effects have been + * felt. Action should be taken to further diagnose (if necessary) and + * correct the problem in order to prevent it from becoming a more + * serious service affecting fault. + */ + WARNING; + + } + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityId.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityId.java new file mode 100644 index 00000000..5bf86749 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityId.java @@ -0,0 +1,75 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import static com.google.common.base.Preconditions.checkArgument; +import com.google.common.collect.ImmutableSet; +import java.net.URI; +import java.util.Objects; +import java.util.Set; + +/** + * Immutable representation of a alarm source. It is meaningful within the + * context of a device. + */ +public final class AlarmEntityId { + + public static final AlarmEntityId NONE = new AlarmEntityId(URI.create("none:none")); + public static final Set SCHEMES = ImmutableSet.of("none", "port", "och", "other"); + + private final URI uri; + + private AlarmEntityId(final URI uri) { + this.uri = uri; + } + + protected AlarmEntityId() { + uri = NONE.uri; + } + + public static AlarmEntityId alarmEntityId(final String string) { + return alarmEntityId(URI.create(string)); + } + + public static AlarmEntityId alarmEntityId(final URI uri) { + checkArgument(SCHEMES.contains(uri.getScheme()), "Unexpected scheme"); + return new AlarmEntityId(uri); + } + + @Override + public String toString() { + return uri.toString(); + } + + @Override + public int hashCode() { + return Objects.hash(uri); + + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof AlarmEntityId) { + final AlarmEntityId other = (AlarmEntityId) obj; + return Objects.equals(this.uri, other.uri); + } + return false; + } + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEvent.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEvent.java new file mode 100644 index 00000000..bbbd993e --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEvent.java @@ -0,0 +1,65 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import org.onosproject.event.AbstractEvent; + +/** + * Entity that represents Alarm events. + */ +public class AlarmEvent extends AbstractEvent { + + + /** + * Creates an event of a given type and for the specified alarm and the + * current time. + * + * @param type topology event type + * @param alarm the alarm + */ + public AlarmEvent(Type type, Alarm alarm) { + super(type, alarm); + } + + /** + * Creates an event of a given type and for the specified alarm and time. + * + * @param type link event type + * @param alarm the alarm + * @param time occurrence time + */ + public AlarmEvent(Type type, Alarm alarm, + long time) { + super(type, alarm, time); + } + + /** + * Type of alarm events. + */ + public enum Type { + /** + * A Raised Alarm. + */ + RAISE, + + /** + * A Cleared Alarm. + */ + CLEAR + } + + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmId.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmId.java new file mode 100644 index 00000000..e0107f87 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmId.java @@ -0,0 +1,84 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import com.google.common.annotations.Beta; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; + +/** + * Alarm identifier suitable as an external key. + *

+ * This class is immutable.

+ */ +@Beta +public final class AlarmId { + + private final long id; + + /** + * Instantiates a new Alarm id. + * + * @param id the id + */ + public AlarmId(final long id) { + this.id = id; + } + + /** + * Creates an alarm identifier from the specified long representation. + * + * @param value long value + * @return intent identifier + */ + public static AlarmId valueOf(final long value) { + return new AlarmId(value); + } + + /** + * Returns the backing integer index. + * + * @return backing integer index + */ + public long fingerprint() { + return id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof AlarmId) { + final AlarmId other = (AlarmId) obj; + return Objects.equals(this.id, other.id); + } + return false; + } + + @Override + public String toString() { + return toStringHelper(this).add("id", id).toString(); + } + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmListener.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmListener.java new file mode 100644 index 00000000..c5e82ba5 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmListener.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import org.onosproject.event.EventListener; + + +/** + * Entity capable of receiving Alarm related events. + */ +public interface AlarmListener extends EventListener { +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProvider.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProvider.java new file mode 100644 index 00000000..82bcda2a --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.Provider; + +/** + * Abstraction of a Alarm provider. + */ +public interface AlarmProvider extends Provider { + + /** + * Triggers an asynchronous discovery of the alarms on the specified device, + * intended to refresh internal alarm model for the device. An indirect + * result of this should be invocation of + * {@link org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderService#updateAlarmList} )} + * at some later point in time. + * + * @param deviceId ID of device to be probed + */ + void triggerProbe(DeviceId deviceId); + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderRegistry.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderRegistry.java new file mode 100644 index 00000000..618298c0 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderRegistry.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + + +import org.onosproject.net.provider.ProviderRegistry; + +/** + * Abstraction of a alarm provider registry. + */ +public interface AlarmProviderRegistry extends ProviderRegistry { +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderService.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderService.java new file mode 100644 index 00000000..727aa281 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmProviderService.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + + +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.ProviderService; + +import java.util.Collection; + +/** + * The interface Alarm provider service. + */ +public interface AlarmProviderService extends ProviderService { + + /** + * Sends active alarm list for a device. + * + * @param deviceId identity of the device + * @param alarms list of device alarms + */ + void updateAlarmList(DeviceId deviceId, Collection alarms); + +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmService.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmService.java new file mode 100644 index 00000000..03c0c7b1 --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmService.java @@ -0,0 +1,121 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import com.google.common.annotations.Beta; +//import org.onosproject.event.ListenerService; + +import java.util.Set; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; + +/** + * Service for interacting with the alarm handling of devices. Unless stated + * otherwise method return active AND recently-cleared alarms. + */ +@Beta +public interface AlarmService { +// extends ListenerService { + + /** + * Alarm should be updated in ONOS's internal representation; only + * administration/book-keeping fields may be updated. Attempting to update + * fields which are mapped directly from device is prohibited. + * + * @param replacement alarm with updated book-keeping fields + * @return updated alarm (including any recent device derived changes) + + * @throws java.lang.IllegalStateException if attempt to update not allowed + * fields. + */ + Alarm update(Alarm replacement); + + /** + * Returns the number of ACTIVE alarms on a device. + * + * @param deviceId the device + * @return number of alarms + */ + int getActiveAlarmCount(DeviceId deviceId); + + /** + * Returns the alarm with the specified identifier. + * + * @param alarmId alarm identifier + * @return alarm or null if one with the given identifier is not known + */ + Alarm getAlarm(AlarmId alarmId); + + /** + * Returns all of the alarms. + * + * @return the alarms + */ + Set getAlarms(); + + /** + * Returns all of the ACTIVE alarms. Recently cleared alarms excluded. + * + * @return the alarms + */ + Set getActiveAlarms(); + + /** + * Returns the alarms with the specified severity. + * + * @param severity the alarm severity + * @return the active alarms with a particular severity + */ + Set getAlarms(Alarm.SeverityLevel severity); + + /** + * Returns the alarm for a given device, regardless of source within that + * device. + * + * @param deviceId the device + * @return the alarms + */ + Set getAlarms(DeviceId deviceId); + + /** + * Returns the alarm for a given device and source. + * + * @param deviceId the device + * @param source the source within the device + * @return the alarms + */ + Set getAlarms(DeviceId deviceId, AlarmEntityId source); + + /** + * Returns the alarm affecting a given link. + * + * @param src one end of the link + * @param dst one end of the link + * @return the alarms + */ + Set getAlarmsForLink(ConnectPoint src, ConnectPoint dst); + + /** + * Returns the alarm affecting a given flow. + * + * @param deviceId the device + * @param flowId the flow + * @return the alarms + */ + Set getAlarmsForFlow(DeviceId deviceId, long flowId); + +// Support retrieving alarms affecting other ONOS entity types may be added in future release +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java new file mode 100644 index 00000000..afa366ad --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java @@ -0,0 +1,309 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import org.onosproject.net.DeviceId; + +import java.util.Objects; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Default implementation of an alarm. + */ +public final class DefaultAlarm implements Alarm { + + private final AlarmId id; + + private final DeviceId deviceId; + private final String description; + private final AlarmEntityId source; + private final long timeRaised; + private final long timeUpdated; + private final Long timeCleared; + private final SeverityLevel severity; + private final boolean isServiceAffecting; + private final boolean isAcknowledged; + private final boolean isManuallyClearable; + private final String assignedUser; + + /** + * Instantiates a new Default alarm. + * + * @param id the id + * @param deviceId the device id + * @param description the description + * @param source the source, null indicates none. + * @param timeRaised the time raised. + * @param timeUpdated the time last updated. + * @param timeCleared the time cleared, null indicates uncleared. + * @param severity the severity + * @param isServiceAffecting the service affecting + * @param isAcknowledged the acknowledged + * @param isManuallyClearable the manually clearable + * @param assignedUser the assigned user, `null` indicates none. + */ + private DefaultAlarm(final AlarmId id, + final DeviceId deviceId, + final String description, + final AlarmEntityId source, + final long timeRaised, + final long timeUpdated, + final Long timeCleared, + final SeverityLevel severity, + final boolean isServiceAffecting, + final boolean isAcknowledged, + final boolean isManuallyClearable, + final String assignedUser) { + this.id = id; + this.deviceId = deviceId; + this.description = description; + this.source = source; + this.timeRaised = timeRaised; + this.timeUpdated = timeUpdated; + this.timeCleared = timeCleared; + this.severity = severity; + this.isServiceAffecting = isServiceAffecting; + this.isAcknowledged = isAcknowledged; + this.isManuallyClearable = isManuallyClearable; + this.assignedUser = assignedUser; + } + + @Override + public AlarmId id() { + return id; + } + + @Override + public DeviceId deviceId() { + return deviceId; + } + + @Override + public String description() { + return description; + } + + @Override + public AlarmEntityId source() { + return source; + } + + @Override + public long timeRaised() { + return timeRaised; + } + + @Override + public long timeUpdated() { + return timeUpdated; + } + + @Override + public Long timeCleared() { + return timeCleared; + } + + @Override + public SeverityLevel severity() { + return severity; + } + + @Override + public boolean serviceAffecting() { + return isServiceAffecting; + } + + @Override + public boolean acknowledged() { + return isAcknowledged; + } + + @Override + public boolean manuallyClearable() { + return isManuallyClearable; + } + + @Override + public String assignedUser() { + return assignedUser; + } + + @Override + public int hashCode() { + return Objects.hash(id, deviceId, description, + source, timeRaised, timeUpdated, timeCleared, severity, + isServiceAffecting, isAcknowledged, + isManuallyClearable, assignedUser); + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DefaultAlarm other = (DefaultAlarm) obj; + if (!Objects.equals(this.id, other.id)) { + return false; + } + if (!Objects.equals(this.deviceId, other.deviceId)) { + return false; + } + if (!Objects.equals(this.description, other.description)) { + return false; + } + if (!Objects.equals(this.source, other.source)) { + return false; + } + if (this.timeRaised != other.timeRaised) { + return false; + } + if (this.timeUpdated != other.timeUpdated) { + return false; + } + if (!Objects.equals(this.timeCleared, other.timeCleared)) { + return false; + } + if (this.severity != other.severity) { + return false; + } + if (this.isServiceAffecting != other.isServiceAffecting) { + return false; + } + if (this.isAcknowledged != other.isAcknowledged) { + return false; + } + if (this.isManuallyClearable != other.isManuallyClearable) { + return false; + } + if (!Objects.equals(this.assignedUser, other.assignedUser)) { + return false; + } + return true; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("id", id) + .add("deviceId", deviceId) + .add("description", description) + .add("source", source) + .add("timeRaised", timeRaised) + .add("timeUpdated", timeUpdated) + .add("timeCleared", timeCleared) + .add("severity", severity) + .add("serviceAffecting", isServiceAffecting) + .add("acknowledged", isAcknowledged) + .add("manuallyClearable", isManuallyClearable) + .add("assignedUser", assignedUser) + .toString(); + } + + public static class Builder { + + // Manadatory fields .. + private final AlarmId id; + private final DeviceId deviceId; + private final String description; + private final SeverityLevel severity; + private final long timeRaised; + + // Optional fields .. + private AlarmEntityId source = AlarmEntityId.NONE; + private long timeUpdated; + private Long timeCleared = null; + private boolean isServiceAffecting = false; + private boolean isAcknowledged = false; + private boolean isManuallyClearable = false; + private String assignedUser = null; + + public Builder(final Alarm alarm) { + this(alarm.id(), alarm.deviceId(), alarm.description(), alarm.severity(), alarm.timeRaised()); + this.source = AlarmEntityId.NONE; + this.timeUpdated = alarm.timeUpdated(); + this.timeCleared = alarm.timeCleared(); + this.isServiceAffecting = alarm.serviceAffecting(); + this.isAcknowledged = alarm.acknowledged(); + this.isManuallyClearable = alarm.manuallyClearable(); + this.assignedUser = alarm.assignedUser(); + + } + + public Builder(final AlarmId id, final DeviceId deviceId, + final String description, final SeverityLevel severity, final long timeRaised) { + super(); + this.id = id; + this.deviceId = deviceId; + this.description = description; + this.severity = severity; + this.timeRaised = timeRaised; + // Unless specified time-updated is same as raised. + this.timeUpdated = timeRaised; + } + + public Builder forSource(final AlarmEntityId source) { + this.source = source; + return this; + } + + public Builder withTimeUpdated(final long timeUpdated) { + this.timeUpdated = timeUpdated; + return this; + } + + public Builder withTimeCleared(final Long timeCleared) { + this.timeCleared = timeCleared; + return this; + } + + public Builder withServiceAffecting(final boolean isServiceAffecting) { + this.isServiceAffecting = isServiceAffecting; + return this; + } + + public Builder withAcknowledged(final boolean isAcknowledged) { + this.isAcknowledged = isAcknowledged; + return this; + } + + public Builder withManuallyClearable(final boolean isManuallyClearable) { + this.isManuallyClearable = isManuallyClearable; + return this; + } + + public Builder withAssignedUser(final String assignedUser) { + this.assignedUser = assignedUser; + return this; + } + + public DefaultAlarm build() { + checkNotNull(id, "Must specify an alarm id"); + checkNotNull(deviceId, "Must specify a device"); + checkNotNull(description, "Must specify a description"); + checkNotNull(timeRaised, "Must specify a time raised"); + checkNotNull(timeUpdated, "Must specify a time updated"); + checkNotNull(severity, "Must specify a severity"); + + return new DefaultAlarm(id, deviceId, description, source, timeRaised, timeUpdated, timeCleared, + severity, isServiceAffecting, isAcknowledged, isManuallyClearable, assignedUser); + } + } +} diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/package-info.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/package-info.java new file mode 100644 index 00000000..b2b8ec9f --- /dev/null +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Abstractions for interacting with alarms. An alarm is a persistent indication + * of a fault that clears only when the triggering condition has been resolved. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java index b9d3eadf..e2109689 100644 --- a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java @@ -30,11 +30,13 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * An Interface maps network configuration information (such as addresses and - * vlans) to a port in the network. This is considered a L2/L3 network - * interface. + * vlans) to a port in the network. */ @Beta public class Interface { + public static final String NO_INTERFACE_NAME = ""; + + private final String name; private final ConnectPoint connectPoint; private final Set ipAddresses; private final MacAddress macAddress; @@ -43,20 +45,45 @@ public class Interface { /** * Creates new Interface with the provided configuration. * + * @param name name of the interface * @param connectPoint the connect point this interface maps to * @param ipAddresses Set of IP addresses * @param macAddress MAC address * @param vlan VLAN ID */ - public Interface(ConnectPoint connectPoint, + public Interface(String name, ConnectPoint connectPoint, Set ipAddresses, MacAddress macAddress, VlanId vlan) { + this.name = name == null ? NO_INTERFACE_NAME : name; this.connectPoint = checkNotNull(connectPoint); this.ipAddresses = ipAddresses == null ? Sets.newHashSet() : ipAddresses; this.macAddress = macAddress == null ? MacAddress.NONE : macAddress; this.vlan = vlan == null ? VlanId.NONE : vlan; } + /** + * Creates new Interface with the provided configuration. + * + * @param connectPoint the connect point this interface maps to + * @param ipAddresses Set of IP addresses + * @param macAddress MAC address + * @param vlan VLAN ID + */ + public Interface(ConnectPoint connectPoint, + Set ipAddresses, + MacAddress macAddress, VlanId vlan) { + this(NO_INTERFACE_NAME, connectPoint, ipAddresses, macAddress, vlan); + } + + /** + * Retrieves the name of the interface. + * + * @return name + */ + public String name() { + return name; + } + /** * Retrieves the connection point that this interface maps to. * @@ -101,7 +128,8 @@ public class Interface { Interface otherInterface = (Interface) other; - return Objects.equals(connectPoint, otherInterface.connectPoint) && + return Objects.equals(name, otherInterface.name) && + Objects.equals(connectPoint, otherInterface.connectPoint) && Objects.equals(ipAddresses, otherInterface.ipAddresses) && Objects.equals(macAddress, otherInterface.macAddress) && Objects.equals(vlan, otherInterface.vlan); @@ -109,12 +137,13 @@ public class Interface { @Override public int hashCode() { - return Objects.hash(connectPoint, ipAddresses, macAddress, vlan); + return Objects.hash(connectPoint, name, ipAddresses, macAddress, vlan); } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) + .add("name", name) .add("connectPoint", connectPoint) .add("ipAddresses", ipAddresses) .add("macAddress", macAddress) diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/InterfaceAdminService.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/InterfaceAdminService.java index 56d5aecc..32d480d6 100644 --- a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/InterfaceAdminService.java +++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/InterfaceAdminService.java @@ -16,13 +16,13 @@ package org.onosproject.incubator.net.intf; -import org.onlab.packet.VlanId; import org.onosproject.net.ConnectPoint; /** * Provides a means to modify the interfaces configuration. */ public interface InterfaceAdminService { + /** * Adds a new interface configuration to the system. * @@ -34,7 +34,7 @@ public interface InterfaceAdminService { * Removes an interface configuration from the system. * * @param connectPoint connect point of the interface - * @param vlanId vlan id + * @param name name of the interface */ - void remove(ConnectPoint connectPoint, VlanId vlanId); + boolean remove(ConnectPoint connectPoint, String name); } diff --git a/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityIdTest.java b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityIdTest.java new file mode 100644 index 00000000..55f052ac --- /dev/null +++ b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmEntityIdTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import com.google.common.testing.EqualsTester; +import static org.junit.Assert.assertEquals; +import org.junit.Test; +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; +import static org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId.alarmEntityId; + +/** + * Test of the alarm source identifier. + * + */ +public class AlarmEntityIdTest { + + /** + * Checks that the class is immutable. + */ + @Test + public void testImmutability() { + assertThatClassIsImmutable(AlarmEntityId.class); + } + + @Test + public void string() { + assertEquals("och:foo", + alarmEntityId("och:foo").toString()); + } + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup( + alarmEntityId("och:foo"), + alarmEntityId("och:foo")) + .addEqualityGroup(alarmEntityId("och:bar")) + .testEquals(); + + } + + @Test + public void validSchemaPermitted() { + alarmEntityId("none:foo"); + alarmEntityId("port:foo"); + alarmEntityId("och:foo"); + alarmEntityId("other:foo"); + + } + + @Test(expected = IllegalArgumentException.class) + public void verifyUnexpectedSchemaRejected() { + alarmEntityId("junk:foo"); + } + + @Test(expected = IllegalArgumentException.class) + public void verifyCorruptSchemaRejected() { + alarmEntityId("other:"); + } + +} diff --git a/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmIdTest.java b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmIdTest.java new file mode 100644 index 00000000..74453a42 --- /dev/null +++ b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/AlarmIdTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; + +/** + * This class tests the immutability, equality, and non-equality of + * {@link AlarmId}. + */ +public class AlarmIdTest { + private static final long ID_A = 1L; + private static final long ID_B = 2L; + private static final long ID_Z = 987654321L; + + /** + * Tests the immutability of {@link AlarmId}. + */ + @Test + public void intentIdFollowsGuidelineForImmutableObject() { + assertThatClassIsImmutable(AlarmId.class); + } + + /** + * Tests equality of {@link AlarmId}. + */ + @Test + public void testEquality() { + final AlarmId id1 = new AlarmId(ID_A); + final AlarmId id2 = new AlarmId(ID_A); + + assertThat(id1, is(id2)); + } + + + /** + * Tests non-equality of {@link AlarmId}. + */ + @Test + public void testNonEquality() { + final AlarmId id1 = new AlarmId(ID_A); + final AlarmId id2 = new AlarmId(ID_B); + + assertThat(id1, is(not(id2))); + } + + @Test + public void valueOf() { + final AlarmId id = new AlarmId(0xdeadbeefL); + assertEquals("incorrect valueOf", id, AlarmId.valueOf(0xdeadbeefL)); + } + + /** + * Tests the equals(), hashCode() and toString() methods. + */ + @Test + public void testEquals() { + final AlarmId id1 = new AlarmId(11111L); + final AlarmId sameAsId1 = new AlarmId(11111L); + final AlarmId id2 = new AlarmId(22222L); + + new EqualsTester() + .addEqualityGroup(id1, sameAsId1) + .addEqualityGroup(id2) + .testEquals(); + } + + /** + * Tests construction of an AlarmId object. + */ + @Test + public void testConstruction() { + final AlarmId id1 = new AlarmId(ID_Z); + assertEquals(id1.fingerprint(), ID_Z); + + // No default constructor so no need to test it ! + } +} diff --git a/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarmTest.java b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarmTest.java new file mode 100644 index 00000000..199ed0d9 --- /dev/null +++ b/framework/src/onos/incubator/api/src/test/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarmTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.faultmanagement.alarm; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; +import org.onosproject.net.DeviceId; + +public class DefaultAlarmTest { + + @Test + public void testImmutability() { + assertThatClassIsImmutable(DefaultAlarm.class); + } + + /** + * Checks the construction of a DefaultAlarm object. + */ + @Test + public void testConstruction() { + final String nameValue = "name3"; + final DefaultAlarm a = new DefaultAlarm.Builder(AlarmId.valueOf(4), + DeviceId.NONE, nameValue, Alarm.SeverityLevel.CLEARED, 3).build(); + + assertThat(a, is(notNullValue())); + final DefaultAlarm b = new DefaultAlarm.Builder(a).build(); + + assertEquals(a, b); + } +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java index 0439d038..bbd96de0 100644 --- a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java @@ -18,6 +18,7 @@ package org.onosproject.incubator.net.intf.impl; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -39,9 +40,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; +import java.util.Iterator; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toSet; @@ -145,7 +148,7 @@ public class InterfaceManager implements InterfaceService, private void updateInterfaces(InterfaceConfig intfConfig) { try { - interfaces.put(intfConfig.subject(), intfConfig.getInterfaces()); + interfaces.put(intfConfig.subject(), Sets.newHashSet(intfConfig.getInterfaces())); } catch (ConfigException e) { log.error("Error in interface config", e); } @@ -157,18 +160,7 @@ public class InterfaceManager implements InterfaceService, @Override public void add(Interface intf) { - if (interfaces.containsKey(intf.connectPoint())) { - boolean conflict = interfaces.get(intf.connectPoint()).stream() - .filter(i -> i.connectPoint().equals(intf.connectPoint())) - .filter(i -> i.mac().equals(intf.mac())) - .filter(i -> i.vlan().equals(intf.vlan())) - .findAny().isPresent(); - - if (conflict) { - log.error("Can't add interface because it conflicts with existing config"); - return; - } - } + addInternal(intf); InterfaceConfig config = configService.addConfig(intf.connectPoint(), CONFIG_CLASS); @@ -178,29 +170,72 @@ public class InterfaceManager implements InterfaceService, configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node()); } + private void addInternal(Interface intf) { + interfaces.compute(intf.connectPoint(), (cp, current) -> { + if (current == null) { + return Sets.newHashSet(intf); + } + + Iterator it = current.iterator(); + while (it.hasNext()) { + Interface i = it.next(); + if (i.name().equals(intf.name())) { + it.remove(); + break; + } + } + + current.add(intf); + return current; + }); + } + @Override - public void remove(ConnectPoint connectPoint, VlanId vlanId) { - Optional intf = interfaces.get(connectPoint).stream() - .filter(i -> i.vlan().equals(vlanId)) - .findAny(); - - if (!intf.isPresent()) { - log.error("Can't find interface {}/{} to remove", connectPoint, vlanId); - return; - } + public boolean remove(ConnectPoint connectPoint, String name) { + boolean success = removeInternal(name, connectPoint); - InterfaceConfig config = configService.addConfig(intf.get().connectPoint(), CONFIG_CLASS); - config.removeInterface(intf.get()); + InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS); + config.removeInterface(name); try { if (config.getInterfaces().isEmpty()) { configService.removeConfig(connectPoint, CONFIG_CLASS); } else { - configService.applyConfig(intf.get().connectPoint(), CONFIG_CLASS, config.node()); + configService.applyConfig(connectPoint, CONFIG_CLASS, config.node()); } } catch (ConfigException e) { log.error("Error reading interfaces JSON", e); } + + return success; + } + + public boolean removeInternal(String name, ConnectPoint connectPoint) { + AtomicBoolean removed = new AtomicBoolean(false); + + interfaces.compute(connectPoint, (cp, current) -> { + if (current == null) { + return null; + } + + Iterator it = current.iterator(); + while (it.hasNext()) { + Interface i = it.next(); + if (i.name().equals(name)) { + it.remove(); + removed.set(true); + break; + } + } + + if (current.isEmpty()) { + return null; + } else { + return current; + } + }); + + return removed.get(); } /** diff --git a/framework/src/onos/incubator/rpc-grpc/pom.xml b/framework/src/onos/incubator/rpc-grpc/pom.xml index f528ca53..367b50a2 100644 --- a/framework/src/onos/incubator/rpc-grpc/pom.xml +++ b/framework/src/onos/incubator/rpc-grpc/pom.xml @@ -122,6 +122,18 @@ + + + org.apache.maven.plugins + maven-javadoc-plugin + + ${basedir}/src/main/java/ + org.onosproject.incubator.rpc.grpc + + + org.apache.felix maven-bundle-plugin @@ -224,8 +236,7 @@ - - + diff --git a/framework/src/onos/pom.xml b/framework/src/onos/pom.xml index 4d49abaa..c72a4594 100644 --- a/framework/src/onos/pom.xml +++ b/framework/src/onos/pom.xml @@ -39,16 +39,12 @@ Open Network Operating System root project - tools/package/maven-plugin utils core web cli protocols - - bgp - providers drivers @@ -58,7 +54,6 @@ tools/package/archetypes tools/package/branding - tools/build/conf http://onosproject.org/ @@ -79,10 +74,11 @@ UTF-8 - 1.1-SNAPSHOT + 1.1 4.0.23.Final 0.5.0.onos - 0.9.0.onos + + 0.9.2.onos-SNAPSHOT 3.0.3 1.19 @@ -94,6 +90,14 @@ + + + + snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + @@ -558,7 +562,7 @@ - rsModel + onos.rsModel m Json model for REST api: @@ -650,7 +654,7 @@ org.onosproject onos-maven-plugin - 1.6-SNAPSHOT + 1.6 cfg @@ -694,12 +698,6 @@ onos-build-conf ${onos-build-conf.version} - - - com.puppycrawl.tools - checkstyle - 5.9 - diff --git a/framework/src/onos/protocols/bgp/api/pom.xml b/framework/src/onos/protocols/bgp/api/pom.xml new file mode 100755 index 00000000..2390e5f6 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/pom.xml @@ -0,0 +1,90 @@ + + + + 4.0.0 + + + org.onosproject + onos-bgp + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-bgp-api + bundle + + ONOS BGP controller subsystem API + + + + org.onosproject + onos-bgpio + + + io.netty + netty + + + org.onosproject + onos-api + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + + io.netty:netty + com.google.guava:guava + org.slf4j:slfj-api + ch.qos.logback:logback-core + ch.qos.logback:logback-classic + com.google.code.findbugs:annotations + + + + + + package + + shade + + + + + + org.apache.felix + maven-bundle-plugin + + + + org.onosproject.bgp.*,org.onosproject.bgpio.*,org.onosproject.bgp.controller + + + + + + + + diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java new file mode 100755 index 00000000..6f64d2bb --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java @@ -0,0 +1,297 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller; + +import java.util.TreeMap; + +/** + * Abstraction of an BGP configuration. Manages the BGP configuration from CLI to the BGP controller. + */ +public interface BgpCfg { + + enum State { + /** + * Signifies that its just created. + */ + INIT, + + /** + * Signifies that only IP Address is configured. + */ + IP_CONFIGURED, + + /** + * Signifies that only Autonomous System is configured. + */ + AS_CONFIGURED, + + /** + * Signifies that both IP and Autonomous System is configured. + */ + IP_AS_CONFIGURED + } + + /** + * Returns the status of the configuration based on this state certain operations like connection is handled. + * + * @return State of the configuration + */ + State getState(); + + /** + * To set the current state of the configuration. + * + * @param state Configuration State enum + */ + void setState(State state); + + /** + * Get the status of the link state support for this BGP speaker. + * + * @return true if the link state is supported else false + */ + boolean getLsCapability(); + + /** + * Set the link state support to this BGP speaker. + * + * @param lscapability true value if link state is supported else false + */ + void setLsCapability(boolean lscapability); + + /** + * Get the status of the 32 bit AS support for this BGP speaker. + * + * @return true if the 32 bit AS number is supported else false + */ + boolean getLargeASCapability(); + + /** + * Set the 32 bit AS support capability to this BGP speaker. + * + * @param largeAs true value if the 32 bit AS is supported else false + */ + void setLargeASCapability(boolean largeAs); + + /** + * Set the AS number to which this BGP speaker belongs. + * + * @param localAs 16 or 32 bit AS number, length is dependent on the capability + */ + void setAsNumber(int localAs); + + /** + * Get the AS number to which this BGP speaker belongs. + * + * @return 16 or 32 bit AS number, length is dependent on the capability + */ + int getAsNumber(); + + /** + * Get the connection retry count number. + * + * @return connection retry count if there is a connection error + */ + int getMaxConnRetryCount(); + + /** + * Set the connection retry count. + * + * @param retryCount number of times to try to connect if there is any error + */ + void setMaxConnRetryCout(int retryCount); + + /** + * Get the connection retry time in seconds. + * + * @return connection retry time in seconds + */ + int getMaxConnRetryTime(); + + /** + * Set the connection retry time in seconds. + * + * @param retryTime connection retry times in seconds + */ + void setMaxConnRetryTime(int retryTime); + + /** + * Set the keep alive timer for the connection. + * + * @param holdTime connection hold timer in seconds + */ + void setHoldTime(short holdTime); + + /** + * Returns the connection hold timer in seconds. + * + * @return connection hold timer in seconds + */ + short getHoldTime(); + + /** + * Returns the maximum number of session supported. + * + * @return maximum number of session supported + */ + int getMaxSession(); + + /** + * Set the maximum number of sessions to support. + * + * @param maxsession maximum number of session + */ + void setMaxSession(int maxsession); + + /** + * Returns the Router ID of this BGP speaker. + * + * @return IP address in string format + */ + String getRouterId(); + + /** + * Set the Router ID of this BGP speaker. + * + * @param routerid IP address in string format + */ + void setRouterId(String routerid); + + /** + * Add the BGP peer IP address and the AS number to which it belongs. + * + * @param routerid IP address in string format + * @param remoteAs AS number to which it belongs + * + * @return true if added successfully else false + */ + boolean addPeer(String routerid, int remoteAs); + + /** + * Add the BGP peer IP address and the keep alive time. + * + * @param routerid IP address in string format + * @param holdTime keep alive time for the connection + * + * @return true if added successfully else false + */ + boolean addPeer(String routerid, short holdTime); + + /** + * Add the BGP peer IP address, the AS number to which it belongs and keep alive time. + * + * @param routerid IP address in string format + * @param remoteAs AS number to which it belongs + * @param holdTime keep alive time for the connection + * + * @return true if added successfully else false + */ + boolean addPeer(String routerid, int remoteAs, short holdTime); + + /** + * Remove the BGP peer with this IP address. + * + * @param routerid router IP address + * + * @return true if removed successfully else false + */ + boolean removePeer(String routerid); + + /** + * Connect to BGP peer with this IP address. + * + * @param routerid router IP address + * + * @return true of the configuration is found and able to connect else false + */ + boolean connectPeer(String routerid); + + /** + * Disconnect this BGP peer with this IP address. + * + * @param routerid router IP address in string format + * + * @return true if the configuration is found and able to disconnect else false + */ + boolean disconnectPeer(String routerid); + + /** + * Returns the peer tree information. + * + * @return return the tree map with IP as key and BGPPeerCfg as object + */ + TreeMap displayPeers(); + + /** + * Return the BGP Peer information with this matching IP. + * + * @param routerid router IP address in string format + * + * @return BGPPeerCfg object + */ + BgpPeerCfg displayPeers(String routerid); + + /** + * Check if this BGP peer is configured. + * + * @param routerid router IP address in string format + * + * @return true if configured exists else false + */ + boolean isPeerConfigured(String routerid); + + /** + * Check if this BGP speaker is having connection with the peer. + * + * @param routerid router IP address in string format + * + * @return true if the connection exists else false + */ + boolean isPeerConnected(String routerid); + + /** + * Return the peer tree map. + * + * @return return the tree map with IP as key and BGPPeerCfg as object + */ + TreeMap getPeerTree(); + + /** + * Set the current connection state information. + * + * @param routerid router IP address in string format + * @param state state information + */ + void setPeerConnState(String routerid, BgpPeerCfg.State state); + + /** + * Check if the peer can be connected or not. + * + * @param routerid router IP address in string format + * + * @return true if the peer can be connected else false + */ + boolean isPeerConnectable(String routerid); + + /** + * Get the current peer connection state information. + * + * @param routerid router IP address in string format + * + * @return state information + */ + BgpPeerCfg.State getPeerConnState(String routerid); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java new file mode 100755 index 00000000..8f33ee87 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpConnectPeer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller; + +/** + * Abstraction of an BGP connect peer, initiate remote connection to BGP peer on configuration. + */ +public interface BgpConnectPeer { + /** + * Initiate bgp peer connection. + */ + void connectPeer(); + + /** + * End bgp peer connection. + */ + void disconnectPeer(); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java new file mode 100755 index 00000000..0930e8e8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java @@ -0,0 +1,131 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller; + +import java.util.Map; +import java.util.Set; + +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessage; + +/** + * Abstraction of an BGP controller. Serves as a one stop shop for obtaining BGP devices and (un)register listeners on + * bgp events + */ +public interface BgpController { + + /** + * Returns list of bgp peers connected to this BGP controller. + * + * @return Iterable of BGPPeer elements + */ + Iterable getPeers(); + + /** + * Returns the actual bgp peer for the given ip address. + * + * @param bgpId the id of the bgp peer to fetch + * @return the interface to this bgp peer + */ + BgpPeer getPeer(BgpId bgpId); + + /** + * Register a listener for BGP message events. + * + * @param listener the listener to notify + */ + void addListener(BgpNodeListener listener); + + /** + * Unregister a listener. + * + * @param listener the listener to unregister + */ + void removeListener(BgpNodeListener listener); + + /** + * Send a message to a particular bgp peer. + * + * @param bgpId the id of the peer to send message. + * @param msg the message to send + */ + void writeMsg(BgpId bgpId, BgpMessage msg); + + /** + * Process a message and notify the appropriate listeners. + * + * @param bgpId id of the peer the message arrived on + * @param msg the message to process. + * @throws BgpParseException on data processing error + */ + void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException; + + /** + * Close all connected BGP peers. + * + */ + void closeConnectedPeers(); + + /** + * Get the BGPConfig class to the caller. + * + * @return configuration object + */ + BgpCfg getConfig(); + + /** + * Get the BGP connected peers to this controller. + * + * @return the integer number + */ + int connectedPeerCount(); + + /** + * Return BGP local RIB instance with VPN. + * + * @return BGPLocalRibImpl local RIB with VPN + */ + BgpLocalRib bgpLocalRibVpn(); + + /** + * Return BGP local RIB instance. + * + * @return BGPLocalRibImpl local RIB + */ + BgpLocalRib bgpLocalRib(); + + /** + * Return BGP peer manager. + * + * @return BGPPeerManager peer manager instance + */ + BgpPeerManager peerManager(); + + /** + * Return BGP connected peers. + * + * @return connectedPeers connected peers + */ + Map connectedPeers(); + + /** + * Return BGP node listener. + * + * @return node listener + */ + Set listener(); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java new file mode 100755 index 00000000..ed04dc94 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpDpid.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The class representing a network bgp device id. This class is immutable. + */ +public final class BgpDpid { + private static final Logger log = LoggerFactory.getLogger(BgpDpid.class); + + private static final String SCHEME = "bgp"; + private static final long UNKNOWN = 0; + private StringBuilder stringBuilder; + public static final int NODE_DESCRIPTOR_LOCAL = 1; + public static final int NODE_DESCRIPTOR_REMOTE = 2; + + /** + * Initialize bgp id to generate URI. + * + * @param linkNlri node Nlri. + * @param nodeDescriptorType node descriptor type, local/remote + */ + public BgpDpid(final BgpLinkLsNlriVer4 linkNlri, int nodeDescriptorType) { + this.stringBuilder = new StringBuilder("bgpls://"); + + if (linkNlri.getRouteDistinguisher() != null) { + this.stringBuilder.append(linkNlri.getRouteDistinguisher().getRouteDistinguisher()).append(':'); + } + + try { + this.stringBuilder.append(linkNlri.getProtocolId()).append(':').append(linkNlri.getIdentifier()) + .append('/'); + + if (nodeDescriptorType == NODE_DESCRIPTOR_LOCAL) { + add(linkNlri.localNodeDescriptors()); + } else if (nodeDescriptorType == NODE_DESCRIPTOR_REMOTE) { + add(linkNlri.remoteNodeDescriptors()); + } + } catch (BgpParseException e) { + log.info("Exception BgpId string: " + e.toString()); + } + + } + + /** + * Initialize bgp id to generate URI. + * + * @param nodeNlri node Nlri. + */ + public BgpDpid(final BgpNodeLSNlriVer4 nodeNlri) { + this.stringBuilder = new StringBuilder("bgpls://"); + + if (nodeNlri.getRouteDistinguisher() != null) { + this.stringBuilder.append(nodeNlri.getRouteDistinguisher().getRouteDistinguisher()).append(':'); + } + + try { + + this.stringBuilder.append(nodeNlri.getProtocolId()).append(':').append(nodeNlri.getIdentifier()) + .append('/'); + + add(nodeNlri.getLocalNodeDescriptors()); + + } catch (BgpParseException e) { + log.info("Exception node string: " + e.toString()); + } + } + + BgpDpid add(final Object value) { + if (value != null) { + this.stringBuilder.append('&').append('=').append(value.toString()); + } + return this; + } + + @Override + public String toString() { + return this.stringBuilder.toString(); + } + + /** + * Produces bgp URI. + * + * @param value string to get URI + * @return bgp URI, otherwise null + */ + public static URI uri(String value) { + try { + return new URI(SCHEME, value, null); + } catch (URISyntaxException e) { + log.info("Exception BgpId URI: " + e.toString()); + } + return null; + } + + /** + * Returns bgpDpid created from the given device URI. + * + * @param uri device URI + * @return object of BgpDpid + */ + public static BgpDpid bgpDpid(URI uri) { + checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme"); + + // TODO: return BgpDpid generated from uri + return null; + } +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java new file mode 100755 index 00000000..7a6c625d --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpId.java @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller; + +import org.onlab.packet.IpAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * The class representing a network peer bgp ip. + * This class is immutable. + */ +public final class BgpId { + + private static final String SCHEME = "bgp"; + private static final long UNKNOWN = 0; + private final IpAddress ipAddress; + + /** + * Private constructor. + */ + private BgpId(IpAddress ipAddress) { + this.ipAddress = ipAddress; + } + + /** + * Create a BGPId from ip address. + * + * @param ipAddress IP address + * @return object of BGPId + */ + public static BgpId bgpId(IpAddress ipAddress) { + return new BgpId(ipAddress); + } + + /** + * Returns the ip address. + * + * @return ipAddress + */ + public IpAddress ipAddress() { + return ipAddress; + } + + /** + * Convert the BGPId value to a ':' separated hexadecimal string. + * + * @return the BGPId value as a ':' separated hexadecimal string. + */ + @Override + public String toString() { + return ipAddress.toString(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof BgpId)) { + return false; + } + + BgpId otherBGPid = (BgpId) other; + return Objects.equals(ipAddress, otherBGPid.ipAddress); + } + + @Override + public int hashCode() { + return Objects.hash(ipAddress); + } + + /** + * Returns BGPId created from the given device URI. + * + * @param uri device URI + * @return object of BGPId + */ + public static BgpId bgpId(URI uri) { + checkArgument(uri.getScheme().equals(SCHEME), "Unsupported URI scheme"); + return new BgpId(IpAddress.valueOf(uri.getSchemeSpecificPart())); + } + + /** + * Produces device URI from the given DPID. + * + * @param bgpId device bgpId + * @return device URI + */ + public static URI uri(BgpId bgpId) { + return uri(bgpId.ipAddress()); + } + + /** + * Produces device URI from the given DPID long. + * + * @param ipAddress device ip address + * @return device URI + */ + public static URI uri(IpAddress ipAddress) { + try { + return new URI(SCHEME, ipAddress.toString(), null); + } catch (URISyntaxException e) { + return null; + } + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java new file mode 100755 index 00000000..8b34e314 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLinkListener.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller; + +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; + +/** + * Allows for providers interested in Link events to be notified. + */ +public interface BgpLinkListener { + + /** + * Notify that got a packet of link from network and need do processing. + * + * @param linkNlri bgp link + */ + void addLink(BgpLinkLsNlriVer4 linkNlri); + + /** + * Notify that got a packet of link from network and need do processing. + * + * @param linkNlri bgp link + */ + void deleteLink(BgpLinkLsNlriVer4 linkNlri); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java new file mode 100755 index 00000000..636c1c85 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpLocalRib.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller; + +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.types.RouteDistinguisher; + +/** + * Abstraction of BGP local RIB. + */ +public interface BgpLocalRib { + + /** + * Add NLRI to local RIB. + * + * @param sessionInfo session info + * @param nlri network layer reach info + * @param details nlri details + */ + void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details); + + /** + * Removes NLRI identifier if it exists. + * + * @param nlri info + */ + void delete(BgpLSNlri nlri); + + /** + * Update NLRI identifier mapped with route distinguisher if it exists in tree otherwise add NLRI infomation mapped + * to respective route distinguisher. + * + * @param sessionInfo BGP session info + * @param nlri info + * @param details has pathattribute, protocol id and identifier + * @param routeDistinguisher unique for each VPN + */ + void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details, + RouteDistinguisher routeDistinguisher); + + /** + * Removes VPN NLRI identifier mapped to route distinguisher if it exists. + * + * @param nlri info + * @param routeDistinguisher unique for each VPN + */ + void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java new file mode 100755 index 00000000..726d931b --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpNodeListener.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller; + +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; + +/** + * Allows for providers interested in node events to be notified. + */ +public interface BgpNodeListener { + + /** + * Notifies that the node was added. + * + * @param nodeNlri node rechability info + */ + void addNode(BgpNodeLSNlriVer4 nodeNlri); + + /** + * Notifies that the node was removed. + * + * @param nodeNlri node rechability info + */ + void deleteNode(BgpNodeLSNlriVer4 nodeNlri); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java new file mode 100755 index 00000000..8fd3c688 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPacketStats.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller; + +/** + * A representation of a packet context which allows any provider to view a packet in event, but may block the response + * to the event if blocked has been called. This packet context can be used to react to the packet in event with a + * packet out. + */ +public interface BgpPacketStats { + /** + * Returns the count for no of packets sent out. + * + * @return int value of no of packets sent + */ + int outPacketCount(); + + /** + * Returns the count for no of packets received. + * + * @return int value of no of packets sent + */ + int inPacketCount(); + + /** + * Returns the count for no of wrong packets received. + * + * @return int value of no of wrong packets received + */ + int wrongPacketCount(); + + /** + * Returns the time. + * + * @return the time + */ + long getTime(); +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java new file mode 100644 index 00000000..9f4d47da --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java @@ -0,0 +1,113 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller; +import java.util.List; +import org.jboss.netty.channel.Channel; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.types.BgpValueType; + +/** + * Represents the peer side of an BGP peer. + * + */ +public interface BgpPeer { + + /** + * Sets the associated Netty channel for this bgp peer. + * + * @param channel the Netty channel + */ + void setChannel(Channel channel); + + /** + * Gets the associated Netty channel handler for this bgp peer. + * + * @return Channel channel connected. + */ + Channel getChannel(); + + /** + * Sets whether the bgp peer is connected. + * + * @param connected whether the bgp peer is connected + */ + void setConnected(boolean connected); + + /** + * Checks whether the handshake is complete. + * + * @return true is finished, false if not. + */ + boolean isHandshakeComplete(); + + /** + * Writes the message to the peer. + * + * @param msg the message to write + */ + void sendMessage(BgpMessage msg); + + /** + * Writes the BGPMessage list to the peer. + * + * @param msgs the messages to be written + */ + void sendMessage(List msgs); + + /** + * Provides the factory for BGP version. + * + * @return BGP version specific factory. + */ + BgpFactory factory(); + + /** + * Checks if the bgp peer is still connected. + * + * @return whether the bgp peer is still connected + */ + boolean isConnected(); + + /** + * Disconnects the bgp peer by closing the TCP connection. Results in a call to the channel handler's + * channelDisconnected method for cleanup + */ + void disconnectPeer(); + + /** + * Identifies the channel used to communicate with the bgp peer. + * + * @return string representation of the connection to the peer + */ + String channelId(); + + /** + * Maintaining Adj-RIB-In separately for each peer. + * + * @param pathAttr list of Bgp path attributes + * @throws BgpParseException while building Adj-Rib-In + */ + void buildAdjRibIn(List pathAttr) throws BgpParseException; + + /** + * Return the BGP session info. + * + * @return sessionInfo bgp session info + */ + BgpSessionInfo sessionInfo(); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java new file mode 100755 index 00000000..2fb970fc --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerCfg.java @@ -0,0 +1,180 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller; + +/** + * BGP Peer configuration information. + */ +public interface BgpPeerCfg { + + enum State { + + /** + * Signifies that peer connection is idle. + */ + IDLE, + + /** + * Signifies that connection is initiated. + */ + CONNECT, + + /** + * Signifies that state is active and connection can be established. + */ + ACTIVE, + + /** + * Signifies that open is sent and anticipating reply. + */ + OPENSENT, + + /** + * Signifies that peer sent the open message as reply. + */ + OPENCONFIRM, + + /** + * Signifies that all the negotiation is successful and ready to exchange other messages. + */ + ESTABLISHED, + + /** + * Signifies that invalid state. + */ + INVALID + } + + /** + * Returns the connection State information of the peer. + * + * @return + * enum state is returned + */ + State getState(); + + /** + * Set the connection state information of the peer. + * + * @param state + * enum state + */ + void setState(State state); + + /** + * Returns the connection is initiated from us or not. + * + * @return + * true if the connection is initiated by this peer, false if it has been received. + */ + boolean getSelfInnitConnection(); + + /** + * Set the connection is initiated from us or not. + * + * @param selfInit + * true if the connection is initiated by this peer, false if it has been received. + */ + void setSelfInnitConnection(boolean selfInit); + + /** + * Returns the AS number to which this peer belongs. + * + * @return + * AS number + */ + int getAsNumber(); + + /** + * Set the AS number to which this peer belongs. + * + * @param asNumber + * AS number + */ + void setAsNumber(int asNumber); + + /** + * Get the keep alive timer value configured. + * + * @return + * keep alive timer value in seconds + */ + short getHoldtime(); + + /** + * Set the keep alive timer value. + * + * @param holdTime + * keep alive timer value in seconds + */ + void setHoldtime(short holdTime); + + /** + * Return the connection type eBGP or iBGP. + * + * @return + * true if iBGP, false if it is eBGP + */ + boolean getIsIBgp(); + + /** + * Set the connection type eBGP or iBGP. + * + * @param isIBgp + * true if iBGP, false if it is eBGP + */ + void setIsIBgp(boolean isIBgp); + + /** + * Return the peer router IP address. + * + * @return + * IP address in string format + */ + String getPeerRouterId(); + + /** + * Set the peer router IP address. + * + * @param peerId + * IP address in string format + */ + void setPeerRouterId(String peerId); + + /** + * Set the peer router IP address and AS number. + * + * @param peerId + * IP address in string format + * @param asNumber + * AS number + */ + void setPeerRouterId(String peerId, int asNumber); + + /** + * Set the peer connect instance. + * + * @param connectpeer connect peer instance + */ + void setConnectPeer(BgpConnectPeer connectpeer); + + /** + * Get the peer connect instance. + * + * @return peer connect instance + */ + BgpConnectPeer connectPeer(); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java new file mode 100755 index 00000000..895cc145 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller; + +/** + * Responsible for keeping track of the current set BGPLS peers connected to the system. + * + */ +public interface BgpPeerManager { + + /** + * Add connected peer. + * + * @param bgpId BGP ID to add + * @param bgpPeer BGp peer instance + * + * @return false if peer already exist, otherwise true + */ + public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer); + + /** + * Validate wheather peer is connected. + * + * @param bgpId BGP ID to validate + * + * @return true if peer exist, otherwise false + */ + public boolean isPeerConnected(BgpId bgpId); + + /** + * Remove connected peer. + * + * @param bgpId BGP ID + */ + public void removeConnectedPeer(BgpId bgpId); + + /** + * Gets connected peer. + * + * @param bgpId BGP ID + * @return BGPPeer the connected peer, otherwise null + */ + public BgpPeer getPeer(BgpId bgpId); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java new file mode 100755 index 00000000..a21a23d2 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpSessionInfo.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller; + +import org.onosproject.bgpio.protocol.BgpVersion; + +/** + * Abstraction of an BGP session info. Maintian session parameters obtained during session creation. + */ +public interface BgpSessionInfo { + /** + * Gets the bgp session type iBGP/eBGP. + * + * @return isiBGPSession, true if session is of type internal, otherwise false. + */ + boolean isIbgpSession(); + + /** + * Gets the negotiated hold time for the session. + * + * @return negotiated hold time. + */ + short negotiatedholdTime(); + + /** + * Gets the BGP ID of BGP peer. + * + * @return bgp ID. + */ + BgpId remoteBgpId(); + + /** + * Gets the BGP version of peer. + * + * @return bgp version. + */ + BgpVersion remoteBgpVersion(); + + /** + * Gets the BGP remote bgp AS number. + * + * @return remoteBgpASNum peer AS number. + */ + long remoteBgpASNum(); + + /** + * Gets the BGP peer hold time. + * + * @return bgp hold time. + */ + short remoteBgpHoldTime(); + + /** + * Gets the BGP version for this bgp peer. + * + * @return bgp identifier. + */ + int remoteBgpIdentifier(); +} diff --git a/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java new file mode 100755 index 00000000..4dd775b8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * BGP controller API. + */ +package org.onosproject.bgp.controller; diff --git a/framework/src/onos/protocols/bgp/bgpio/pom.xml b/framework/src/onos/protocols/bgp/bgpio/pom.xml new file mode 100755 index 00000000..5d67f18c --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/pom.xml @@ -0,0 +1,76 @@ + + + + 4.0.0 + + + org.onosproject + onos-bgp + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-bgpio + bundle + + ONOS BGPio Protocol subsystem + + + + org.onosproject + onos-api + + + org.onosproject + onlab-osgi + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + + org.osgi + org.osgi.core + + + org.apache.karaf.shell + org.apache.karaf.shell.console + + + org.apache.felix + org.apache.felix.scr.annotations + + + + + + + org.apache.felix + maven-bundle-plugin + + + + + diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java new file mode 100755 index 00000000..d0890320 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/BgpParseException.java @@ -0,0 +1,106 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.exceptions; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * Custom Exception for BGP IO. + */ +public class BgpParseException extends Exception { + + private static final long serialVersionUID = 1L; + private byte errorCode; + private byte errorSubCode; + private ChannelBuffer data; + + /** + * Default constructor to create a new exception. + */ + public BgpParseException() { + super(); + } + + /** + * Constructor to create exception from message and cause. + * + * @param message the detail of exception in string + * @param cause underlying cause of the error + */ + public BgpParseException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * Constructor to create exception from message. + * + * @param message the detail of exception in string + */ + public BgpParseException(final String message) { + super(message); + } + + /** + * Constructor to create exception from cause. + * + * @param cause underlying cause of the error + */ + public BgpParseException(final Throwable cause) { + super(cause); + } + + /** + * Constructor to create exception from error code and error subcode. + * + * @param errorCode error code of BGP message + * @param errorSubCode error subcode of BGP message + * @param data error data of BGP message + */ + public BgpParseException(final byte errorCode, final byte errorSubCode, final ChannelBuffer data) { + super(); + this.errorCode = errorCode; + this.errorSubCode = errorSubCode; + this.data = data; + } + + /** + * Returns errorcode for this exception. + * + * @return errorcode for this exception + */ + public byte getErrorCode() { + return this.errorCode; + } + + /** + * Returns error Subcode for this exception. + * + * @return error Subcode for this exception + */ + public byte getErrorSubCode() { + return this.errorSubCode; + } + + /** + * Returns error data for this exception. + * + * @return error data for this exception + */ + public ChannelBuffer getData() { + return this.data; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java new file mode 100755 index 00000000..78b28072 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/exceptions/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * BGP custom exceptions. + */ +package org.onosproject.bgpio.exceptions; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java new file mode 100755 index 00000000..eb18c7d1 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactories.java @@ -0,0 +1,82 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.ver4.BgpFactoryVer4; +import org.onosproject.bgpio.types.BgpHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstraction to provide the version for BGP. + */ +public final class BgpFactories { + + protected static final Logger log = LoggerFactory.getLogger(BgpFactories.class); + + private static final GenericReader GENERIC_READER = new GenericReader(); + + private BgpFactories() { + } + + /** + * Returns the instance of BGP Version. + * + * @param version BGP version + * @return BGP version + */ + public static BgpFactory getFactory(BgpVersion version) { + switch (version) { + case BGP_4: + return BgpFactoryVer4.INSTANCE; + default: + throw new IllegalArgumentException("[BgpFactory:]Unknown version: " + version); + } + } + + /** + * Reader class for reading BGP messages from channel buffer. + * + */ + private static class GenericReader implements BgpMessageReader { + + @Override + public BgpMessage readFrom(ChannelBuffer bb, BgpHeader bgpHeader) + throws BgpParseException { + BgpFactory factory; + + if (!bb.readable()) { + log.error("Empty message received"); + throw new BgpParseException("Empty message received"); + } + // TODO: Currently only BGP version 4 is supported + factory = org.onosproject.bgpio.protocol.ver4.BgpFactoryVer4.INSTANCE; + return factory.getReader().readFrom(bb, bgpHeader); + } + } + + /** + * Returns BGP messsage generic reader. + * + * @return bgp message generic reader + */ + public static BgpMessageReader getGenericReader() { + return GENERIC_READER; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java new file mode 100755 index 00000000..11a85ff8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +/** + * Abstraction of an message factory providing builder functions to BGP messages + * and objects. + * + */ +public interface BgpFactory { + + /** + * Gets the builder object for a open message. + * + * @return builder object for open message + */ + BgpOpenMsg.Builder openMessageBuilder(); + + /** + * Gets the builder object for a keepalive message. + * + * @return builder object for keepalive message + */ + BgpKeepaliveMsg.Builder keepaliveMessageBuilder(); + + /** + * Gets the builder object for a notification message. + * + * @return builder object for notification message. + */ + BgpNotificationMsg.Builder notificationMessageBuilder(); + + /** + * Gets the BGP message reader. + * + * @return BGP message reader + */ + BgpMessageReader getReader(); + + /** + * Returns BGP version. + * + * @return BGP version + */ + BgpVersion getVersion(); +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java new file mode 100644 index 00000000..0cb776a0 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsg.java @@ -0,0 +1,48 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.types.BgpHeader; + +/** + * Abstraction of an entity providing BGP Keepalive Message. + */ +public interface BgpKeepaliveMsg extends BgpMessage { + + @Override + BgpVersion getVersion(); + + @Override + BgpType getType(); + + @Override + void writeTo(ChannelBuffer channelBuffer); + + @Override + BgpHeader getHeader(); + + /** + * Builder interface with get and set functions to build Keepalive message. + */ + interface Builder extends BgpMessage.Builder { + @Override + BgpKeepaliveMsg build(); + + @Override + Builder setHeader(BgpHeader bgpMsgHeader); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java new file mode 100644 index 00000000..dd8857a7 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLSNlri.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.types.RouteDistinguisher; + +/** + * Abstraction of an entity providing BGP-LS NLRI. + */ +public interface BgpLSNlri { + /** + * Returns NlriType of BGP-LS NLRI. + * + * @return NlriType of BGP-LS NLRI + */ + NlriType getNlriType(); + + /** + * Returns Identifier in Nlri. + * + * @return Identifier in Nlri + */ + long getIdentifier(); + + /** + * Returns Protocol Id in Nlri. + * + * @return Protocol Id in Nlri + * @throws BgpParseException while getting protocol ID + */ + ProtocolType getProtocolId() throws BgpParseException; + + /** + * Returns Route distinguisher in Nlri. + * + * @return Route distinguisher in Nlri + */ + RouteDistinguisher getRouteDistinguisher(); +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java new file mode 100644 index 00000000..3924a13b --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpLinkLsNlri.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import java.util.List; + +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors; + +/** + * Abstraction of an entity providing BGP-LS Link NLRI. + */ +public interface BgpLinkLsNlri extends BgpLSNlri { + /** + * Returns local node descriptors. + * + * @return local node descriptors + */ + NodeDescriptors localNodeDescriptors(); + + /** + * Returns remote node descriptors. + * + * @return remote node descriptors + */ + NodeDescriptors remoteNodeDescriptors(); + + /** + * Returns link descriptors. + * + * @return link descriptors + */ + List linkDescriptors(); +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java new file mode 100644 index 00000000..f1e1b96f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessage.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; + +/** + * Abstraction of an entity providing BGP Messages. + */ +public interface BgpMessage extends Writeable { + /** + * Returns BGP Header of BGP Message. + * + * @return BGP Header of BGP Message + */ + BgpHeader getHeader(); + + /** + * Returns version of BGP Message. + * + * @return version of BGP Message + */ + BgpVersion getVersion(); + + /** + * Returns BGP Type of BGP Message. + * + * @return BGP Type of BGP Message + */ + BgpType getType(); + + @Override + void writeTo(ChannelBuffer cb) throws BgpParseException; + + /** + * Builder interface with get and set functions to build BGP Message. + */ + interface Builder { + /** + * Builds BGP Message. + * + * @return BGP Message + * @throws BgpParseException while building bgp message + */ + BgpMessage build() throws BgpParseException; + + /** + * Sets BgpHeader and return its builder. + * + * @param bgpMsgHeader BGP Message Header + * @return builder by setting BGP message header + */ + Builder setHeader(BgpHeader bgpMsgHeader); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java new file mode 100755 index 00000000..b8318b29 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageReader.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; + +/** + * Abstraction of an entity providing BGP Message Reader. + */ +public interface BgpMessageReader { + + /** + * Reads the Objects in the BGP Message and Returns BGP Message. + * + * @param cb Channel Buffer + * @param bgpHeader BGP message header + * @return BGP Message + * @throws BgpParseException while parsing BGP message. + */ + T readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException; +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java new file mode 100644 index 00000000..bb75b5ea --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpMessageWriter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; + +/** + * Abstraction of an entity providing BGP Message Writer. + */ +public interface BgpMessageWriter { + + /** + * Writes the Objects of the BGP Message into Channel Buffer. + * + * @param cb Channel Buffer + * @param message BGP Message + * @throws BgpParseException + * While writing message + */ + void write(ChannelBuffer cb, T message) throws BgpParseException; +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java new file mode 100644 index 00000000..13ef5cc5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNodeLSNlri.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; + +/** + * Abstraction of an entity providing BGP-LS Node NLRI. + */ +public interface BgpNodeLSNlri extends BgpLSNlri { + /** + * Returns local node descriptors. + * + * @return local node descriptors + */ + BgpNodeLSIdentifier getLocalNodeDescriptors(); +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java new file mode 100644 index 00000000..e3361aa7 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpNotificationMsg.java @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.onosproject.bgpio.exceptions.BgpParseException; + +/** + * Abstraction of an entity providing BGP notification message. + */ +public interface BgpNotificationMsg extends BgpMessage { + /** + * Returns errorCode in notification message. + * + * @return errorCode in notification message + */ + byte getErrorCode(); + + /** + * Returns error subCode in notification message. + * + * @return error subCode in notification message + */ + byte getErrorSubCode(); + + /** + * Returns error data in notification message. + * + * @return error data in notification message + */ + byte[] getData(); + + /** + * Builder interface with get and set functions to build notification message. + */ + public interface Builder extends BgpMessage.Builder { + + @Override + BgpNotificationMsg build() throws BgpParseException; + + /** + * Sets errorCode in notification message and return its builder. + * + * @param errorCode in notification message + * @return builder by setting errorCode in notification message + */ + Builder setErrorCode(byte errorCode); + + /** + * Sets error subCode in notification message and return its builder. + * + * @param errorSubCode in notification message + * @return builder by setting error subCode in notification message + */ + Builder setErrorSubCode(byte errorSubCode); + + /** + * Sets error data in notification message and return its builder. + * + * @param data in notification message + * @return builder by setting Data in notification message + */ + Builder setData(byte[] data); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java new file mode 100644 index 00000000..94ec2235 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java @@ -0,0 +1,127 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import java.util.LinkedList; + +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.types.BgpValueType; + +/** + * Abstraction of an entity providing BGP Open Message. + */ +public interface BgpOpenMsg extends BgpMessage { + + @Override + BgpHeader getHeader(); + + @Override + BgpVersion getVersion(); + + @Override + BgpType getType(); + + /** + * Returns hold time of Open Message. + * + * @return hold time of Open Message + */ + short getHoldTime(); + + /** + * Returns AS Number of Open Message. + * + * @return AS Number of Open Message + */ + short getAsNumber(); + + /** + * Returns BGP Identifier of Open Message. + * + * @return BGP Identifier of Open Message + */ + int getBgpId(); + + /** + * Returns capabilities of Open Message. + * + * @return capabilities of Open Message + */ + LinkedList getCapabilityTlv(); + + /** + * Builder interface with get and set functions to build Open message. + */ + interface Builder extends BgpMessage.Builder { + + @Override + BgpOpenMsg build() throws BgpParseException; + + /** + * Sets hold time in Open Message and return its builder. + * + * @param holdtime hold timer value in open message + * @return builder by setting hold time + */ + Builder setHoldTime(short holdtime); + + /** + * Sets AS number in Open Message and return its builder. + * + * @param asNumber as number in open message + * @return builder by setting asNumber + */ + Builder setAsNumber(short asNumber); + + /** + * Sets BGP Identifier in Open Message and return its builder. + * + * @param bgpId BGP Identifier in open message + * @return builder by setting BGP Identifier + */ + Builder setBgpId(int bgpId); + + /** + * Sets capabilities in Open Message and return its builder. + * + * @param capabilityTlv capabilities in open message + * @return builder by setting capabilities + */ + Builder setCapabilityTlv(LinkedList capabilityTlv); + + /** + * Sets isLargeAsCapabilityTlvSet and return its builder. + * + * @param isLargeAsCapabilitySet + * boolean value to know whether large AS capability is set or not + * @return builder by setting capabilities + */ + Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet); + + /** + * Sets isLsCapabilityTlvSet and return its builder. + * + * @param isLsCapabilitySet + * boolean value to know whether LS capability is set or not + * @return builder by setting capabilities + */ + Builder setLsCapabilityTlv(boolean isLsCapabilitySet); + + @Override + Builder setHeader(BgpHeader bgpMsgHeader); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java new file mode 100644 index 00000000..54bcdba3 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpPrefixLSNlri.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import java.util.List; + +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors; + +/** + * Abstraction of an entity providing BGP-LS Prefix NLRI. + */ +public interface BgpPrefixLSNlri extends BgpLSNlri { + /** + * Returns local node descriptors. + * + * @return local node descriptors + */ + NodeDescriptors getLocalNodeDescriptors(); + + /** + * Returns list of Prefix descriptor. + * + * @return list of Prefix descriptor + */ + List getPrefixdescriptor(); +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java new file mode 100755 index 00000000..b90721d5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpType.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +/** + * Enum to Provide the Different types of BGP messages. + */ +public enum BgpType { + + NONE(0), OPEN(1), UPDATE(2), NOTIFICATION(3), KEEP_ALIVE(4); + + int value; + + /** + * Assign value with the value val as the types of BGP message. + * + * @param val type of BGP message + */ + BgpType(int val) { + value = val; + } + + /** + * Returns value as type of BGP message. + * + * @return value type of BGP message + */ + public byte getType() { + return (byte) value; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java new file mode 100644 index 00000000..d79a4236 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java @@ -0,0 +1,48 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +import java.util.List; + +import org.onlab.packet.IpPrefix; +import org.onosproject.bgpio.protocol.ver4.BgpPathAttributes; + +/** + * Abstraction of an entity providing BGP Update Message. + */ +public interface BgpUpdateMsg extends BgpMessage { + /** + * Returns path attributes in BGP Update Message. + * + * @return path attributes in BGP Update Message + */ + BgpPathAttributes bgpPathAttributes(); + + /** + * Returns withdrawn Routes. + * + * @return withdrawn Routes + */ + List withdrawnRoutes(); + + /** + * Returns NLRI list of prefix. + * + * @return NLRI list of prefix + */ + List nlri(); +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java new file mode 100755 index 00000000..b1f037f4 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpVersion.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +/** + * Enum to provide BGP Message Version. + */ +public enum BgpVersion { + + BGP_4(4); + + public final int packetVersion; + + /** + * Assign BGP PacketVersion with specified packetVersion. + * + * @param packetVersion version of BGP + */ + BgpVersion(final int packetVersion) { + this.packetVersion = packetVersion; + } + + /** + * Returns Packet version of BGP Message. + * + * @return packetVersion + */ + public int getPacketVersion() { + return packetVersion; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java new file mode 100644 index 00000000..0e531d64 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/IGPRouterID.java @@ -0,0 +1,23 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +/** + * Provides Abstraction of IGP RouterID TLV. + */ +public interface IGPRouterID { +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java new file mode 100644 index 00000000..535ba71d --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/NlriType.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +/** + * Enum to Provide the Different BGP-LS NLRI types. + */ +public enum NlriType { + + NODE(1), LINK(2), PREFIX_IPV4(3), PREFIX_IPV6(4); + + int value; + + /** + * Assign value with the value as the LINK-STATE NLRI type. + * + * @param value LINK-STATE NLRI type + */ + NlriType(int value) { + this.value = value; + } + + /** + * Returns value as LINK-STATE NLRI type. + * + * @return value LINK-STATE NLRI type + */ + public byte getType() { + return (byte) value; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java new file mode 100755 index 00000000..1c6f7fc2 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/Writeable.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; + +/** + * Abstraction of an entity providing functionality to write byte streams of + * Messages to channel buffer. + */ +public interface Writeable { + + /** + * Writes byte streams of messages to channel buffer. + * + * @param cb channelBuffer + * @throws BgpParseException when error occurs while writing BGP message to channel buffer + */ + void writeTo(ChannelBuffer cb) throws BgpParseException; +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java new file mode 100644 index 00000000..a4360fdf --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLSIdentifier.java @@ -0,0 +1,297 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.IPv4AddressTlv; +import org.onosproject.bgpio.types.IPv6AddressTlv; +import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv; +import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.UnSupportedAttribute; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +/** + * Implementation of local node descriptors, remote node descriptors and link descriptors. + */ +public class BgpLinkLSIdentifier implements Comparable { + private static final Logger log = LoggerFactory.getLogger(BgpLinkLSIdentifier.class); + public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259; + public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260; + public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261; + public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262; + + private NodeDescriptors localNodeDescriptors; + private NodeDescriptors remoteNodeDescriptors; + private List linkDescriptor; + + /** + * Initialize fields. + */ + public BgpLinkLSIdentifier() { + this.localNodeDescriptors = null; + this.remoteNodeDescriptors = null; + this.linkDescriptor = null; + } + + /** + * Constructors to initialize parameters. + * + * @param localNodeDescriptors local node descriptors + * @param remoteNodeDescriptors remote node descriptors + * @param linkDescriptor link descriptors + */ + public BgpLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors, + LinkedList linkDescriptor) { + this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors); + this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors); + this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor); + } + + /** + * Reads channel buffer and parses link identifier. + * + * @param cb ChannelBuffer + * @param protocolId in linkstate nlri + * @return object of BGPLinkLSIdentifier + * @throws BgpParseException while parsing link identifier + */ + public static BgpLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BgpParseException { + //Parse local node descriptor + NodeDescriptors localNodeDescriptors = new NodeDescriptors(); + localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId); + + //Parse remote node descriptor + NodeDescriptors remoteNodeDescriptors = new NodeDescriptors(); + remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId); + + //Parse link descriptor + LinkedList linkDescriptor = new LinkedList<>(); + linkDescriptor = parseLinkDescriptors(cb); + return new BgpLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor); + } + + /** + * Parses Local/Remote node descriptors. + * + * @param cb ChannelBuffer + * @param desType descriptor type + * @param protocolId protocol identifier + * @return object of NodeDescriptors + * @throws BgpParseException while parsing Local/Remote node descriptors + */ + public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId) + throws BgpParseException { + log.debug("parse Node descriptors"); + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT)); + } + NodeDescriptors nodeIdentifier = new NodeDescriptors(); + ChannelBuffer tempCb = cb.readBytes(length); + + if (type == desType) { + nodeIdentifier = NodeDescriptors.read(tempCb, length, desType, protocolId); + } else { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); + } + return nodeIdentifier; + } + + /** + * Parses link descriptors. + * + * @param cb ChannelBuffer + * @return list of link descriptors + * @throws BgpParseException while parsing link descriptors + */ + public static LinkedList parseLinkDescriptors(ChannelBuffer cb) throws BgpParseException { + LinkedList linkDescriptor = new LinkedList<>(); + BgpValueType tlv = null; + int count = 0; + + while (cb.readableBytes() > 0) { + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN_AS_SHORT)); + } + ChannelBuffer tempCb = cb.readBytes(length); + switch (type) { + case LinkLocalRemoteIdentifiersTlv.TYPE: + tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb); + break; + case IPV4_INTERFACE_ADDRESS_TYPE: + tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE); + break; + case IPV4_NEIGHBOR_ADDRESS_TYPE: + tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE); + break; + case IPV6_INTERFACE_ADDRESS_TYPE: + tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE); + break; + case IPV6_NEIGHBOR_ADDRESS_TYPE: + tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE); + break; + case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: + tlv = BgpAttrNodeMultiTopologyId.read(tempCb); + count = count++; + //MultiTopologyId TLV cannot repeat more than once + if (count > 1) { + //length + 4 implies data contains type, length and value + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length + + Constants.TYPE_AND_LEN_AS_SHORT)); + } + break; + default: + UnSupportedAttribute.skipBytes(tempCb, length); + } + linkDescriptor.add(tlv); + } + return linkDescriptor; + } + + /** + * Returns local node descriptors. + * + * @return local node descriptors + */ + public NodeDescriptors localNodeDescriptors() { + return this.localNodeDescriptors; + } + + /** + * Returns remote node descriptors. + * + * @return remote node descriptors + */ + public NodeDescriptors remoteNodeDescriptors() { + return this.remoteNodeDescriptors; + } + + /** + * Returns link descriptors. + * + * @return link descriptors + */ + public List linkDescriptors() { + return this.linkDescriptor; + } + + @Override + public int hashCode() { + return Objects.hash(linkDescriptor, localNodeDescriptors, remoteNodeDescriptors); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof BgpLinkLSIdentifier) { + int countObjSubTlv = 0; + int countOtherSubTlv = 0; + boolean isCommonSubTlv = true; + BgpLinkLSIdentifier other = (BgpLinkLSIdentifier) obj; + Iterator objListIterator = other.linkDescriptor.iterator(); + countOtherSubTlv = other.linkDescriptor.size(); + countObjSubTlv = linkDescriptor.size(); + if (countObjSubTlv != countOtherSubTlv) { + return false; + } else { + while (objListIterator.hasNext() && isCommonSubTlv) { + BgpValueType subTlv = objListIterator.next(); + if (linkDescriptor.contains(subTlv) && other.linkDescriptor.contains(subTlv)) { + isCommonSubTlv = Objects.equals(linkDescriptor.get(linkDescriptor.indexOf(subTlv)), + other.linkDescriptor.get(other.linkDescriptor.indexOf(subTlv))); + } else { + isCommonSubTlv = false; + } + } + return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors) + && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors); + } + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("localNodeDescriptors", localNodeDescriptors) + .add("remoteNodeDescriptors", remoteNodeDescriptors) + .add("linkDescriptor", linkDescriptor) + .toString(); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + int result = this.localNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).localNodeDescriptors); + if (result != 0) { + return result; + } else if (this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors) != 0) { + return this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors); + } else { + int countOtherSubTlv = ((BgpLinkLSIdentifier) o).linkDescriptor.size(); + int countObjSubTlv = linkDescriptor.size(); + if (countOtherSubTlv != countObjSubTlv) { + if (countOtherSubTlv > countObjSubTlv) { + return 1; + } else { + return -1; + } + } + ListIterator listIterator = linkDescriptor.listIterator(); + ListIterator listIteratorOther = ((BgpLinkLSIdentifier) o).linkDescriptor.listIterator(); + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (linkDescriptor.contains(tlv) && ((BgpLinkLSIdentifier) o).linkDescriptor.contains(tlv)) { + int res = linkDescriptor.get(linkDescriptor.indexOf(tlv)).compareTo( + ((BgpLinkLSIdentifier) o).linkDescriptor.get(((BgpLinkLSIdentifier) o).linkDescriptor + .indexOf(tlv))); + if (res != 0) { + return res; + } + } else { + return 1; + } + } + } + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java new file mode 100755 index 00000000..01d369e4 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpLinkLsNlriVer4.java @@ -0,0 +1,210 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpLinkLsNlri; +import org.onosproject.bgpio.protocol.NlriType; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.RouteDistinguisher; +import org.onosproject.bgpio.util.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Link LS NLRI. + */ +public class BgpLinkLsNlriVer4 implements BgpLinkLsNlri { + + /* + * REFERENCE : draft-ietf-idr-ls-distribution-11 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+ + | Protocol-ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | + | (64 bits) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Local Node Descriptors (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Remote Node Descriptors (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Link Descriptors (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure : The Link NLRI format + */ + private static final Logger log = LoggerFactory.getLogger(BgpLinkLsNlriVer4.class); + public static final int LINK_NLRITYPE = 2; + + private BgpLinkLSIdentifier linkLSIdentifier; + private byte protocolId; + private long identifier; + private RouteDistinguisher routeDistinguisher; + private boolean isVpn; + + /** + * Initialize fields. + */ + public BgpLinkLsNlriVer4() { + this.protocolId = 0; + this.identifier = 0; + this.linkLSIdentifier = null; + this.routeDistinguisher = null; + this.isVpn = false; + } + + /** + * Constructor to initialize parameters for BGP LinkLSNlri. + * + * @param protocolId protocol Id + * @param identifier field in BGP LinkLSNlri + * @param linkLSIdentifier link LS identifier + * @param routeDistinguisher route distinguisher from message + * @param isVpn vpn info availability in message + */ + public BgpLinkLsNlriVer4(byte protocolId, long identifier, BgpLinkLSIdentifier linkLSIdentifier, + RouteDistinguisher routeDistinguisher, boolean isVpn) { + this.protocolId = protocolId; + this.identifier = identifier; + this.linkLSIdentifier = linkLSIdentifier; + this.routeDistinguisher = routeDistinguisher; + this.isVpn = isVpn; + } + + /** + * Reads from channelBuffer and parses Link LS Nlri. + * + * @param cb ChannelBuffer + * @param afi Address Family Identifier + * @param safi Subsequent Address Family Identifier + * @return object of this class + * @throws BgpParseException while parsing Link LS NLRI + */ + public static BgpLinkLsNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { + boolean isVpn = false; + RouteDistinguisher routeDistinguisher = null; + if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { + routeDistinguisher = new RouteDistinguisher(); + routeDistinguisher = RouteDistinguisher.read(cb); + isVpn = true; + } else { + isVpn = false; + } + byte protocolId = cb.readByte(); + long identifier = cb.readLong(); + + BgpLinkLSIdentifier linkLSIdentifier = new BgpLinkLSIdentifier(); + linkLSIdentifier = BgpLinkLSIdentifier.parseLinkIdendifier(cb, protocolId); + return new BgpLinkLsNlriVer4(protocolId, identifier, linkLSIdentifier, routeDistinguisher, isVpn); + } + + @Override + public NlriType getNlriType() { + return NlriType.LINK; + } + + @Override + public long getIdentifier() { + return this.identifier; + } + + /** + * Set the link LS identifier. + * + * @param linkLSIdentifier link LS identifier to set + */ + public void setLinkLSIdentifier(BgpLinkLSIdentifier linkLSIdentifier) { + this.linkLSIdentifier = linkLSIdentifier; + } + + @Override + public ProtocolType getProtocolId() throws BgpParseException { + switch (protocolId) { + case Constants.ISIS_LEVELONE: + return ProtocolType.ISIS_LEVEL_ONE; + case Constants.ISIS_LEVELTWO: + return ProtocolType.ISIS_LEVEL_TWO; + case Constants.OSPFV2: + return ProtocolType.OSPF_V2; + case Constants.DIRECT: + return ProtocolType.DIRECT; + case Constants.STATIC_CONFIGURATION: + return ProtocolType.STATIC_CONFIGURATION; + case Constants.OSPFV3: + return ProtocolType.OSPF_V3; + default: + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); + } + } + + @Override + public NodeDescriptors localNodeDescriptors() { + return this.linkLSIdentifier.localNodeDescriptors(); + } + + @Override + public NodeDescriptors remoteNodeDescriptors() { + return this.linkLSIdentifier.remoteNodeDescriptors(); + } + + /** + * Returns whether VPN is present or not. + * + * @return whether VPN is present or not + */ + public boolean isVpnPresent() { + return this.isVpn; + } + + @Override + public RouteDistinguisher getRouteDistinguisher() { + return this.routeDistinguisher; + } + + /** + * Returns link identifier. + * + * @return link identifier + */ + public BgpLinkLSIdentifier getLinkIdentifier() { + return this.linkLSIdentifier; + } + + @Override + public List linkDescriptors() { + return this.linkLSIdentifier.linkDescriptors(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("protocolId", protocolId) + .add("identifier", identifier) + .add("RouteDistinguisher ", routeDistinguisher) + .add("linkLSIdentifier", linkLSIdentifier) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java new file mode 100644 index 00000000..6c2c96d9 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSIdentifier.java @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.util.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Node Identifier which includes local node descriptor/remote node descriptors. + */ +public class BgpNodeLSIdentifier implements Comparable { + + private static final Logger log = LoggerFactory.getLogger(BgpNodeLSIdentifier.class); + private NodeDescriptors nodeDescriptors; + + /** + * Resets fields. + */ + public BgpNodeLSIdentifier() { + this.nodeDescriptors = null; + } + + /** + * Constructor to initialize fields. + * + * @param nodeDescriptors local/remote node descriptor + */ + public BgpNodeLSIdentifier(NodeDescriptors nodeDescriptors) { + this.nodeDescriptors = nodeDescriptors; + } + + /** + * Parse local node descriptors. + * + * @param cb ChannelBuffer + * @param protocolId protocol identifier + * @return object of this BGPNodeLSIdentifier + * @throws BgpParseException while parsing local node descriptors + */ + public static BgpNodeLSIdentifier parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId) + throws BgpParseException { + log.debug("parse Local node descriptor"); + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + Constants.TYPE_AND_LEN)); + } + NodeDescriptors nodeDescriptors = new NodeDescriptors(); + ChannelBuffer tempCb = cb.readBytes(length); + + if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) { + nodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId); + } else { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); + } + return new BgpNodeLSIdentifier(nodeDescriptors); + } + + /** + * Returns node descriptors. + * + * @return node descriptors + */ + public NodeDescriptors getNodedescriptors() { + return this.nodeDescriptors; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof BgpNodeLSIdentifier) { + BgpNodeLSIdentifier other = (BgpNodeLSIdentifier) obj; + return Objects.equals(nodeDescriptors, other.nodeDescriptors); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(nodeDescriptors); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("NodeDescriptors", nodeDescriptors) + .toString(); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return this.nodeDescriptors.compareTo(((BgpNodeLSIdentifier) o).nodeDescriptors); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java new file mode 100644 index 00000000..b27096cf --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpNodeLSNlriVer4.java @@ -0,0 +1,212 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpNodeLSNlri; +import org.onosproject.bgpio.protocol.NlriType; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.RouteDistinguisher; +import org.onosproject.bgpio.util.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Node LS NLRI. + */ +public class BgpNodeLSNlriVer4 implements BgpNodeLSNlri { + + /* + *REFERENCE : draft-ietf-idr-ls-distribution-11 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+ + | Protocol-ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | + | (64 bits) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Local Node Descriptors (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure : The Node NLRI format + */ + + protected static final Logger log = LoggerFactory.getLogger(BgpNodeLSNlriVer4.class); + + public static final int NODE_NLRITYPE = 1; + public static final int IDENTIFIER_LENGTH = 16; + private long identifier; + private byte protocolId; + private BgpNodeLSIdentifier localNodeDescriptors; + private RouteDistinguisher routeDistinguisher; + private boolean isVpn; + + /** + * Enum to provide PROTOCOLTYPE. + */ + public enum ProtocolType { + ISIS_LEVEL_ONE(1), ISIS_LEVEL_TWO(2), OSPF_V2(3), DIRECT(4), STATIC_CONFIGURATION(5), OSPF_V3(6); + int value; + + /** + * Assign val with the value as the protocol type. + * + * @param val protocol type + */ + ProtocolType(int val) { + value = val; + } + + /** + * Returns value of protocol type. + * + * @return protocol type + */ + public byte getType() { + return (byte) value; + } + } + + /** + * Reset fields. + */ + public BgpNodeLSNlriVer4() { + this.identifier = 0; + this.protocolId = 0; + this.localNodeDescriptors = null; + this.routeDistinguisher = null; + this.isVpn = false; + } + + /** + * Constructors to initialize its parameters. + * + * @param identifier of LinkState Nlri + * @param protocolId of LinkState Nlri + * @param localNodeDescriptors local node descriptors + * @param isVpn true if VPN info is present + * @param routeDistinguisher unique for each VPN + */ + public BgpNodeLSNlriVer4(long identifier, byte protocolId, BgpNodeLSIdentifier localNodeDescriptors, boolean isVpn, + RouteDistinguisher routeDistinguisher) { + this.identifier = identifier; + this.protocolId = protocolId; + this.localNodeDescriptors = localNodeDescriptors; + this.routeDistinguisher = routeDistinguisher; + this.isVpn = isVpn; + } + + /** + * Reads from channelBuffer and parses Node LS Nlri. + * + * @param cb ChannelBuffer + * @param afi Address Family Identifier + * @param safi Subsequent Address Family Identifier + * @return object of this class + * @throws BgpParseException while parsing node descriptors + */ + public static BgpNodeLSNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { + boolean isVpn = false; + RouteDistinguisher routeDistinguisher = null; + if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { + routeDistinguisher = new RouteDistinguisher(); + routeDistinguisher = RouteDistinguisher.read(cb); + isVpn = true; + } else { + isVpn = false; + } + byte protocolId = cb.readByte(); + long identifier = cb.readLong(); + + // Parse Local Node Descriptors + BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(); + localNodeDescriptors = BgpNodeLSIdentifier.parseLocalNodeDescriptors(cb, protocolId); + return new BgpNodeLSNlriVer4(identifier, protocolId, localNodeDescriptors, isVpn, routeDistinguisher); + } + + @Override + public NlriType getNlriType() { + return NlriType.NODE; + } + + @Override + public BgpNodeLSIdentifier getLocalNodeDescriptors() { + return this.localNodeDescriptors; + } + + /** + * Returns whether VPN is present or not. + * + * @return whether VPN is present or not + */ + public boolean isVpnPresent() { + return this.isVpn; + } + + @Override + public RouteDistinguisher getRouteDistinguisher() { + return this.routeDistinguisher; + } + + @Override + public long getIdentifier() { + return this.identifier; + } + + /** + * Set the node LS identifier. + * + * @param localNodeDescriptors node LS identifier to set + */ + public void setNodeLSIdentifier(BgpNodeLSIdentifier localNodeDescriptors) { + this.localNodeDescriptors = localNodeDescriptors; + } + + @Override + public ProtocolType getProtocolId() throws BgpParseException { + switch (protocolId) { + case Constants.ISIS_LEVELONE: + return ProtocolType.ISIS_LEVEL_ONE; + case Constants.ISIS_LEVELTWO: + return ProtocolType.ISIS_LEVEL_TWO; + case Constants.OSPFV2: + return ProtocolType.OSPF_V2; + case Constants.DIRECT: + return ProtocolType.DIRECT; + case Constants.STATIC_CONFIGURATION: + return ProtocolType.STATIC_CONFIGURATION; + case Constants.OSPFV3: + return ProtocolType.OSPF_V3; + default: + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("protocolId", protocolId) + .add("identifier", identifier) + .add("RouteDistinguisher ", routeDistinguisher) + .add("localNodeDescriptors", localNodeDescriptors) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java new file mode 100644 index 00000000..49cb74bd --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java @@ -0,0 +1,205 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpPrefixLSNlri; +import org.onosproject.bgpio.protocol.NlriType; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.RouteDistinguisher; +import org.onosproject.bgpio.util.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Prefix IPV4 LS NLRI. + */ +public class BgpPrefixIPv4LSNlriVer4 implements BgpPrefixLSNlri { + + /* + * REFERENCE : draft-ietf-idr-ls-distribution-11 + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+ + | Protocol-ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | + | (64 bits) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Local Node Descriptor (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // Prefix Descriptors (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure : The IPv4/IPv6 Topology Prefix NLRI format + */ + + protected static final Logger log = LoggerFactory.getLogger(BgpPrefixIPv4LSNlriVer4.class); + + public static final int PREFIX_IPV4_NLRITYPE = 3; + public static final int IDENTIFIER_LENGTH = 16; + private long identifier; + private byte protocolId; + private RouteDistinguisher routeDistinguisher; + private boolean isVpn; + private BgpPrefixLSIdentifier bgpPrefixLSIdentifier; + + /** + * Resets parameters. + */ + public BgpPrefixIPv4LSNlriVer4() { + this.identifier = 0; + this.protocolId = 0; + this.bgpPrefixLSIdentifier = null; + this.routeDistinguisher = null; + this.isVpn = false; + } + + /** + * Constructor to initialize parameters for BGP PrefixLSNlri. + * + * @param identifier field in BGP PrefixLSNlri + * @param protocolId protocol Id + * @param bgpPrefixLSIdentifier prefix LS Identifier + * @param routeDistinguisher RouteDistinguisher + * @param isVpn vpn availability in message + */ + public BgpPrefixIPv4LSNlriVer4(long identifier, byte protocolId, BgpPrefixLSIdentifier bgpPrefixLSIdentifier, + RouteDistinguisher routeDistinguisher, boolean isVpn) { + this.identifier = identifier; + this.protocolId = protocolId; + this.bgpPrefixLSIdentifier = bgpPrefixLSIdentifier; + this.routeDistinguisher = routeDistinguisher; + this.isVpn = isVpn; + } + + /** + * Reads from channelBuffer and parses Prefix LS Nlri. + * + * @param cb ChannelBuffer + * @param afi Address family identifier + * @param safi Subsequent address family identifier + * @return object of BGPPrefixIPv4LSNlriVer4 + * @throws BgpParseException while parsing Prefix LS Nlri + */ + public static BgpPrefixIPv4LSNlriVer4 read(ChannelBuffer cb, short afi, byte safi) throws BgpParseException { + + boolean isVpn = false; + RouteDistinguisher routeDistinguisher = null; + if ((afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { + routeDistinguisher = new RouteDistinguisher(); + routeDistinguisher = RouteDistinguisher.read(cb); + isVpn = true; + } else { + isVpn = false; + } + byte protocolId = cb.readByte(); + long identifier = cb.readLong(); + + BgpPrefixLSIdentifier bgpPrefixLSIdentifier = new BgpPrefixLSIdentifier(); + bgpPrefixLSIdentifier = BgpPrefixLSIdentifier.parsePrefixIdendifier(cb, protocolId); + return new BgpPrefixIPv4LSNlriVer4(identifier, protocolId, bgpPrefixLSIdentifier, routeDistinguisher, isVpn); + } + + @Override + public NlriType getNlriType() { + return NlriType.PREFIX_IPV4; + } + + @Override + public NodeDescriptors getLocalNodeDescriptors() { + return this.bgpPrefixLSIdentifier.getLocalNodeDescriptors(); + } + + @Override + public long getIdentifier() { + return this.identifier; + } + + /** + * Set the prefix LS identifier. + * + * @param bgpPrefixLSIdentifier prefix identifier to set + */ + public void setPrefixLSIdentifier(BgpPrefixLSIdentifier bgpPrefixLSIdentifier) { + this.bgpPrefixLSIdentifier = bgpPrefixLSIdentifier; + } + + @Override + public ProtocolType getProtocolId() throws BgpParseException { + switch (protocolId) { + case Constants.ISIS_LEVELONE: + return ProtocolType.ISIS_LEVEL_ONE; + case Constants.ISIS_LEVELTWO: + return ProtocolType.ISIS_LEVEL_TWO; + case Constants.OSPFV2: + return ProtocolType.OSPF_V2; + case Constants.DIRECT: + return ProtocolType.DIRECT; + case Constants.STATIC_CONFIGURATION: + return ProtocolType.STATIC_CONFIGURATION; + case Constants.OSPFV3: + return ProtocolType.OSPF_V3; + default: + throw new BgpParseException("protocol id not valid"); + } + } + + /** + * Returns whether VPN is present or not. + * + * @return whether VPN is present or not + */ + public boolean isVpnPresent() { + return this.isVpn; + } + + /** + * Returns Prefix Identifier. + * + * @return Prefix Identifier + */ + public BgpPrefixLSIdentifier getPrefixIdentifier() { + return this.bgpPrefixLSIdentifier; + } + + @Override + public RouteDistinguisher getRouteDistinguisher() { + return this.routeDistinguisher; + } + + @Override + public List getPrefixdescriptor() { + return this.bgpPrefixLSIdentifier.getPrefixdescriptor(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("protocolId", protocolId) + .add("identifier", identifier) + .add("RouteDistinguisher ", routeDistinguisher) + .add("bgpPrefixLSIdentifier", bgpPrefixLSIdentifier) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java new file mode 100644 index 00000000..22e68917 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixLSIdentifier.java @@ -0,0 +1,272 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.IPReachabilityInformationTlv; +import org.onosproject.bgpio.types.OSPFRouteTypeTlv; +import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; +import org.onosproject.bgpio.util.UnSupportedAttribute; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of Local node descriptors and prefix descriptors. + */ +public class BgpPrefixLSIdentifier implements Comparable { + + protected static final Logger log = LoggerFactory.getLogger(BgpPrefixLSIdentifier.class); + public static final int TYPE_AND_LEN = 4; + private NodeDescriptors localNodeDescriptors; + private List prefixDescriptor; + + /** + * Resets parameters. + */ + public BgpPrefixLSIdentifier() { + this.localNodeDescriptors = null; + this.prefixDescriptor = null; + } + + /** + * Constructor to initialize parameters. + * + * @param localNodeDescriptors Local node descriptors + * @param prefixDescriptor Prefix Descriptors + */ + public BgpPrefixLSIdentifier(NodeDescriptors localNodeDescriptors, List prefixDescriptor) { + this.localNodeDescriptors = localNodeDescriptors; + this.prefixDescriptor = prefixDescriptor; + } + + /** + * Reads the channel buffer and parses Prefix Identifier. + * + * @param cb ChannelBuffer + * @param protocolId protocol ID + * @return object of this class + * @throws BgpParseException while parsing Prefix Identifier + */ + public static BgpPrefixLSIdentifier parsePrefixIdendifier(ChannelBuffer cb, byte protocolId) + throws BgpParseException { + //Parse Local Node descriptor + NodeDescriptors localNodeDescriptors = new NodeDescriptors(); + localNodeDescriptors = parseLocalNodeDescriptors(cb, protocolId); + + //Parse Prefix descriptor + List prefixDescriptor = new LinkedList<>(); + prefixDescriptor = parsePrefixDescriptors(cb); + return new BgpPrefixLSIdentifier(localNodeDescriptors, prefixDescriptor); + } + + /** + * Parse local node descriptors. + * + * @param cb ChannelBuffer + * @param protocolId protocol identifier + * @return LocalNodeDescriptors + * @throws BgpParseException while parsing local node descriptors + */ + public static NodeDescriptors parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId) + throws BgpParseException { + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + //length + 4 implies data contains type, length and value + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); + } + NodeDescriptors localNodeDescriptors = new NodeDescriptors(); + ChannelBuffer tempCb = cb.readBytes(length); + + if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) { + localNodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId); + } else { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); + } + return localNodeDescriptors; + } + + /** + * Parse list of prefix descriptors. + * + * @param cb ChannelBuffer + * @return list of prefix descriptors + * @throws BgpParseException while parsing list of prefix descriptors + */ + public static List parsePrefixDescriptors(ChannelBuffer cb) throws BgpParseException { + LinkedList prefixDescriptor = new LinkedList<>(); + BgpValueType tlv = null; + boolean isIpReachInfo = false; + ChannelBuffer tempCb; + int count = 0; + + while (cb.readableBytes() > 0) { + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + //length + 4 implies data contains type, length and value + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); + } + tempCb = cb.readBytes(length); + switch (type) { + case OSPFRouteTypeTlv.TYPE: + tlv = OSPFRouteTypeTlv.read(tempCb); + break; + case IPReachabilityInformationTlv.TYPE: + tlv = IPReachabilityInformationTlv.read(tempCb, length); + isIpReachInfo = true; + break; + case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY: + tlv = BgpAttrNodeMultiTopologyId.read(tempCb); + count = count + 1; + if (count > 1) { + //length + 4 implies data contains type, length and value + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length + TYPE_AND_LEN)); + } + break; + default: + UnSupportedAttribute.skipBytes(tempCb, length); + } + prefixDescriptor.add(tlv); + } + + if (!isIpReachInfo) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + null); + } + return prefixDescriptor; + } + + /** + * Returns local node descriptors. + * + * @return local node descriptors + */ + public NodeDescriptors getLocalNodeDescriptors() { + return this.localNodeDescriptors; + } + + /** + * Returns Prefix descriptors. + * + * @return Prefix descriptors + */ + public List getPrefixdescriptor() { + return this.prefixDescriptor; + } + + @Override + public int hashCode() { + return Objects.hash(prefixDescriptor.hashCode(), localNodeDescriptors); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixLSIdentifier) { + int countObjSubTlv = 0; + int countOtherSubTlv = 0; + boolean isCommonSubTlv = true; + BgpPrefixLSIdentifier other = (BgpPrefixLSIdentifier) obj; + + Iterator objListIterator = other.prefixDescriptor.iterator(); + countOtherSubTlv = other.prefixDescriptor.size(); + countObjSubTlv = prefixDescriptor.size(); + if (countObjSubTlv != countOtherSubTlv) { + return false; + } else { + while (objListIterator.hasNext() && isCommonSubTlv) { + BgpValueType subTlv = objListIterator.next(); + if (prefixDescriptor.contains(subTlv) && other.prefixDescriptor.contains(subTlv)) { + isCommonSubTlv = Objects.equals(prefixDescriptor.get(prefixDescriptor.indexOf(subTlv)), + other.prefixDescriptor.get(other.prefixDescriptor.indexOf(subTlv))); + } else { + isCommonSubTlv = false; + } + } + return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors); + } + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("localNodeDescriptors", localNodeDescriptors) + .add("prefixDescriptor", prefixDescriptor) + .toString(); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + int result = this.localNodeDescriptors.compareTo(((BgpPrefixLSIdentifier) o).localNodeDescriptors); + if (result != 0) { + return result; + } else { + int countOtherSubTlv = ((BgpPrefixLSIdentifier) o).prefixDescriptor.size(); + int countObjSubTlv = prefixDescriptor.size(); + if (countOtherSubTlv != countObjSubTlv) { + if (countOtherSubTlv > countObjSubTlv) { + return 1; + } else { + return -1; + } + } + + ListIterator listIterator = prefixDescriptor.listIterator(); + ListIterator listIteratorOther = ((BgpPrefixLSIdentifier) o).prefixDescriptor.listIterator(); + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (prefixDescriptor.contains(tlv) && ((BgpPrefixLSIdentifier) o).prefixDescriptor.contains(tlv)) { + int res = prefixDescriptor.get(prefixDescriptor.indexOf(tlv)).compareTo( + ((BgpPrefixLSIdentifier) o).prefixDescriptor + .get(((BgpPrefixLSIdentifier) o).prefixDescriptor.indexOf(tlv))); + if (res != 0) { + return res; + } + } else { + return 1; + } + } + } + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java new file mode 100644 index 00000000..f91ac260 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/NodeDescriptors.java @@ -0,0 +1,264 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.AreaIDTlv; +import org.onosproject.bgpio.types.AutonomousSystemTlv; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpLSIdentifierTlv; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.IsIsNonPseudonode; +import org.onosproject.bgpio.types.IsIsPseudonode; +import org.onosproject.bgpio.types.OSPFNonPseudonode; +import org.onosproject.bgpio.types.OSPFPseudonode; +import org.onosproject.bgpio.util.UnSupportedAttribute; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Local and Remote NodeDescriptors which contains Node Descriptor Sub-TLVs. + */ +public class NodeDescriptors { + + /* + *Reference :draft-ietf-idr-ls-distribution-11 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + // Node Descriptor Sub-TLVs (variable) // + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure : Local or Remote Node Descriptors TLV format + */ + + private static final Logger log = LoggerFactory.getLogger(NodeDescriptors.class); + + public static final short LOCAL_NODE_DES_TYPE = 256; + public static final short REMOTE_NODE_DES_TYPE = 257; + public static final short IGP_ROUTERID_TYPE = 515; + public static final short IS_IS_LEVEL_1_PROTOCOL_ID = 1; + public static final short IS_IS_LEVEL_2_PROTOCOL_ID = 2; + public static final short OSPF_V2_PROTOCOL_ID = 3; + public static final short OSPF_V3_PROTOCOL_ID = 6; + public static final int TYPE_AND_LEN = 4; + public static final int ISISNONPSEUDONODE_LEN = 6; + public static final int ISISPSEUDONODE_LEN = 7; + public static final int OSPFNONPSEUDONODE_LEN = 4; + public static final int OSPFPSEUDONODE_LEN = 8; + private List subTlvs; + private short deslength; + private short desType; + + /** + * Resets parameters. + */ + public NodeDescriptors() { + this.subTlvs = null; + this.deslength = 0; + this.desType = 0; + } + + /** + * Constructor to initialize parameters. + * + * @param subTlvs list of subTlvs + * @param deslength Descriptors length + * @param desType local node descriptor or remote node descriptor type + */ + public NodeDescriptors(List subTlvs, short deslength, short desType) { + this.subTlvs = subTlvs; + this.deslength = deslength; + this.desType = desType; + } + + /** + * Returns list of subTlvs. + * + * @return subTlvs list of subTlvs + */ + public List getSubTlvs() { + return subTlvs; + } + + @Override + public int hashCode() { + return Objects.hash(subTlvs.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof NodeDescriptors) { + int countObjSubTlv = 0; + int countOtherSubTlv = 0; + boolean isCommonSubTlv = true; + NodeDescriptors other = (NodeDescriptors) obj; + Iterator objListIterator = other.subTlvs.iterator(); + countOtherSubTlv = other.subTlvs.size(); + countObjSubTlv = subTlvs.size(); + if (countObjSubTlv != countOtherSubTlv) { + return false; + } else { + while (objListIterator.hasNext() && isCommonSubTlv) { + BgpValueType subTlv = objListIterator.next(); + if (subTlvs.contains(subTlv) && other.subTlvs.contains(subTlv)) { + isCommonSubTlv = Objects.equals(subTlvs.get(subTlvs.indexOf(subTlv)), + other.subTlvs.get(other.subTlvs.indexOf(subTlv))); + } else { + isCommonSubTlv = false; + } + } + return isCommonSubTlv; + } + } + return false; + } + + /** + * Reads node descriptors Sub-TLVs. + * + * @param cb ChannelBuffer + * @param desLength node descriptor length + * @param desType local node descriptor or remote node descriptor type + * @param protocolId protocol ID + * @return object of NodeDescriptors + * @throws BgpParseException while parsing node descriptors + */ + public static NodeDescriptors read(ChannelBuffer cb, short desLength, short desType, byte protocolId) + throws BgpParseException { + log.debug("Read NodeDescriptor"); + List subTlvs = new LinkedList<>(); + BgpValueType tlv = null; + + while (cb.readableBytes() > 0) { + ChannelBuffer tempBuf = cb.copy(); + short type = cb.readShort(); + short length = cb.readShort(); + if (cb.readableBytes() < length) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, + tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN)); + } + ChannelBuffer tempCb = cb.readBytes(length); + switch (type) { + case AutonomousSystemTlv.TYPE: + tlv = AutonomousSystemTlv.read(tempCb); + break; + case BgpLSIdentifierTlv.TYPE: + tlv = BgpLSIdentifierTlv.read(tempCb); + break; + case AreaIDTlv.TYPE: + tlv = AreaIDTlv.read(tempCb); + break; + case IGP_ROUTERID_TYPE: + if (protocolId == IS_IS_LEVEL_1_PROTOCOL_ID || protocolId == IS_IS_LEVEL_2_PROTOCOL_ID) { + if (length == ISISNONPSEUDONODE_LEN) { + tlv = IsIsNonPseudonode.read(tempCb); + } else if (length == ISISPSEUDONODE_LEN) { + tlv = IsIsPseudonode.read(tempCb); + } + } else if (protocolId == OSPF_V2_PROTOCOL_ID || protocolId == OSPF_V3_PROTOCOL_ID) { + if (length == OSPFNONPSEUDONODE_LEN) { + tlv = OSPFNonPseudonode.read(tempCb); + } else if (length == OSPFPSEUDONODE_LEN) { + tlv = OSPFPseudonode.read(tempCb); + } + } + break; + default: + UnSupportedAttribute.skipBytes(tempCb, length); + } + subTlvs.add(tlv); + } + return new NodeDescriptors(subTlvs, desLength, desType); + } + + /** + * Returns node descriptors length. + * + * @return node descriptors length + */ + public short getLength() { + return this.deslength; + } + + /** + * Returns node descriptors type. + * + * @return node descriptors type + */ + public short getType() { + return this.desType; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("desType", desType) + .add("deslength", deslength) + .add("subTlvs", subTlvs) + .toString(); + } + + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + ListIterator listIterator = subTlvs.listIterator(); + ListIterator listIteratorOther = ((NodeDescriptors) o).subTlvs.listIterator(); + int countOtherSubTlv = ((NodeDescriptors) o).subTlvs.size(); + int countObjSubTlv = subTlvs.size(); + if (countOtherSubTlv != countObjSubTlv) { + if (countOtherSubTlv > countObjSubTlv) { + return 1; + } else { + return -1; + } + } else { + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + log.debug("NodeDescriptor compare subtlv's"); + if (subTlvs.contains(tlv) && ((NodeDescriptors) o).subTlvs.contains(tlv)) { + int result = subTlvs.get(subTlvs.indexOf(tlv)).compareTo( + ((NodeDescriptors) o).subTlvs.get(((NodeDescriptors) o).subTlvs.indexOf(tlv))); + if (result != 0) { + return result; + } + } else { + return 1; + } + } + } + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java new file mode 100755 index 00000000..9578ccfe --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetails.java @@ -0,0 +1,135 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.types.BgpValueType; + +import com.google.common.base.MoreObjects; + +/** + * This Class stores path Attributes, protocol ID and Identifier of LinkState NLRI. + */ +public class PathAttrNlriDetails { + private List pathAttributes; + private ProtocolType protocolID; + private long identifier; + + /** + * Sets path attribute with specified path attribute. + * + * @param pathAttributes in update message + */ + public void setPathAttribute(List pathAttributes) { + this.pathAttributes = pathAttributes; + } + + /** + * Returns path attributes. + * + * @return path attributes + */ + public List pathAttributes() { + return this.pathAttributes; + } + + /** + * Sets protocolID with specified protocolID. + * + * @param protocolID in linkstate nlri + */ + public void setProtocolID(ProtocolType protocolID) { + this.protocolID = protocolID; + } + + /** + * Returns protocolID. + * + * @return protocolID + */ + public ProtocolType protocolID() { + return this.protocolID; + } + + /** + * Sets identifier with specified identifier. + * + * @param identifier in linkstate nlri + */ + public void setIdentifier(long identifier) { + this.identifier = identifier; + } + + /** + * Returns Identifier. + * + * @return Identifier + */ + public long identifier() { + return this.identifier; + } + + @Override + public int hashCode() { + return Objects.hash(pathAttributes, protocolID, identifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof PathAttrNlriDetails) { + int countObjSubTlv = 0; + int countOtherSubTlv = 0; + boolean isCommonSubTlv = true; + PathAttrNlriDetails other = (PathAttrNlriDetails) obj; + Iterator objListIterator = other.pathAttributes.iterator(); + countOtherSubTlv = other.pathAttributes.size(); + countObjSubTlv = pathAttributes.size(); + if (countObjSubTlv != countOtherSubTlv) { + return false; + } else { + while (objListIterator.hasNext() && isCommonSubTlv) { + BgpValueType subTlv = objListIterator.next(); + if (pathAttributes.contains(subTlv) && other.pathAttributes.contains(subTlv)) { + isCommonSubTlv = Objects.equals(pathAttributes.get(pathAttributes.indexOf(subTlv)), + other.pathAttributes.get(other.pathAttributes.indexOf(subTlv))); + } else { + isCommonSubTlv = false; + } + } + return isCommonSubTlv && Objects.equals(identifier, other.identifier) + && Objects.equals(protocolID, other.protocolID); + } + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("identifier", identifier) + .add("protocolID", protocolID) + .add("pathAttributes", pathAttributes) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java new file mode 100755 index 00000000..4172ae46 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/PathAttrNlriDetailsLocalRib.java @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgpio.protocol.linkstate; + +import java.util.Objects; + +import org.onlab.packet.IpAddress; +import com.google.common.base.MoreObjects; + +/** + * This Class stores path Attributes, protocol ID and Identifier of LinkState nlri. + */ +public class PathAttrNlriDetailsLocalRib { + + private IpAddress localRibIpAddress; + private long localRibAsNum; + private int localRibIdentifier; + private boolean isLocalRibIbgpSession; + private PathAttrNlriDetails localRibNlridetails; + + /** + * Constructor to initialize parameter. + * + * @param localRibIpAddress peer ip address + * @param localRibIdentifier peer identifier + * @param localRibAsNum peer As number + * @param isLocalRibIbgpSession flag to indicate is Ibgp session + * @param localRibNlridetails Nlri details + * + */ + public PathAttrNlriDetailsLocalRib(IpAddress localRibIpAddress, int localRibIdentifier, long localRibAsNum, + boolean isLocalRibIbgpSession, PathAttrNlriDetails localRibNlridetails) { + this.localRibIpAddress = localRibIpAddress; + this.localRibAsNum = localRibAsNum; + this.localRibIdentifier = localRibIdentifier; + this.isLocalRibIbgpSession = isLocalRibIbgpSession; + this.localRibNlridetails = localRibNlridetails; + } + + /** + * Gets the Ipaddress updated in local rib. + * + * @return localRibIpAddress ip address + */ + public IpAddress localRibIpAddress() { + return localRibIpAddress; + } + + /** + * Gets the autonomous system number updated in local rib. + * + * @return localRibAsNum autonomous system number + */ + public long localRibAsNum() { + return localRibAsNum; + } + + /** + * Gets the indetifier updated in local rib. + * + * @return localRibIdentifier identifier + */ + public int localRibIdentifier() { + return localRibIdentifier; + } + + /** + * Gets the bgp session type updated in local rib. + * + * @return isLocalRibIbgpSession session type + */ + public boolean isLocalRibIbgpSession() { + return isLocalRibIbgpSession; + } + + /** + * Returns local RIB Nlri details. + * + * @return localRibNlridetails Nlri details in local rib + */ + public PathAttrNlriDetails localRibNlridetails() { + return this.localRibNlridetails; + } + + @Override + public int hashCode() { + return Objects.hash(localRibIpAddress, localRibIdentifier, localRibAsNum, isLocalRibIbgpSession, + localRibNlridetails.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PathAttrNlriDetailsLocalRib) { + PathAttrNlriDetailsLocalRib other = (PathAttrNlriDetailsLocalRib) obj; + return Objects.equals(localRibIpAddress, other.localRibIpAddress) + && Objects.equals(localRibIdentifier, other.localRibIdentifier) + && Objects.equals(localRibAsNum, other.localRibAsNum) + && Objects.equals(isLocalRibIbgpSession, other.isLocalRibIbgpSession) + && Objects.equals(localRibNlridetails, other.localRibNlridetails); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).add("peerIdentifier", localRibIdentifier) + .add("localRibpathAttributes", localRibNlridetails.pathAttributes()).toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java new file mode 100755 index 00000000..87ba60f0 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * BGP Protocol specific link state details. + */ +package org.onosproject.bgpio.protocol.linkstate; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java new file mode 100755 index 00000000..723b31b1 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * BGP Protocol specific components. + */ +package org.onosproject.bgpio.protocol; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java new file mode 100755 index 00000000..c57832b6 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpFactoryVer4.java @@ -0,0 +1,58 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol.ver4; + +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpKeepaliveMsg; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.protocol.BgpNotificationMsg; +import org.onosproject.bgpio.protocol.BgpOpenMsg; +import org.onosproject.bgpio.protocol.BgpVersion; + +/** + * Provides BGP Factory and returns builder classes for all objects and messages. + */ +public class BgpFactoryVer4 implements BgpFactory { + + public static final BgpFactoryVer4 INSTANCE = new BgpFactoryVer4(); + + @Override + public BgpOpenMsg.Builder openMessageBuilder() { + return new BgpOpenMsgVer4.Builder(); + } + + @Override + public BgpKeepaliveMsg.Builder keepaliveMessageBuilder() { + return new BgpKeepaliveMsgVer4.Builder(); + } + + @Override + public BgpNotificationMsg.Builder notificationMessageBuilder() { + return new BgpNotificationMsgVer4.Builder(); + } + + @Override + public BgpMessageReader getReader() { + return BgpMessageVer4.READER; + } + + @Override + public BgpVersion getVersion() { + return BgpVersion.BGP_4; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java new file mode 100644 index 00000000..2c141586 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpKeepaliveMsgVer4.java @@ -0,0 +1,157 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.ver4; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpKeepaliveMsg; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.protocol.BgpMessageWriter; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides BGP keep alive message. + */ +public class BgpKeepaliveMsgVer4 implements BgpKeepaliveMsg { + + /* + ::= + A KEEPALIVE message consists of only the message header and has a + length of 19 octets. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + + + | Marker | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + REFERENCE : RFC 4271 + */ + + protected static final Logger log = LoggerFactory + .getLogger(BgpKeepaliveMsgVer4.class); + + private BgpHeader bgpMsgHeader; + public static final byte PACKET_VERSION = 4; + public static final int PACKET_MINIMUM_LENGTH = 19; + public static final int MARKER_LENGTH = 16; + public static final BgpType MSG_TYPE = BgpType.KEEP_ALIVE; + public static byte[] marker = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + + public static final BgpKeepaliveMsgVer4.Reader READER = new Reader(); + + /** + * Reader class for reading BGP keepalive message from channel buffer. + */ + static class Reader implements BgpMessageReader { + + @Override + public BgpKeepaliveMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) + throws BgpParseException { + + /* bgpHeader is not required in case of keepalive message and + Header is already read and no other fields except header in keepalive message.*/ + return new BgpKeepaliveMsgVer4(); + } + } + + /** + * Default constructor. + */ + public BgpKeepaliveMsgVer4() { + } + + /** + * Builder class for BGP keepalive message. + */ + static class Builder implements BgpKeepaliveMsg.Builder { + BgpHeader bgpMsgHeader; + + @Override + public Builder setHeader(BgpHeader bgpMsgHeader) { + this.bgpMsgHeader = bgpMsgHeader; + return this; + } + + @Override + public BgpKeepaliveMsg build() { + return new BgpKeepaliveMsgVer4(); + } + } + + @Override + public void writeTo(ChannelBuffer cb) { + WRITER.write(cb, this); + } + + static final Writer WRITER = new Writer(); + + /** + * Writer class for writing the BGP keepalive message to channel buffer. + */ + static class Writer implements BgpMessageWriter { + + @Override + public void write(ChannelBuffer cb, BgpKeepaliveMsgVer4 message) { + + // write marker + cb.writeBytes(marker, 0, MARKER_LENGTH); + + // write length of header + cb.writeShort(PACKET_MINIMUM_LENGTH); + + // write the type of message + cb.writeByte(MSG_TYPE.getType()); + } + } + + @Override + public BgpVersion getVersion() { + return BgpVersion.BGP_4; + } + + @Override + public BgpType getType() { + return MSG_TYPE; + } + + @Override + public BgpHeader getHeader() { + return this.bgpMsgHeader; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java new file mode 100755 index 00000000..1c05dae4 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpMessageVer4.java @@ -0,0 +1,111 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.protocol.ver4; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides BGP messages. + */ +public abstract class BgpMessageVer4 { + + protected static final Logger log = LoggerFactory.getLogger(BgpFactories.class); + + static final byte OPEN_MSG_TYPE = 0x1; + static final byte KEEPALIVE_MSG_TYPE = 0x4; + static final byte UPDATE_MSG_TYPE = 0x2; + static final byte NOTIFICATION_MSG_TYPE = 0x3; + static final int MINIMUM_COMMON_HEADER_LENGTH = 19; + static final int HEADER_AND_MSG_LEN = 18; + static final int MAXIMUM_PACKET_LENGTH = 4096; + + public static final BgpMessageVer4.Reader READER = new Reader(); + + /** + * Reader class for reading BGP messages from channel buffer. + * + */ + static class Reader implements BgpMessageReader { + @Override + public BgpMessage readFrom(ChannelBuffer cb, BgpHeader bgpHeader) + throws BgpParseException { + + if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { + log.error("Packet should have minimum length."); + Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, + cb.readableBytes()); + } + if (cb.readableBytes() > MAXIMUM_PACKET_LENGTH) { + log.error("Packet length should not exceed {}.", MAXIMUM_PACKET_LENGTH); + Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, + cb.readableBytes()); + } + try { + // fixed value property version == 4 + byte[] marker = new byte[BgpHeader.MARKER_LENGTH]; + cb.readBytes(marker, 0, BgpHeader.MARKER_LENGTH); + bgpHeader.setMarker(marker); + for (int i = 0; i < BgpHeader.MARKER_LENGTH; i++) { + if (marker[i] != (byte) 0xff) { + throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, + BgpErrorType.CONNECTION_NOT_SYNCHRONIZED, null); + } + } + short length = cb.readShort(); + if (length > cb.readableBytes() + HEADER_AND_MSG_LEN) { + Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, + BgpErrorType.BAD_MESSAGE_LENGTH, length); + } + bgpHeader.setLength(length); + byte type = cb.readByte(); + bgpHeader.setType(type); + log.debug("Reading update message of type " + type); + + int len = length - MINIMUM_COMMON_HEADER_LENGTH; + switch (type) { + case OPEN_MSG_TYPE: + log.debug("OPEN MESSAGE is received"); + return BgpOpenMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); + case KEEPALIVE_MSG_TYPE: + log.debug("KEEPALIVE MESSAGE is received"); + return BgpKeepaliveMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); + case UPDATE_MSG_TYPE: + log.debug("UPDATE MESSAGE is received"); + return BgpUpdateMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); + case NOTIFICATION_MSG_TYPE: + log.debug("NOTIFICATION MESSAGE is received"); + return BgpNotificationMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); + default: + Validation.validateType(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_TYPE, type); + return null; + } + } catch (IndexOutOfBoundsException e) { + throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, + BgpErrorType.BAD_MESSAGE_LENGTH, null); + } + } + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java new file mode 100644 index 00000000..7243e21a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpNotificationMsgVer4.java @@ -0,0 +1,265 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.ver4; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.protocol.BgpMessageWriter; +import org.onosproject.bgpio.protocol.BgpNotificationMsg; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * A NOTIFICATION message is sent when an error condition is detected. The BGP connection is closed immediately after it + * is sent. + */ +class BgpNotificationMsgVer4 implements BgpNotificationMsg { + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Error code | Error subcode | Data (variable) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + REFERENCE : RFC 4271 + */ + + private static final Logger log = LoggerFactory.getLogger(BgpNotificationMsgVer4.class); + + static final byte PACKET_VERSION = 4; + //BGPHeader(19) + Error code(1) + Error subcode(1) + static final int TOTAL_MESSAGE_MIN_LENGTH = 21; + static final int PACKET_MINIMUM_LENGTH = 2; + static final BgpType MSG_TYPE = BgpType.NOTIFICATION; + static final byte DEFAULT_ERRORSUBCODE = 0; + static final byte[] MARKER = {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }; + static final byte MESSAGE_TYPE = 3; + static final BgpHeader DEFAULT_MESSAGE_HEADER = new BgpHeader(MARKER, BgpHeader.DEFAULT_HEADER_LENGTH, + MESSAGE_TYPE); + + private byte errorCode; + private byte errorSubCode; + private byte[] data; + private BgpHeader bgpHeader; + public static final BgpNotificationMsgVer4.Reader READER = new Reader(); + + /** + * Initialize fields. + */ + public BgpNotificationMsgVer4() { + this.bgpHeader = null; + this.data = null; + this.errorCode = 0; + this.errorSubCode = 0; + } + + /** + * Constructor to initialize parameters. + * + * @param bgpHeader BGP Header in notification message + * @param errorCode error code + * @param errorSubCode error subcode + * @param data field + */ + public BgpNotificationMsgVer4(BgpHeader bgpHeader, byte errorCode, byte errorSubCode, byte[] data) { + this.bgpHeader = bgpHeader; + this.data = data; + this.errorCode = errorCode; + this.errorSubCode = errorSubCode; + } + + /** + * Reader reads BGP Notification Message from the channel buffer. + */ + static class Reader implements BgpMessageReader { + @Override + public BgpNotificationMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException { + byte errorCode; + byte errorSubCode; + if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) { + throw new BgpParseException("Not enough readable bytes"); + } + errorCode = cb.readByte(); + errorSubCode = cb.readByte(); + //Message Length = 21 + Data Length + int dataLength = bgpHeader.getLength() - TOTAL_MESSAGE_MIN_LENGTH; + byte[] data = new byte[dataLength]; + cb.readBytes(data, 0, dataLength); + return new BgpNotificationMsgVer4(bgpHeader, errorCode, errorSubCode, data); + } + } + + /** + * Builder class for BGP notification message. + */ + static class Builder implements BgpNotificationMsg.Builder { + private byte errorCode; + private byte errorSubCode; + private byte[] data; + private BgpHeader bgpHeader; + private boolean isErrorCodeSet = false; + private boolean isErrorSubCodeSet = false; + private boolean isBGPHeaderSet = false; + + @Override + public BgpNotificationMsg build() throws BgpParseException { + BgpHeader bgpHeader = this.isBGPHeaderSet ? this.bgpHeader : DEFAULT_MESSAGE_HEADER; + if (!this.isErrorCodeSet) { + throw new BgpParseException("Error code must be present"); + } + + byte errorSubCode = this.isErrorSubCodeSet ? this.errorSubCode : DEFAULT_ERRORSUBCODE; + return new BgpNotificationMsgVer4(bgpHeader, this.errorCode, errorSubCode, this.data); + } + + @Override + public Builder setErrorCode(byte errorCode) { + this.errorCode = errorCode; + this.isErrorCodeSet = true; + return this; + } + + @Override + public Builder setErrorSubCode(byte errorSubCode) { + this.errorSubCode = errorSubCode; + this.isErrorSubCodeSet = true; + return this; + } + + @Override + public Builder setData(byte[] data) { + if (data != null) { + this.data = data; + } + return this; + } + + @Override + public Builder setHeader(BgpHeader bgpMsgHeader) { + this.bgpHeader = bgpMsgHeader; + return this; + } + } + + @Override + public BgpVersion getVersion() { + return BgpVersion.BGP_4; + } + + @Override + public BgpType getType() { + return BgpType.NOTIFICATION; + } + + @Override + public void writeTo(ChannelBuffer cb) throws BgpParseException { + WRITER.write(cb, this); + } + + static final Writer WRITER = new Writer(); + + /** + * Writer writes BGP notification message to channel buffer. + */ + static class Writer implements BgpMessageWriter { + @Override + public void write(ChannelBuffer cb, BgpNotificationMsgVer4 message) throws BgpParseException { + int msgStartIndex = cb.writerIndex(); + int headerLenIndex = message.bgpHeader.write(cb); + if (headerLenIndex <= 0) { + throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR, (byte) 0, null); + } + cb.writeByte(message.errorCode); + cb.writeByte(message.errorSubCode); + if (message.data != null) { + cb.writeBytes(message.data); + } + + //Update message length field in notification message + int length = cb.writerIndex() - msgStartIndex; + cb.setShort(headerLenIndex, (short) length); + message.bgpHeader.setLength((short) length); + } + } + + @Override + public byte getErrorCode() { + return this.errorCode; + } + + /** + * Sets errorcode with specified errorcode. + * + * @param errorCode field + */ + public void setErrorCode(byte errorCode) { + this.errorCode = errorCode; + } + + @Override + public byte getErrorSubCode() { + return this.errorSubCode; + } + + /** + * Sets error subcode with specified errorSubCode. + * + * @param errorSubCode field + */ + public void setErrorSubCode(byte errorSubCode) { + this.errorSubCode = errorSubCode; + } + + @Override + public byte[] getData() { + return this.data; + } + + /** + * Sets error data with specified data. + * + * @param data field + */ + public void setData(byte[] data) { + this.data = data; + } + + @Override + public BgpHeader getHeader() { + return this.bgpHeader; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("bgpHeader", bgpHeader) + .add("data", data) + .add("errorCode", errorCode) + .add("errorSubCode", errorSubCode) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java new file mode 100644 index 00000000..359eec25 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java @@ -0,0 +1,518 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.ver4; + +import java.util.LinkedList; +import java.util.ListIterator; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.protocol.BgpMessageWriter; +import org.onosproject.bgpio.protocol.BgpOpenMsg; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides BGP open message. + */ +public class BgpOpenMsgVer4 implements BgpOpenMsg { + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+ + | Version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | My Autonomous System | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Hold Time | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | BGP Identifier | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Opt Parm Len | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Optional Parameters (variable) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + OPEN Message Format + REFERENCE : RFC 4271 + */ + + protected static final Logger log = LoggerFactory.getLogger(BgpOpenMsgVer4.class); + + public static final byte PACKET_VERSION = 4; + public static final int OPEN_MSG_MINIMUM_LENGTH = 10; + public static final int MSG_HEADER_LENGTH = 19; + public static final int MARKER_LENGTH = 16; + public static final int DEFAULT_HOLD_TIME = 120; + public static final short AS_TRANS = 23456; + public static final int OPT_PARA_TYPE_CAPABILITY = 2; + public static final BgpType MSG_TYPE = BgpType.OPEN; + public static final short AFI = 16388; + public static final byte SAFI = 71; + public static final byte RES = 0; + public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65; + public static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER, + (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01); + private BgpHeader bgpMsgHeader; + private byte version; + private short asNumber; + private short holdTime; + private int bgpId; + private boolean isLargeAsCapabilitySet; + private LinkedList capabilityTlv; + + public static final BgpOpenMsgVer4.Reader READER = new Reader(); + + /** + * reset variables. + */ + public BgpOpenMsgVer4() { + this.bgpMsgHeader = null; + this.version = 0; + this.holdTime = 0; + this.asNumber = 0; + this.bgpId = 0; + this.capabilityTlv = null; + } + + /** + * Constructor to initialize all variables of BGP Open message. + * + * @param bgpMsgHeader BGP Header in open message + * @param version BGP version in open message + * @param holdTime hold time in open message + * @param asNumber AS number in open message + * @param bgpId BGP identifier in open message + * @param capabilityTlv capabilities in open message + */ + public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, short asNumber, short holdTime, + int bgpId, LinkedList capabilityTlv) { + this.bgpMsgHeader = bgpMsgHeader; + this.version = version; + this.asNumber = asNumber; + this.holdTime = holdTime; + this.bgpId = bgpId; + this.capabilityTlv = capabilityTlv; + } + + @Override + public BgpHeader getHeader() { + return this.bgpMsgHeader; + } + + @Override + public BgpVersion getVersion() { + return BgpVersion.BGP_4; + } + + @Override + public BgpType getType() { + return MSG_TYPE; + } + + @Override + public short getHoldTime() { + return this.holdTime; + } + + @Override + public short getAsNumber() { + return this.asNumber; + } + + @Override + public int getBgpId() { + return this.bgpId; + } + + @Override + public LinkedList getCapabilityTlv() { + return this.capabilityTlv; + } + + /** + * Reader class for reading BGP open message from channel buffer. + */ + public static class Reader implements BgpMessageReader { + + @Override + public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException { + + byte version; + short holdTime; + short asNumber; + int bgpId; + byte optParaLen = 0; + byte optParaType; + byte capParaLen = 0; + LinkedList capabilityTlv = new LinkedList<>(); + + if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) { + log.error("[readFrom] Invalid length: Packet size is less than the minimum length "); + Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH, + cb.readableBytes()); + } + + // Read version + version = cb.readByte(); + if (version != PACKET_VERSION) { + log.error("[readFrom] Invalid version: " + version); + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, + BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null); + } + + // Read AS number + asNumber = cb.readShort(); + + // Read Hold timer + holdTime = cb.readShort(); + + // Read BGP Identifier + bgpId = cb.readInt(); + + // Read optional parameter length + optParaLen = cb.readByte(); + + // Read Capabilities if optional parameter length is greater than 0 + if (optParaLen != 0) { + // Read optional parameter type + optParaType = cb.readByte(); + + // Read optional parameter length + capParaLen = cb.readByte(); + + if (cb.readableBytes() < capParaLen) { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null); + } + + ChannelBuffer capaCb = cb.readBytes(capParaLen); + + // Parse capabilities only if optional parameter type is 2 + if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) { + capabilityTlv = parseCapabilityTlv(capaCb); + } else { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, + BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null); + } + } + return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv); + } + } + + /** + * Parsing capabilities. + * + * @param cb of type channel buffer + * @return capabilityTlv of open message + * @throws BgpParseException while parsing capabilities + */ + protected static LinkedList parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException { + + LinkedList capabilityTlv = new LinkedList<>(); + + while (cb.readableBytes() > 0) { + BgpValueType tlv; + short type = cb.readByte(); + short length = cb.readByte(); + + switch (type) { + case FourOctetAsNumCapabilityTlv.TYPE: + log.debug("FourOctetAsNumCapabilityTlv"); + if (FourOctetAsNumCapabilityTlv.LENGTH != length) { + throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv."); + } + if (length > cb.readableBytes()) { + throw new BgpParseException("Four octet as num tlv length" + + " is more than readableBytes."); + } + int as4Num = cb.readInt(); + tlv = new FourOctetAsNumCapabilityTlv(as4Num); + break; + case MultiProtocolExtnCapabilityTlv.TYPE: + log.debug("MultiProtocolExtnCapabilityTlv"); + if (MultiProtocolExtnCapabilityTlv.LENGTH != length) { + throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv."); + } + if (length > cb.readableBytes()) { + throw new BgpParseException("BGP LS tlv length is more than readableBytes."); + } + short afi = cb.readShort(); + byte res = cb.readByte(); + byte safi = cb.readByte(); + tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + break; + default: + log.debug("Warning: Unsupported TLV: " + type); + cb.skipBytes(length); + continue; + } + capabilityTlv.add(tlv); + } + return capabilityTlv; + } + + /** + * Builder class for BGP open message. + */ + static class Builder implements BgpOpenMsg.Builder { + + private boolean isHeaderSet = false; + private BgpHeader bgpMsgHeader; + private boolean isHoldTimeSet = false; + private short holdTime; + private boolean isAsNumSet = false; + private short asNumber; + private boolean isBgpIdSet = false; + private int bgpId; + private boolean isLargeAsCapabilityTlvSet = false; + private boolean isLsCapabilityTlvSet = false; + + LinkedList capabilityTlv = new LinkedList<>(); + + @Override + public BgpOpenMsg build() throws BgpParseException { + BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER; + short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME; + + if (!this.isAsNumSet) { + throw new BgpParseException("BGP AS number is not set (mandatory)"); + } + + if (!this.isBgpIdSet) { + throw new BgpParseException("BGPID is not set (mandatory)"); + } + + if (this.isLargeAsCapabilityTlvSet) { + BgpValueType tlv; + int value = this.asNumber; + tlv = new FourOctetAsNumCapabilityTlv(value); + this.capabilityTlv.add(tlv); + } + + if (this.isLsCapabilityTlvSet) { + BgpValueType tlv; + tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI); + this.capabilityTlv.add(tlv); + } + + return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId, + this.capabilityTlv); + } + + @Override + public Builder setHeader(BgpHeader bgpMsgHeader) { + this.bgpMsgHeader = bgpMsgHeader; + return this; + } + + @Override + public Builder setHoldTime(short holdTime) { + this.holdTime = holdTime; + this.isHoldTimeSet = true; + return this; + } + + @Override + public Builder setAsNumber(short asNumber) { + this.asNumber = asNumber; + this.isAsNumSet = true; + return this; + } + + @Override + public Builder setBgpId(int bgpId) { + this.bgpId = bgpId; + this.isBgpIdSet = true; + return this; + } + + @Override + public Builder setCapabilityTlv(LinkedList capabilityTlv) { + this.capabilityTlv = capabilityTlv; + return this; + } + + @Override + public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) { + this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet; + return this; + } + + @Override + public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) { + this.isLsCapabilityTlvSet = isLsCapabilitySet; + return this; + } + } + + @Override + public void writeTo(ChannelBuffer cb) { + try { + WRITER.write(cb, this); + } catch (BgpParseException e) { + log.debug("[writeTo] Error: " + e.toString()); + } + } + + public static final Writer WRITER = new Writer(); + + /** + * Writer class for writing BGP open message to channel buffer. + */ + public static class Writer implements BgpMessageWriter { + + @Override + public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException { + + int optParaLen = 0; + int as4num = 0; + + int startIndex = cb.writerIndex(); + + // write common header and get msg length index + int msgLenIndex = message.bgpMsgHeader.write(cb); + + if (msgLenIndex <= 0) { + throw new BgpParseException("Unable to write message header."); + } + + // write version in 1-octet + cb.writeByte(message.version); + + // get as4num if LS Capability is set + if (message.isLargeAsCapabilitySet) { + LinkedList capabilityTlv = message + .getCapabilityTlv(); + ListIterator listIterator = capabilityTlv + .listIterator(); + + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { + as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); + break; + } + } + } + + if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) { + // write As number as AS_TRANS + cb.writeShort(AS_TRANS); + } else { + // write AS number in next 2-octet + cb.writeShort(message.asNumber); + } + + // write HoldTime in next 2-octet + cb.writeShort(message.holdTime); + + // write BGP Identifier in next 4-octet + cb.writeInt(message.bgpId); + + // store the index of Optional parameter length + int optParaLenIndex = cb.writerIndex(); + + // set optional parameter length as 0 + cb.writeByte(0); + + // Pack capability TLV + optParaLen = message.packCapabilityTlv(cb, message); + + if (optParaLen != 0) { + // Update optional parameter length + cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type. + } + + // write OPEN Object Length + int length = cb.writerIndex() - startIndex; + cb.setShort(msgLenIndex, (short) length); + message.bgpMsgHeader.setLength((short) length); + } + } + + /** + * returns length of capability tlvs. + * + * @param cb of type channel buffer + * @param message of type BGPOpenMsgVer4 + * @return capParaLen of open message + */ + protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) { + int startIndex = cb.writerIndex(); + int capParaLen = 0; + int capParaLenIndex = 0; + + LinkedList capabilityTlv = message.capabilityTlv; + ListIterator listIterator = capabilityTlv.listIterator(); + + if (listIterator.hasNext()) { + // Set optional parameter type as 2 + cb.writeByte(OPT_PARA_TYPE_CAPABILITY); + + // Store the index of capability parameter length and update length at the end + capParaLenIndex = cb.writerIndex(); + + // Set capability parameter length as 0 + cb.writeByte(0); + + // Update the startIndex to know the length of capability tlv + startIndex = cb.writerIndex(); + } + + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (tlv == null) { + log.debug("Warning: tlv is null from CapabilityTlv list"); + continue; + } + tlv.write(cb); + } + + capParaLen = cb.writerIndex() - startIndex; + + if (capParaLen != 0) { + // Update capability parameter length + cb.setByte(capParaLenIndex, (byte) capParaLen); + } + return capParaLen; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("bgpMsgHeader", bgpMsgHeader) + .add("version", version) + .add("holdTime", holdTime) + .add("asNumber", asNumber) + .add("bgpId", bgpId) + .add("capabilityTlv", capabilityTlv) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java new file mode 100644 index 00000000..13e52ca2 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java @@ -0,0 +1,200 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.ver4; + +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.As4Path; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.NextHop; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgpio.types.MpReachNlri; +import org.onosproject.bgpio.types.MpUnReachNlri; +import org.onosproject.bgpio.util.UnSupportedAttribute; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of BGP Path Attribute. + */ +public class BgpPathAttributes { + + /* Path attribute: + + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Attr. Flags |Attr. Type Code| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + REFERENCE : RFC 4271 + */ + protected static final Logger log = LoggerFactory.getLogger(BgpPathAttributes.class); + + public static final int LINK_STATE_ATTRIBUTE_TYPE = 50; + public static final int MPREACHNLRI_TYPE = 14; + public static final int MPUNREACHNLRI_TYPE = 15; + + private final List pathAttribute; + + /** + * Initialize parameter. + */ + public BgpPathAttributes() { + this.pathAttribute = null; + } + + /** + * Constructor to initialize parameters for BGP path attributes. + * + * @param pathAttribute list of path attributes + */ + public BgpPathAttributes(List pathAttribute) { + this.pathAttribute = pathAttribute; + } + + /** + * Returns list of path attributes. + * + * @return list of path attributes + */ + public List pathAttributes() { + return this.pathAttribute; + } + + /** + * Reads from channelBuffer and parses BGP path attributes. + * + * @param cb channelBuffer + * @return object of BgpPathAttributes + * @throws BgpParseException while parsing BGP path attributes + */ + public static BgpPathAttributes read(ChannelBuffer cb) + throws BgpParseException { + + BgpValueType pathAttribute = null; + List pathAttributeList = new LinkedList<>(); + boolean isOrigin = false; + boolean isAsPath = false; + boolean isNextHop = false; + boolean isMpReach = false; + boolean isMpUnReach = false; + while (cb.readableBytes() > 0) { + cb.markReaderIndex(); + byte flags = cb.readByte(); + byte typeCode = cb.readByte(); + cb.resetReaderIndex(); + switch (typeCode) { + case Origin.ORIGIN_TYPE: + pathAttribute = Origin.read(cb); + isOrigin = ((Origin) pathAttribute).isOriginSet(); + break; + case AsPath.ASPATH_TYPE: + pathAttribute = AsPath.read(cb); + isAsPath = ((AsPath) pathAttribute).isaspathSet(); + break; + case As4Path.AS4PATH_TYPE: + pathAttribute = As4Path.read(cb); + break; + case NextHop.NEXTHOP_TYPE: + pathAttribute = NextHop.read(cb); + isNextHop = ((NextHop) pathAttribute).isNextHopSet(); + break; + case Med.MED_TYPE: + pathAttribute = Med.read(cb); + break; + case LocalPref.LOCAL_PREF_TYPE: + pathAttribute = LocalPref.read(cb); + break; + case MpReachNlri.MPREACHNLRI_TYPE: + pathAttribute = MpReachNlri.read(cb); + isMpReach = ((MpReachNlri) pathAttribute).isMpReachNlriSet(); + break; + case MpUnReachNlri.MPUNREACHNLRI_TYPE: + pathAttribute = MpUnReachNlri.read(cb); + isMpUnReach = ((MpUnReachNlri) pathAttribute) + .isMpUnReachNlriSet(); + break; + case LINK_STATE_ATTRIBUTE_TYPE: + //TODO: To be merged later + break; + default: + //skip bytes for unsupported attribute types + UnSupportedAttribute.read(cb); + } + pathAttributeList.add(pathAttribute); + } + + checkMandatoryAttr(isOrigin, isAsPath, isNextHop, isMpReach, isMpUnReach); + //TODO:if mp_reach or mp_unreach not present ignore the packet + return new BgpPathAttributes(pathAttributeList); + } + + /** + * Checks mandatory attributes are presents, if not present throws exception. + * + * @param isOrigin say whether origin attribute is present + * @param isAsPath say whether aspath attribute is present + * @param isNextHop say whether nexthop attribute is present + * @param isMpReach say whether mpreach attribute is present + * @param isMpUnReach say whether mpunreach attribute is present + * @throws BgpParseException if mandatory path attribute is not present + */ + public static void checkMandatoryAttr(boolean isOrigin, boolean isAsPath, + boolean isNextHop, boolean isMpReach, boolean isMpUnReach) + throws BgpParseException { + // Mandatory attributes validation not required for MP_UNREACH + if (isMpUnReach) { + return; + } + + if (!isOrigin) { + log.debug("Mandatory Attributes not Present"); + Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, + Origin.ORIGIN_TYPE); + } + if (!isAsPath) { + log.debug("Mandatory Attributes not Present"); + Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, + AsPath.ASPATH_TYPE); + } + if (!isMpUnReach && !isMpReach && !isNextHop) { + log.debug("Mandatory Attributes not Present"); + Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, + NextHop.NEXTHOP_TYPE); + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("pathAttribute", pathAttribute) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java new file mode 100644 index 00000000..4d6af594 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java @@ -0,0 +1,285 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol.ver4; + +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.IpPrefix; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpUpdateMsg; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.util.Validation; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * BGP Update Message: UPDATE messages are used to transfer routing information + * between BGP peers. The information in the UPDATE message is used by core to + * construct a graph + */ +public class BgpUpdateMsgVer4 implements BgpUpdateMsg { + + /* 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + + + | Marker | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Withdrawn Routes Length (2 octets) | + +-----------------------------------------------------+ + | Withdrawn Routes (variable) | + +-----------------------------------------------------+ + | Total Path Attribute Length (2 octets) | + +-----------------------------------------------------+ + | Path Attributes (variable) | + +-----------------------------------------------------+ + | Network Layer Reachability Information (variable) | + +-----------------------------------------------------+ + REFERENCE : RFC 4271 + */ + + protected static final Logger log = LoggerFactory + .getLogger(BgpUpdateMsgVer4.class); + + public static final byte PACKET_VERSION = 4; + //Withdrawn Routes Length(2) + Total Path Attribute Length(2) + public static final int PACKET_MINIMUM_LENGTH = 4; + public static final int BYTE_IN_BITS = 8; + public static final int MIN_LEN_AFTER_WITHDRW_ROUTES = 2; + public static final int MINIMUM_COMMON_HEADER_LENGTH = 19; + public static final BgpType MSG_TYPE = BgpType.UPDATE; + public static final BgpUpdateMsgVer4.Reader READER = new Reader(); + + private List withdrawnRoutes; + private BgpPathAttributes bgpPathAttributes; + private BgpHeader bgpHeader; + private List nlri; + + /** + * Constructor to initialize parameters for BGP Update message. + * + * @param bgpHeader in Update message + * @param withdrawnRoutes withdrawn routes + * @param bgpPathAttributes BGP Path attributes + * @param nlri Network Layer Reachability Information + */ + public BgpUpdateMsgVer4(BgpHeader bgpHeader, List withdrawnRoutes, + BgpPathAttributes bgpPathAttributes, List nlri) { + this.bgpHeader = bgpHeader; + this.withdrawnRoutes = withdrawnRoutes; + this.bgpPathAttributes = bgpPathAttributes; + this.nlri = nlri; + } + + /** + * Reader reads BGP Update Message from the channel buffer. + */ + static class Reader implements BgpMessageReader { + + @Override + public BgpUpdateMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) + throws BgpParseException { + + if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength()); + } + + LinkedList withDrwRoutes = new LinkedList<>(); + LinkedList nlri = new LinkedList<>(); + BgpPathAttributes bgpPathAttributes = new BgpPathAttributes(); + // Reading Withdrawn Routes Length + Short withDrwLen = cb.readShort(); + + if (cb.readableBytes() < withDrwLen) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, + cb.readableBytes()); + } + ChannelBuffer tempCb = cb.readBytes(withDrwLen); + if (withDrwLen != 0) { + // Parsing WithdrawnRoutes + withDrwRoutes = parseWithdrawnRoutes(tempCb); + } + if (cb.readableBytes() < MIN_LEN_AFTER_WITHDRW_ROUTES) { + log.debug("Bgp Path Attribute len field not present"); + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); + } + + // Reading Total Path Attribute Length + short totPathAttrLen = cb.readShort(); + int len = withDrwLen + totPathAttrLen + PACKET_MINIMUM_LENGTH; + if (len > bgpHeader.getLength()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null); + } + if (totPathAttrLen != 0) { + // Parsing BGPPathAttributes + if (cb.readableBytes() < totPathAttrLen) { + Validation + .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, + cb.readableBytes()); + } + tempCb = cb.readBytes(totPathAttrLen); + bgpPathAttributes = BgpPathAttributes.read(tempCb); + } + if (cb.readableBytes() > 0) { + // Parsing NLRI + nlri = parseNlri(cb); + } + return new BgpUpdateMsgVer4(bgpHeader, withDrwRoutes, + bgpPathAttributes, nlri); + } + } + + /** + * Parses NLRI from channel buffer. + * + * @param cb channelBuffer + * @return list of IP Prefix + * @throws BgpParseException while parsing NLRI + */ + public static LinkedList parseNlri(ChannelBuffer cb) + throws BgpParseException { + LinkedList nlri = new LinkedList<>(); + while (cb.readableBytes() > 0) { + int length = cb.readByte(); + IpPrefix ipPrefix; + if (length == 0) { + byte[] prefix = new byte[] {0}; + ipPrefix = Validation.bytesToPrefix(prefix, length); + nlri.add(ipPrefix); + } else { + int len = length / BYTE_IN_BITS; + int reminder = length % BYTE_IN_BITS; + if (reminder > 0) { + len = len + 1; + } + if (cb.readableBytes() < len) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, + cb.readableBytes()); + } + byte[] prefix = new byte[len]; + cb.readBytes(prefix, 0, len); + ipPrefix = Validation.bytesToPrefix(prefix, length); + nlri.add(ipPrefix); + } + } + return nlri; + } + + /** + * Parsing withdrawn routes from channel buffer. + * + * @param cb channelBuffer + * @return list of IP prefix + * @throws BgpParseException while parsing withdrawn routes + */ + public static LinkedList parseWithdrawnRoutes(ChannelBuffer cb) + throws BgpParseException { + LinkedList withDrwRoutes = new LinkedList<>(); + while (cb.readableBytes() > 0) { + int length = cb.readByte(); + IpPrefix ipPrefix; + if (length == 0) { + byte[] prefix = new byte[] {0}; + ipPrefix = Validation.bytesToPrefix(prefix, length); + withDrwRoutes.add(ipPrefix); + } else { + int len = length / BYTE_IN_BITS; + int reminder = length % BYTE_IN_BITS; + if (reminder > 0) { + len = len + 1; + } + if (cb.readableBytes() < len) { + Validation + .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.MALFORMED_ATTRIBUTE_LIST, + cb.readableBytes()); + } + byte[] prefix = new byte[len]; + cb.readBytes(prefix, 0, len); + ipPrefix = Validation.bytesToPrefix(prefix, length); + withDrwRoutes.add(ipPrefix); + } + } + return withDrwRoutes; + } + + @Override + public BgpVersion getVersion() { + return BgpVersion.BGP_4; + } + + @Override + public BgpType getType() { + return BgpType.UPDATE; + } + + @Override + public void writeTo(ChannelBuffer channelBuffer) throws BgpParseException { + //Not to be implemented as of now + } + + @Override + public BgpPathAttributes bgpPathAttributes() { + return this.bgpPathAttributes; + } + + @Override + public List withdrawnRoutes() { + return withdrawnRoutes; + } + + @Override + public List nlri() { + return nlri; + } + + @Override + public BgpHeader getHeader() { + return this.bgpHeader; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("bgpHeader", bgpHeader) + .add("withDrawnRoutes", withdrawnRoutes) + .add("nlri", nlri) + .add("bgpPathAttributes", bgpPathAttributes) + .toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java new file mode 100755 index 00000000..fb8c67c0 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * BGP Protocol specific details of version 4. + */ +package org.onosproject.bgpio.protocol.ver4; \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java new file mode 100644 index 00000000..842c6f02 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AreaIDTlv.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.common.base.MoreObjects; + +/** + * Provides AreaID Tlv which contains opaque value (32 Bit Area-ID). + */ +public class AreaIDTlv implements BgpValueType { + + /* Reference :draft-ietf-idr-ls-distribution-11 + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type= 514 | Length=4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | opaque value (32 Bit Area-ID) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + public static final short TYPE = 514; + public static final short LENGTH = 4; + + private final int areaID; + + /** + * Constructor to initialize areaID. + * + * @param areaID of BGP AreaID Tlv + */ + public AreaIDTlv(int areaID) { + this.areaID = areaID; + } + + /** + * Returns object of this class with specified areaID. + * + * @param areaID opaque value of area id + * @return object of AreaIDTlv + */ + public static AreaIDTlv of(final int areaID) { + return new AreaIDTlv(areaID); + } + + /** + * Returns opaque value of area id. + * + * @return opaque value of area id + */ + public int getAreaID() { + return areaID; + } + + @Override + public int hashCode() { + return Objects.hash(areaID); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AreaIDTlv) { + AreaIDTlv other = (AreaIDTlv) obj; + return Objects.equals(areaID, other.areaID); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeInt(areaID); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of AreaIDTlv. + * + * @param cb ChannelBuffer + * @return object of AreaIDTlv + */ + public static AreaIDTlv read(ChannelBuffer cb) { + return AreaIDTlv.of(cb.readInt()); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Integer) (this.areaID)).compareTo((Integer) (((AreaIDTlv) o).areaID)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("Value", areaID) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java new file mode 100644 index 00000000..3ceca2ce --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java @@ -0,0 +1,175 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of As4Path BGP Path Attribute. + */ +public class As4Path implements BgpValueType { + private static final Logger log = LoggerFactory.getLogger(AsPath.class); + public static final byte AS4PATH_TYPE = 17; + public static final byte ASNUM_SIZE = 4; + + private List as4pathSet; + private List as4pathSeq; + + /** + * Initialize fields. + */ + public As4Path() { + this.as4pathSeq = null; + this.as4pathSet = null; + } + + /** + * Constructor to initialize parameters. + * + * @param as4pathSet AS4path Set + * @param as4pathSeq AS4path Sequence + */ + public As4Path(List as4pathSet, List as4pathSeq) { + this.as4pathSeq = as4pathSeq; + this.as4pathSet = as4pathSet; + } + + /** + * Reads from the channel buffer and parses As4Path. + * + * @param cb ChannelBuffer + * @return object of As4Path + * @throws BgpParseException while parsing As4Path + */ + public static As4Path read(ChannelBuffer cb) throws BgpParseException { + List as4pathSet = new ArrayList<>(); + List as4pathSeq = new ArrayList<>(); + ChannelBuffer tempCb = cb.copy(); + Validation validation = Validation.parseAttributeHeader(cb); + + if (cb.readableBytes() < validation.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + validation.getLength()); + } + //if fourth bit is set length is read as short otherwise as byte , len includes type, length and value + int len = validation.isShort() ? validation.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : validation + .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + ChannelBuffer tempBuf = cb.readBytes(validation.getLength()); + while (tempBuf.readableBytes() > 0) { + byte pathSegType = tempBuf.readByte(); + //no of ASes + byte pathSegLen = tempBuf.readByte(); + //length = no of Ases * ASnum size (4 bytes) + int length = pathSegLen * ASNUM_SIZE; + if (tempBuf.readableBytes() < length) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length); + } + ChannelBuffer aspathBuf = tempBuf.readBytes(length); + while (aspathBuf.readableBytes() > 0) { + int asNum; + asNum = aspathBuf.readInt(); + switch (pathSegType) { + case AsPath.ASPATH_SET_TYPE: + as4pathSet.add(asNum); + break; + case AsPath.ASPATH_SEQ_TYPE: + as4pathSeq.add(asNum); + break; + default: log.debug("Other type Not Supported:" + pathSegType); + } + } + } + return new As4Path(as4pathSet, as4pathSeq); + } + + @Override + public short getType() { + return AS4PATH_TYPE; + } + + /** + * Returns list of ASNum in AS4path Sequence. + * + * @return list of ASNum in AS4path Sequence + */ + public List as4PathSEQ() { + return this.as4pathSeq; + } + + /** + * Returns list of ASNum in AS4path Set. + * + * @return list of ASNum in AS4path Set + */ + public List as4PathSET() { + return this.as4pathSet; + } + + @Override + public int hashCode() { + return Objects.hash(as4pathSet, as4pathSeq); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof As4Path) { + As4Path other = (As4Path) obj; + return Objects.equals(as4pathSet, other.as4pathSet) && Objects.equals(as4pathSeq, other.as4pathSeq); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("as4pathSet", as4pathSet) + .add("as4pathSeq", as4pathSeq) + .toString(); + } + + @Override + public int write(ChannelBuffer cb) { + //Not required to Implement as of now + return 0; + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java new file mode 100644 index 00000000..2a050c44 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java @@ -0,0 +1,214 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of AsPath mandatory BGP Path Attribute. + */ +public class AsPath implements BgpValueType { + /** + * Enum to provide AS types. + */ + public enum ASTYPE { + AS_SET(1), AS_SEQUENCE(2), AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4); + int value; + + /** + * Assign val with the value as the AS type. + * + * @param val AS type + */ + ASTYPE(int val) { + value = val; + } + + /** + * Returns value of AS type. + * + * @return AS type + */ + public byte type() { + return (byte) value; + } + } + + private static final Logger log = LoggerFactory.getLogger(AsPath.class); + public static final byte ASPATH_TYPE = 2; + public static final byte ASPATH_SET_TYPE = 1; + public static final byte ASPATH_SEQ_TYPE = 2; + public static final byte ASNUM_SIZE = 2; + + private boolean isAsPath = false; + private List aspathSet; + private List aspathSeq; + + /** + * Initialize Fields. + */ + public AsPath() { + this.aspathSeq = null; + this.aspathSet = null; + } + + /** + * Constructor to initialize parameters. + * + * @param aspathSet ASpath Set type + * @param aspathSeq ASpath Sequence type + */ + public AsPath(List aspathSet, List aspathSeq) { + this.aspathSeq = aspathSeq; + this.aspathSet = aspathSet; + this.isAsPath = true; + } + + /** + * Reads from the channel buffer and parses AsPath. + * + * @param cb ChannelBuffer + * @return object of AsPath + * @throws BgpParseException while parsing AsPath + */ + public static AsPath read(ChannelBuffer cb) throws BgpParseException { + List aspathSet = new ArrayList<>(); + List aspathSeq = new ArrayList<>(); + ChannelBuffer tempCb = cb.copy(); + Validation validation = Validation.parseAttributeHeader(cb); + + if (cb.readableBytes() < validation.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + validation.getLength()); + } + //if fourth bit is set, length is read as short otherwise as byte , len includes type, length and value + int len = validation.isShort() ? validation.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : validation + .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + ChannelBuffer tempBuf = cb.readBytes(validation.getLength()); + while (tempBuf.readableBytes() > 0) { + byte pathSegType = tempBuf.readByte(); + //no of ASes + byte pathSegLen = tempBuf.readByte(); + int length = pathSegLen * ASNUM_SIZE; + if (tempBuf.readableBytes() < length) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length); + } + ChannelBuffer aspathBuf = tempBuf.readBytes(length); + while (aspathBuf.readableBytes() > 0) { + short asNum; + asNum = aspathBuf.readShort(); + switch (pathSegType) { + case ASPATH_SET_TYPE: + aspathSet.add(asNum); + break; + case ASPATH_SEQ_TYPE: + aspathSeq.add(asNum); + break; + default: log.debug("Other type Not Supported:" + pathSegType); + } + } + } + return new AsPath(aspathSet, aspathSeq); + } + + @Override + public short getType() { + return ASPATH_TYPE; + } + + /** + * Returns whether ASpath path attribute is present. + * + * @return whether ASpath path attribute is present + */ + public boolean isaspathSet() { + return this.isAsPath; + } + + /** + * Returns list of ASNum in ASpath Sequence. + * + * @return list of ASNum in ASpath Sequence + */ + public List asPathSeq() { + return this.aspathSeq; + } + + /** + * Returns list of ASNum in ASpath SET. + * + * @return list of ASNum in ASpath SET + */ + public List asPathSet() { + return this.aspathSet; + } + + @Override + public int hashCode() { + return Objects.hash(aspathSet, aspathSeq); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof AsPath) { + AsPath other = (AsPath) obj; + return Objects.equals(aspathSet, other.aspathSet) && Objects.equals(aspathSeq, other.aspathSeq); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("aspathSet", aspathSet) + .add("aspathSeq", aspathSeq) + .toString(); + } + + @Override + public int write(ChannelBuffer cb) { + //Not required to Implement as of now + return 0; + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java new file mode 100644 index 00000000..119926c8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AutonomousSystemTlv.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.common.base.MoreObjects; + +/** + * Provides Autonomous System Tlv which contains opaque value (32 Bit AS Number). + */ +public class AutonomousSystemTlv implements BgpValueType { + + /* Reference :draft-ietf-idr-ls-distribution-11 + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type= 512 | Length=4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | opaque value (32 Bit AS Number) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + public static final short TYPE = 512; + public static final short LENGTH = 4; + + private final int asNum; + + /** + * Constructor to initialize asNum. + * + * @param asNum 32 Bit AS Number + */ + public AutonomousSystemTlv(int asNum) { + this.asNum = asNum; + } + + /** + * Returns object of this class with specified asNum. + * + * @param asNum 32 Bit AS Number + * @return object of AutonomousSystemTlv + */ + public static AutonomousSystemTlv of(final int asNum) { + return new AutonomousSystemTlv(asNum); + } + + /** + * Returns opaque value of AS Number. + * + * @return opaque value of AS Number + */ + public int getAsNum() { + return asNum; + } + + @Override + public int hashCode() { + return Objects.hash(asNum); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AutonomousSystemTlv) { + AutonomousSystemTlv other = (AutonomousSystemTlv) obj; + return Objects.equals(asNum, other.asNum); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeInt(asNum); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of AutonomousSystemTlv. + * + * @param c ChannelBuffer + * @return object of AutonomousSystemTlv + */ + public static AutonomousSystemTlv read(ChannelBuffer c) { + return AutonomousSystemTlv.of(c.readInt()); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Integer) (this.asNum)).compareTo((Integer) (((AutonomousSystemTlv) o).asNum)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("asNum", asNum) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java new file mode 100644 index 00000000..c0932ebe --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpErrorType.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +/** + * BgpErrorType class defines all errorCodes and error Subcodes required for Notification message. + */ +public final class BgpErrorType { + private BgpErrorType() { + } + + //Error Codes + public static final byte MESSAGE_HEADER_ERROR = 1; + public static final byte OPEN_MESSAGE_ERROR = 2; + public static final byte UPDATE_MESSAGE_ERROR = 3; + public static final byte HOLD_TIMER_EXPIRED = 4; + public static final byte FINITE_STATE_MACHINE_ERROR = 5; + public static final byte CEASE = 6; + + //Message Header Error subcodes + public static final byte CONNECTION_NOT_SYNCHRONIZED = 1; + public static final byte BAD_MESSAGE_LENGTH = 2; + public static final byte BAD_MESSAGE_TYPE = 3; + + //OPEN Message Error subcodes + public static final byte UNSUPPORTED_VERSION_NUMBER = 1; + public static final byte BAD_PEER_AS = 2; + public static final byte BAD_BGP_IDENTIFIER = 3; + public static final byte UNSUPPORTED_OPTIONAL_PARAMETER = 4; + public static final byte UNACCEPTABLE_HOLD_TIME = 5; + public static final byte UNSUPPORTED_CAPABILITY = 7; + + //UPDATE Message Error subcodes + public static final byte MALFORMED_ATTRIBUTE_LIST = 1; + public static final byte UNRECOGNIZED_WELLKNOWN_ATTRIBUTE = 2; + public static final byte MISSING_WELLKNOWN_ATTRIBUTE = 3; + public static final byte ATTRIBUTE_FLAGS_ERROR = 4; + public static final byte ATTRIBUTE_LENGTH_ERROR = 5; + public static final byte INVALID_ORIGIN_ATTRIBUTE = 6; + public static final byte INVALID_NEXTHOP_ATTRIBUTE = 8; + public static final byte OPTIONAL_ATTRIBUTE_ERROR = 9; + public static final byte INVALID_NETWORK_FIELD = 10; + public static final byte MALFORMED_ASPATH = 11; + + //FSM Error subcodes + public static final byte UNSPECIFIED_ERROR = 0; + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE = 1; + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE = 2; + public static final byte RECEIVE_UNEXPECTED_MESSAGE_IN_ESTABLISHED_STATE = 3; + + //Cease Error subcodes + public static final byte MAXIMUM_NUMBER_OF_PREFIXES_REACHED = 1; + public static final byte ADMINISTRATIVE_SHUTDOWN = 2; + public static final byte PEER_DECONFIGURED = 3; + public static final byte ADMINISTRATIVE_RESET = 4; + public static final byte CONNECTION_REJECTED = 5; + public static final byte OTHER_CONFIGURATION_CHANGE = 6; + public static final byte CONNECTION_COLLISION_RESOLUTION = 7; + public static final byte OUT_OF_RESOURCES = 8; +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java new file mode 100755 index 00000000..ad637753 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpHeader.java @@ -0,0 +1,161 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides BGP Message Header which is common for all the Messages. + */ + +public class BgpHeader { + + /* 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + + + | Marker | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + protected static final Logger log = LoggerFactory.getLogger(BgpHeader.class); + + public static final int MARKER_LENGTH = 16; + public static final short DEFAULT_HEADER_LENGTH = 19; + + private byte[] marker; + private byte type; + private short length; + + /** + * Reset fields. + */ + public BgpHeader() { + this.marker = null; + this.length = 0; + this.type = 0; + } + + /** + * Constructors to initialize parameters. + * + * @param marker field in BGP header + * @param length message length + * @param type message type + */ + public BgpHeader(byte[] marker, short length, byte type) { + this.marker = marker; + this.length = length; + this.type = type; + } + + /** + * Sets marker field. + * + * @param value marker field + */ + public void setMarker(byte[] value) { + this.marker = value; + } + + /** + * Sets message type. + * + * @param value message type + */ + public void setType(byte value) { + this.type = value; + } + + /** + * Sets message length. + * + * @param value message length + */ + public void setLength(short value) { + this.length = value; + } + + /** + * Returns message length. + * + * @return message length + */ + public short getLength() { + return this.length; + } + + /** + * Returns message marker. + * + * @return message marker + */ + public byte[] getMarker() { + return this.marker; + } + + /** + * Returns message type. + * + * @return message type + */ + public byte getType() { + return this.type; + } + + /** + * Writes Byte stream of BGP header to channel buffer. + * + * @param cb ChannelBuffer + * @return length index of message header + */ + public int write(ChannelBuffer cb) { + + cb.writeBytes(getMarker(), 0, MARKER_LENGTH); + + int headerLenIndex = cb.writerIndex(); + cb.writeShort((short) 0); + cb.writeByte(type); + + return headerLenIndex; + } + + /** + * Read from channel buffer and Returns BGP header. + * + * @param cb ChannelBuffer + * @return object of BGPHeader + */ + public static BgpHeader read(ChannelBuffer cb) { + + byte[] marker = new byte[MARKER_LENGTH]; + byte type; + short length; + cb.readBytes(marker, 0, MARKER_LENGTH); + length = cb.readShort(); + type = cb.readByte(); + return new BgpHeader(marker, length, type); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java new file mode 100644 index 00000000..58645d4f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpLSIdentifierTlv.java @@ -0,0 +1,131 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.common.base.MoreObjects; + +/** + * Provides BGPLSIdentifier Tlv which contains opaque value (32 Bit BGPLS-Identifier). + */ +public class BgpLSIdentifierTlv implements BgpValueType { + + /* Reference :draft-ietf-idr-ls-distribution-11 + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type= 513 | Length=4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | opaque value (32 Bit BGPLS-Identifier) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + public static final short TYPE = 513; + public static final short LENGTH = 4; + + private final int bgpLsIdentifier; + + /** + * Constructor to initialize bgpLsIdentifier. + * + * @param bgpLsIdentifier BGPLS-Identifier + */ + public BgpLSIdentifierTlv(int bgpLsIdentifier) { + this.bgpLsIdentifier = bgpLsIdentifier; + } + + /** + * Returns object of this class with specified bgpLsIdentifier. + * + * @param bgpLsIdentifier BGPLS-Identifier + * @return BGPLS-Identifier + */ + public static BgpLSIdentifierTlv of(final int bgpLsIdentifier) { + return new BgpLSIdentifierTlv(bgpLsIdentifier); + } + + /** + * Returns opaque value of BGPLS-Identifier. + * + * @return opaque value of BGPLS-Identifier + */ + public int getBgpLsIdentifier() { + return bgpLsIdentifier; + } + + @Override + public int hashCode() { + return Objects.hash(bgpLsIdentifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLSIdentifierTlv) { + BgpLSIdentifierTlv other = (BgpLSIdentifierTlv) obj; + return Objects.equals(bgpLsIdentifier, other.bgpLsIdentifier); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeInt(bgpLsIdentifier); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and parses BGPLS Identifier TLV. + * + * @param cb ChannelBuffer + * @return object of BGPLSIdentifierTlv + */ + public static BgpLSIdentifierTlv read(ChannelBuffer cb) { + return BgpLSIdentifierTlv.of(cb.readInt()); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Integer) (this.bgpLsIdentifier)).compareTo((Integer) (((BgpLSIdentifierTlv) o).bgpLsIdentifier)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("Value", bgpLsIdentifier) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java new file mode 100644 index 00000000..af7f4b75 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpValueType.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * Abstraction which Provides the BGP of TLV format. + */ +public interface BgpValueType { + /** + * Returns the Type of BGP Message. + * + * @return short value of type + */ + short getType(); + + /** + * Writes the byte Stream of BGP Message to channel buffer. + * + * @param cb channel buffer + * @return length written to channel buffer + */ + int write(ChannelBuffer cb); + + /** + * Compares two objects. + * + * @param o object + * @return result after comparing two objects + */ + int compareTo(Object o); +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java new file mode 100644 index 00000000..59db3318 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java @@ -0,0 +1,120 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides FourOctetAsNumCapabilityTlv Capability Tlv. + */ +public class FourOctetAsNumCapabilityTlv implements BgpValueType { + + /** + * support to indicate its support for four-octet AS numbers -CAPABILITY TLV format. + */ + protected static final Logger log = LoggerFactory + .getLogger(FourOctetAsNumCapabilityTlv.class); + + public static final byte TYPE = 65; + public static final byte LENGTH = 4; + + private final int rawValue; + + /** + * constructor to initialize rawValue. + * @param rawValue FourOctetAsNumCapabilityTlv + */ + public FourOctetAsNumCapabilityTlv(int rawValue) { + this.rawValue = rawValue; + } + + /** + * constructor to initialize raw. + * @param raw AS number + * @return object of FourOctetAsNumCapabilityTlv + */ + public static FourOctetAsNumCapabilityTlv of(final int raw) { + return new FourOctetAsNumCapabilityTlv(raw); + } + + /** + * Returns value of TLV. + * @return int value of rawValue + */ + public int getInt() { + return rawValue; + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int hashCode() { + return Objects.hash(rawValue); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof FourOctetAsNumCapabilityTlv) { + FourOctetAsNumCapabilityTlv other = (FourOctetAsNumCapabilityTlv) obj; + return Objects.equals(rawValue, other.rawValue); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeByte(TYPE); + cb.writeByte(LENGTH); + cb.writeInt(rawValue); + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of FourOctetAsNumCapabilityTlv. + * @param cb type of channel buffer + * @return object of FourOctetAsNumCapabilityTlv + */ + public static FourOctetAsNumCapabilityTlv read(ChannelBuffer cb) { + return FourOctetAsNumCapabilityTlv.of(cb.readInt()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("Value", rawValue).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java new file mode 100644 index 00000000..d97537e8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPReachabilityInformationTlv.java @@ -0,0 +1,165 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.IpPrefix; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; + +/** + * Provides IP Reachability InformationTlv Tlv which contains IP Prefix. + */ +public class IPReachabilityInformationTlv implements BgpValueType { + + /* + * Reference :draft-ietf-idr-ls-distribution-11 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prefix Length | IP Prefix (variable) // + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 14: IP Reachability Information TLV Format + */ + + public static final short TYPE = 265; + public static final int ONE_BYTE_LEN = 8; + + private byte prefixLen; + private byte[] ipPrefix; + public short length; + + /** + * Constructor to initialize parameters. + * + * @param prefixLen length of IP Prefix + * @param ipPrefix IP Prefix + * @param length length of value field + */ + public IPReachabilityInformationTlv(byte prefixLen, byte[] ipPrefix, short length) { + this.ipPrefix = ipPrefix; + this.prefixLen = prefixLen; + this.length = length; + } + + /** + * Returns IP Prefix. + * + * @return IP Prefix + */ + public IpPrefix getPrefixValue() { + IpPrefix prefix = Validation.bytesToPrefix(ipPrefix, prefixLen); + return prefix; + } + + /** + * Returns IP Prefix length. + * + * @return IP Prefix length + */ + public byte getPrefixLen() { + return this.prefixLen; + } + + @Override + public int hashCode() { + return Objects.hash(Arrays.hashCode(ipPrefix), prefixLen); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof IPReachabilityInformationTlv) { + IPReachabilityInformationTlv other = (IPReachabilityInformationTlv) obj; + return Objects.equals(prefixLen, other.prefixLen) && Arrays.equals(ipPrefix, other.ipPrefix); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeShort(TYPE); + cb.writeShort(length); + cb.writeByte(prefixLen); + cb.writeBytes(ipPrefix); + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of IPReachabilityInformationTlv. + * + * @param cb ChannelBuffer + * @param length of value field + * @return object of IPReachabilityInformationTlv + */ + public static IPReachabilityInformationTlv read(ChannelBuffer cb, short length) { + byte preficLen = cb.readByte(); + byte[] prefix; + if (preficLen == 0) { + prefix = new byte[] {0}; + } else { + int len = preficLen / ONE_BYTE_LEN; + int reminder = preficLen % ONE_BYTE_LEN; + if (reminder > 0) { + len = len + 1; + } + prefix = new byte[len]; + cb.readBytes(prefix, 0, len); + } + return IPReachabilityInformationTlv.of(preficLen, prefix, length); + } + + public static IPReachabilityInformationTlv of(final byte preficLen, final byte[] prefix, final short length) { + return new IPReachabilityInformationTlv(preficLen, prefix, length); + } + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + ByteBuffer value1 = ByteBuffer.wrap(this.ipPrefix); + ByteBuffer value2 = ByteBuffer.wrap(((IPReachabilityInformationTlv) o).ipPrefix); + return value1.compareTo(value2); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", length) + .add("Prefixlength", getPrefixLen()) + .add("Prefixvalue", getPrefixValue()) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java new file mode 100644 index 00000000..4efde70e --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv4AddressTlv.java @@ -0,0 +1,133 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.net.InetAddress; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +/** + * Provides Implementation of IPv4AddressTlv. + */ +public class IPv4AddressTlv implements BgpValueType { + private static final int LENGTH = 4; + + private Ip4Address address; + private short type; + + /** + * Constructor to initialize parameters. + * + * @param address Ipv4 address of interface/neighbor + * @param type address type + */ + public IPv4AddressTlv(Ip4Address address, short type) { + this.address = Preconditions.checkNotNull(address); + this.type = type; + } + + /** + * Returns Ipv4 address of interface/neighbor. + * + * @return Ipv4 address of interface/neighbor + */ + public Ip4Address address() { + return address; + } + + @Override + public short getType() { + return this.type; + } + + @Override + public int hashCode() { + return Objects.hash(address); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof IPv4AddressTlv) { + IPv4AddressTlv other = (IPv4AddressTlv) obj; + return Objects.equals(this.address, other.address) && Objects.equals(this.type, other.type); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeShort(type); + cb.writeShort(LENGTH); + cb.writeInt(address.toInt()); + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of IPv4AddressTlv. + * + * @param cb channelBuffer + * @param type address type + * @return object of IPv4AddressTlv + * @throws BgpParseException while parsing IPv4AddressTlv + */ + public static IPv4AddressTlv read(ChannelBuffer cb, short type) throws BgpParseException { + InetAddress ipAddress = Validation.toInetAddress(LENGTH, cb); + if (ipAddress.isMulticastAddress()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); + } + Ip4Address address = Ip4Address.valueOf(ipAddress); + return IPv4AddressTlv.of(address, type); + } + + /** + * Returns object of this class with specified values. + * + * @param address Ipv4 interface/neighbor Address + * @param type says Ipv4 address of interface/neighbor tlv type + * @return object of this class + */ + public static IPv4AddressTlv of(final Ip4Address address , final short type) { + return new IPv4AddressTlv(address, type); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Ip4Address) (this.address)).compareTo((Ip4Address) (((IPv4AddressTlv) o).address)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("type", type) + .add("LENGTH", LENGTH) + .add("address", address) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java new file mode 100644 index 00000000..087cd5c6 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IPv6AddressTlv.java @@ -0,0 +1,133 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.net.InetAddress; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip6Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +/** + * Provides Implementation of IPv6AddressTlv. + */ +public class IPv6AddressTlv implements BgpValueType { + private static final int LENGTH = 16; + + private final Ip6Address address; + private short type; + + /** + * Constructor to initialize parameters. + * + * @param address Ipv6 address of interface/neighbor + * @param type address type + */ + public IPv6AddressTlv(Ip6Address address, short type) { + this.address = Preconditions.checkNotNull(address); + this.type = type; + } + + /** + * Returns Ipv6 address of interface/neighbor. + * + * @return Ipv6 address of interface/neighbor + */ + public Ip6Address address() { + return address; + } + + @Override + public short getType() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(address); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof IPv6AddressTlv) { + IPv6AddressTlv other = (IPv6AddressTlv) obj; + return Objects.equals(this.address, other.address) && Objects.equals(this.type, other.type); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeShort(type); + cb.writeShort(LENGTH); + cb.writeBytes(address.toOctets()); + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of IPv6AddressTlv. + * + * @param cb channelBuffer + * @param type address type + * @return object of IPv6AddressTlv + * @throws BgpParseException while parsing IPv6AddressTlv + */ + public static IPv6AddressTlv read(ChannelBuffer cb, short type) throws BgpParseException { + InetAddress ipAddress = Validation.toInetAddress(LENGTH, cb); + if (ipAddress.isMulticastAddress()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); + } + Ip6Address address = Ip6Address.valueOf(ipAddress); + return IPv6AddressTlv.of(address, type); + } + + /** + * Returns object of this class with specified values. + * + * @param address Ipv6 interface/neighbor address + * @param type says Ipv6 address of interface/neighbor tlv type + * @return object of this class + */ + public static IPv6AddressTlv of(final Ip6Address address , final short type) { + return new IPv6AddressTlv(address, type); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Ip6Address) (this.address)).compareTo((Ip6Address) (((IPv6AddressTlv) o).address)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("type", type) + .add("LENGTH", LENGTH) + .add("address", address) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java new file mode 100644 index 00000000..427aa929 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsNonPseudonode.java @@ -0,0 +1,124 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.protocol.IGPRouterID; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of IsIsNonPseudonode Tlv. + */ +public class IsIsNonPseudonode implements IGPRouterID, BgpValueType { + public static final short TYPE = 515; + public static final short LENGTH = 6; + + private final byte[] isoNodeID; + + /** + * Constructor to initialize isoNodeID. + * + * @param isoNodeID ISO system-ID + */ + public IsIsNonPseudonode(byte[] isoNodeID) { + this.isoNodeID = Arrays.copyOf(isoNodeID, isoNodeID.length); + } + + /** + * Returns object of this class with specified isoNodeID. + * + * @param isoNodeID ISO system-ID + * @return object of IsIsNonPseudonode + */ + public static IsIsNonPseudonode of(final byte[] isoNodeID) { + return new IsIsNonPseudonode(isoNodeID); + } + + /** + * Returns ISO NodeID. + * + * @return ISO NodeID + */ + public byte[] getISONodeID() { + return isoNodeID; + } + + @Override + public int hashCode() { + return Arrays.hashCode(isoNodeID); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof IsIsNonPseudonode) { + IsIsNonPseudonode other = (IsIsNonPseudonode) obj; + return Arrays.equals(isoNodeID, other.isoNodeID); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeBytes(isoNodeID); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of IsIsNonPseudonode. + * + * @param cb ChannelBuffer + * @return object of IsIsNonPseudonode + */ + public static IsIsNonPseudonode read(ChannelBuffer cb) { + byte[] isoNodeID = new byte[LENGTH]; + cb.readBytes(isoNodeID); + return IsIsNonPseudonode.of(isoNodeID); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + ByteBuffer value1 = ByteBuffer.wrap(this.isoNodeID); + ByteBuffer value2 = ByteBuffer.wrap(((IsIsNonPseudonode) o).isoNodeID); + return value1.compareTo(value2); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("ISONodeID", isoNodeID) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java new file mode 100644 index 00000000..094c4382 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/IsIsPseudonode.java @@ -0,0 +1,146 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.protocol.IGPRouterID; + +import com.google.common.base.MoreObjects; + +/** + * Provides implementation of IsIsPseudonode Tlv. + */ +public class IsIsPseudonode implements IGPRouterID, BgpValueType { + public static final short TYPE = 515; + public static final short LENGTH = 7; + + private final byte[] isoNodeID; + private byte psnIdentifier; + + /** + * Constructor to initialize isoNodeID. + * + * @param isoNodeID ISO system-ID + * @param psnIdentifier PSN identifier + */ + public IsIsPseudonode(byte[] isoNodeID, byte psnIdentifier) { + this.isoNodeID = Arrays.copyOf(isoNodeID, isoNodeID.length); + this.psnIdentifier = psnIdentifier; + } + + /** + * Returns object of this class with specified values. + * + * @param isoNodeID ISO system-ID + * @param psnIdentifier PSN identifier + * @return object of IsIsPseudonode + */ + public static IsIsPseudonode of(final byte[] isoNodeID, + final byte psnIdentifier) { + return new IsIsPseudonode(isoNodeID, psnIdentifier); + } + + /** + * Returns ISO NodeID. + * + * @return ISO NodeID + */ + public byte[] getISONodeID() { + return isoNodeID; + } + + /** + * Returns PSN Identifier. + * + * @return PSN Identifier + */ + public byte getPSNIdentifier() { + return this.psnIdentifier; + } + + @Override + public int hashCode() { + return Arrays.hashCode(isoNodeID) & Objects.hash(psnIdentifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof IsIsPseudonode) { + IsIsPseudonode other = (IsIsPseudonode) obj; + return Arrays.equals(isoNodeID, other.isoNodeID) + && Objects.equals(psnIdentifier, other.psnIdentifier); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeBytes(isoNodeID, 0, LENGTH - 1); + c.writeByte(psnIdentifier); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of IsIsPseudonode. + * + * @param cb ChannelBuffer + * @return object of IsIsPseudonode + */ + public static IsIsPseudonode read(ChannelBuffer cb) { + byte[] isoNodeID = new byte[LENGTH - 1]; + cb.readBytes(isoNodeID); + byte psnIdentifier = cb.readByte(); + return IsIsPseudonode.of(isoNodeID, psnIdentifier); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + ByteBuffer value1 = ByteBuffer.wrap(this.isoNodeID); + ByteBuffer value2 = ByteBuffer.wrap(((IsIsPseudonode) o).isoNodeID); + if (value1.compareTo(value2) != 0) { + return value1.compareTo(value2); + } + return ((Byte) (this.psnIdentifier)).compareTo((Byte) (((IsIsPseudonode) o).psnIdentifier)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("isoNodeID", isoNodeID) + .add("psnIdentifier", psnIdentifier) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java new file mode 100644 index 00000000..0c412432 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTlv.java @@ -0,0 +1,142 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of Link Local/Remote IdentifiersTlv. + */ +public class LinkLocalRemoteIdentifiersTlv implements BgpValueType { + public static final short TYPE = 258; + private static final int LENGTH = 8; + + private final int linkLocalIdentifer; + private final int linkRemoteIdentifer; + + /** + * Constructor to initialize parameters. + * + * @param linkLocalIdentifer link local Identifer + * @param linkRemoteIdentifer link remote Identifer + */ + public LinkLocalRemoteIdentifiersTlv(int linkLocalIdentifer, int linkRemoteIdentifer) { + this.linkLocalIdentifer = linkLocalIdentifer; + this.linkRemoteIdentifer = linkRemoteIdentifer; + } + + /** + * Returns link remote Identifer. + * + * @return link remote Identifer + */ + public int getLinkRemoteIdentifier() { + return linkRemoteIdentifer; + } + + /** + * Returns link local Identifer. + * + * @return link local Identifer + */ + public int getLinkLocalIdentifier() { + return linkLocalIdentifer; + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int hashCode() { + return Objects.hash(linkLocalIdentifer, linkRemoteIdentifer); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof LinkLocalRemoteIdentifiersTlv) { + LinkLocalRemoteIdentifiersTlv other = (LinkLocalRemoteIdentifiersTlv) obj; + return Objects.equals(this.linkLocalIdentifer, other.linkLocalIdentifer) + && Objects.equals(this.linkRemoteIdentifer, other.linkRemoteIdentifer); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeShort(TYPE); + cb.writeShort(LENGTH); + cb.writeInt(linkLocalIdentifer); + cb.writeInt(linkRemoteIdentifer); + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of LinkLocalRemoteIdentifiersTlv. + * + * @param cb channelBuffer + * @return object of LinkLocalRemoteIdentifiersTlv + */ + public static LinkLocalRemoteIdentifiersTlv read(ChannelBuffer cb) { + int linkLocalIdentifer = cb.readInt(); + int linkRemoteIdentifer = cb.readInt(); + return LinkLocalRemoteIdentifiersTlv.of(linkLocalIdentifer, linkRemoteIdentifer); + } + + /** + * Returns object of this class with specified link local identifer and link remote identifer. + * + * @param linkLocalIdentifer link local identifier + * @param linkRemoteIdentifer link remote identifier + * @return object of LinkLocalRemoteIdentifiersTlv + */ + public static LinkLocalRemoteIdentifiersTlv of(final int linkLocalIdentifer, final int linkRemoteIdentifer) { + return new LinkLocalRemoteIdentifiersTlv(linkLocalIdentifer, linkRemoteIdentifer); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + int result = ((Integer) (this.linkLocalIdentifer)) + .compareTo((Integer) (((LinkLocalRemoteIdentifiersTlv) o).linkLocalIdentifer)); + if (result != 0) { + return result; + } + return ((Integer) (this.linkRemoteIdentifer)) + .compareTo((Integer) (((LinkLocalRemoteIdentifiersTlv) o).linkRemoteIdentifer)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("TYPE", TYPE) + .add("LENGTH", LENGTH) + .add("linkLocalIdentifer", linkLocalIdentifer) + .add("linkRemoteIdentifer", linkRemoteIdentifer) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java new file mode 100644 index 00000000..cdf6ebeb --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java @@ -0,0 +1,314 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv; +import org.onosproject.bgpio.types.attr.BgpAttrNodeIsIsAreaId; +import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId; +import org.onosproject.bgpio.types.attr.BgpAttrNodeName; +import org.onosproject.bgpio.types.attr.BgpAttrOpaqueNode; +import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV4; +import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV6; +import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric; +import org.onosproject.bgpio.types.attr.BgpLinkAttrIsIsAdminstGrp; +import org.onosproject.bgpio.types.attr.BgpLinkAttrMplsProtocolMask; +import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth; +import org.onosproject.bgpio.types.attr.BgpLinkAttrName; +import org.onosproject.bgpio.types.attr.BgpLinkAttrOpaqLnkAttrib; +import org.onosproject.bgpio.types.attr.BgpLinkAttrProtectionType; +import org.onosproject.bgpio.types.attr.BgpLinkAttrSrlg; +import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric; +import org.onosproject.bgpio.types.attr.BgpLinkAttrUnRsrvdLinkBandwidth; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrExtRouteTag; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrIgpFlags; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrMetric; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrOspfFwdAddr; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrOpaqueData; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrRouteTag; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP Link state attribute. + */ +public class LinkStateAttributes implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(LinkStateAttributes.class); + + /* Node Attributes */ + public static final short ATTR_NODE_MT_TOPOLOGY_ID = 263; + public static final short ATTR_NODE_FLAG_BITS = 1024; + public static final short ATTR_NODE_OPAQUE_NODE = 1025; + public static final short ATTR_NODE_NAME = 1026; + public static final short ATTR_NODE_ISIS_AREA_ID = 1027; + public static final short ATTR_NODE_IPV4_LOCAL_ROUTER_ID = 1028; + public static final short ATTR_NODE_IPV6_LOCAL_ROUTER_ID = 1029; + + /* Link Attributes */ + public static final short ATTR_LINK_IPV4_REMOTE_ROUTER_ID = 1030; + public static final short ATTR_LINK_IPV6_REMOTE_ROUTER_ID = 1031; + public static final short ATTR_LINK_ADMINISTRATIVE_GRPS = 1088; + public static final short ATTR_LINK_MAX_BANDWIDTH = 1089; + public static final short ATTR_LINK_MAX_RES_BANDWIDTH = 1090; + public static final short ATTR_LINK_UNRES_BANDWIDTH = 1091; + public static final short ATTR_LINK_TE_DEFAULT_METRIC = 1092; + public static final short ATTR_LINK_PROTECTION_TYPE = 1093; + public static final short ATTR_LINK_MPLS_PROTOCOL_MASK = 1094; + public static final short ATTR_LINK_IGP_METRIC = 1095; + public static final short ATTR_LINK_SHR_RISK_GRP = 1096; + public static final short ATTR_LINK_OPAQUE_ATTR = 1097; + public static final short ATTR_LINK_NAME_ATTR = 1098; + + /* Prefix Attributes */ + public static final short ATTR_PREFIX_IGP_FLAG = 1152; + public static final short ATTR_PREFIX_ROUTE_TAG = 1153; + public static final short ATTR_PREFIX_EXTENDED_TAG = 1154; + public static final short ATTR_PREFIX_METRIC = 1155; + public static final short ATTR_PREFIX_OSPF_FWD_ADDR = 1156; + public static final short ATTR_PREFIX_OPAQUE_ATTR = 1157; + + public static final byte LINKSTATE_ATTRIB_TYPE = 50; + public static final byte TYPE_AND_LEN = 4; + private boolean isLinkStateAttribute = false; + private List linkStateAttribList; + + /** + * Constructor to reset parameters. + */ + LinkStateAttributes() { + this.linkStateAttribList = null; + } + + /** + * Constructor to initialize parameters. + * + * @param linkStateAttribList Linked list of Link, Node and Prefix TLVs + */ + LinkStateAttributes(List linkStateAttribList) { + this.linkStateAttribList = linkStateAttribList; + this.isLinkStateAttribute = true; + } + + /** + * Returns linked list of Link, Node and Prefix TLVs. + * + * @return linked list of Link, Node and Prefix TLVs + */ + public List linkStateAttributes() { + return this.linkStateAttribList; + } + + /** + * Returns if the Link state attributes are set or not. + * + * @return a boolean value to to check if the LS attributes are set or not + */ + public boolean isLinkStateAttributeSet() { + return this.isLinkStateAttribute; + } + + /** + * Reads the Link state attribute TLVs. + * + * @param cb ChannelBuffer + * @return constructor of LinkStateAttributes + * @throws BgpParseException while parsing link state attributes + */ + public static LinkStateAttributes read(ChannelBuffer cb) + throws BgpParseException { + + ChannelBuffer tempBuf = cb; + Validation parseFlags = Validation.parseAttributeHeader(cb); + int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN + : parseFlags.getLength() + 3; + + ChannelBuffer data = tempBuf.readBytes(len); + if (!parseFlags.getFirstBit() || parseFlags.getSecondBit() + || parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_FLAGS_ERROR, + data); + } + + if (cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.BAD_MESSAGE_LENGTH, + parseFlags.getLength()); + } + + BgpValueType bgpLSAttrib = null; + LinkedList linkStateAttribList; + linkStateAttribList = new LinkedList(); + ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); + while (tempCb.readableBytes() > 0) { + short tlvCodePoint = tempCb.readShort(); + switch (tlvCodePoint) { + + /********* 7 NODE ATTRIBUTES ********/ + case ATTR_NODE_MT_TOPOLOGY_ID: /* 263 Multi-Topology Identifier*/ + bgpLSAttrib = BgpAttrNodeMultiTopologyId.read(tempCb); + break; + + case ATTR_NODE_FLAG_BITS: /*Node flag bit TLV*/ + bgpLSAttrib = BgpAttrNodeFlagBitTlv.read(tempCb); + break; + + case ATTR_NODE_OPAQUE_NODE: /*Opaque Node Attribute*/ + bgpLSAttrib = BgpAttrOpaqueNode.read(tempCb); + break; + + case ATTR_NODE_NAME: /*Node Name*/ + bgpLSAttrib = BgpAttrNodeName.read(tempCb); + break; + + case ATTR_NODE_ISIS_AREA_ID: /*IS-IS Area Identifier TLV*/ + bgpLSAttrib = BgpAttrNodeIsIsAreaId.read(tempCb); + break; + + case ATTR_NODE_IPV4_LOCAL_ROUTER_ID: /*IPv4 Router-ID of Local Node*/ + bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) ATTR_NODE_IPV4_LOCAL_ROUTER_ID); + break; + + case ATTR_NODE_IPV6_LOCAL_ROUTER_ID: /*IPv6 Router-ID of Local Node*/ + bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) ATTR_NODE_IPV6_LOCAL_ROUTER_ID); + break; + + /********* 15 LINK ATTRIBUTES ********/ + + case ATTR_LINK_IPV4_REMOTE_ROUTER_ID: /*IPv4 Router-ID of Remote Node*/ + bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) 1030); + break; + + case ATTR_LINK_IPV6_REMOTE_ROUTER_ID: /*IPv6 Router-ID of Remote Node*/ + bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) 1031); + break; + + case ATTR_LINK_ADMINISTRATIVE_GRPS: /*ISIS Administrative group STLV 3*/ + bgpLSAttrib = BgpLinkAttrIsIsAdminstGrp.read(tempCb); + break; + + case ATTR_LINK_MAX_BANDWIDTH: /*Maximum link bandwidth*/ + bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb, + (short) 1089); + break; + + case ATTR_LINK_MAX_RES_BANDWIDTH: /* Maximum Reservable link bandwidth */ + bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb, + (short) 1090); + break; + + case ATTR_LINK_UNRES_BANDWIDTH: /* UnReserved link bandwidth */ + bgpLSAttrib = BgpLinkAttrUnRsrvdLinkBandwidth + .read(tempCb, (short) 1091); + break; + + case ATTR_LINK_TE_DEFAULT_METRIC: /* TE Default Metric */ + bgpLSAttrib = BgpLinkAttrTeDefaultMetric.read(tempCb); + break; + + case ATTR_LINK_PROTECTION_TYPE:/* Link Protection type */ + bgpLSAttrib = BgpLinkAttrProtectionType.read(tempCb); + break; + + case ATTR_LINK_MPLS_PROTOCOL_MASK: /* MPLS Protocol Mask */ + bgpLSAttrib = BgpLinkAttrMplsProtocolMask.read(tempCb); // 2 + break; + + case ATTR_LINK_IGP_METRIC: /* IGP Metric */ + bgpLSAttrib = BgpLinkAttrIgpMetric.read(tempCb); // 2 + break; + + case ATTR_LINK_SHR_RISK_GRP: /* Shared Risk Link Group */ + bgpLSAttrib = BgpLinkAttrSrlg.read(tempCb); // 3 + break; + + case ATTR_LINK_OPAQUE_ATTR: /* Opaque link attribute */ + bgpLSAttrib = BgpLinkAttrOpaqLnkAttrib.read(tempCb); + break; + + case ATTR_LINK_NAME_ATTR: /* Link Name attribute */ + bgpLSAttrib = BgpLinkAttrName.read(tempCb); + break; + + /********* 6 PREFIX ATTRIBUTES ********/ + + case ATTR_PREFIX_IGP_FLAG: /* IGP Flags */ + bgpLSAttrib = BgpPrefixAttrIgpFlags.read(tempCb); + break; + + case ATTR_PREFIX_ROUTE_TAG: /* Route Tag */ + bgpLSAttrib = BgpPrefixAttrRouteTag.read(tempCb); + break; + + case ATTR_PREFIX_EXTENDED_TAG: /* Extended Tag */ + bgpLSAttrib = BgpPrefixAttrExtRouteTag.read(tempCb); + break; + + case ATTR_PREFIX_METRIC: /* Prefix Metric */ + bgpLSAttrib = BgpPrefixAttrMetric.read(tempCb); + break; + + case ATTR_PREFIX_OSPF_FWD_ADDR: /* OSPF Forwarding Address */ + bgpLSAttrib = BgpPrefixAttrOspfFwdAddr.read(tempCb); + break; + + case ATTR_PREFIX_OPAQUE_ATTR: /* Opaque Prefix Attribute */ + bgpLSAttrib = BgpPrefixAttrOpaqueData.read(tempCb); + break; + + default: + throw new BgpParseException( + "The Bgp-LS Attribute is not supported : " + + tlvCodePoint); + } + + linkStateAttribList.add(bgpLSAttrib); + } + return new LinkStateAttributes(linkStateAttribList); + } + + @Override + public short getType() { + return LINKSTATE_ATTRIB_TYPE; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("linkStateAttribList", linkStateAttribList).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java new file mode 100644 index 00000000..36793c18 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; + +/** + * Provides implementation of LocalPref BGP Path Attribute. + */ +public class LocalPref implements BgpValueType { + public static final byte LOCAL_PREF_TYPE = 5; + public static final byte LOCAL_PREF_MAX_LEN = 4; + + private int localPref; + + /** + * Constructor to initialize LocalPref. + * + * @param localPref local preference + */ + public LocalPref(int localPref) { + this.localPref = localPref; + } + + /** + * Returns local preference value. + * + * @return local preference value + */ + public int localPref() { + return this.localPref; + } + + /** + * Reads the channel buffer and returns object of LocalPref. + * + * @param cb channelBuffer + * @return object of LocalPref + * @throws BgpParseException while parsing localPref attribute + */ + public static LocalPref read(ChannelBuffer cb) throws BgpParseException { + int localPref; + ChannelBuffer tempCb = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + if ((parseFlags.getLength() > LOCAL_PREF_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + parseFlags.getLength()); + } + + int len = parseFlags.isShort() ? parseFlags.getLength() + + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if (parseFlags.getFirstBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + localPref = cb.readInt(); + return new LocalPref(localPref); + } + + @Override + public short getType() { + return LOCAL_PREF_TYPE; + } + + @Override + public int hashCode() { + return Objects.hash(localPref); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof LocalPref) { + LocalPref other = (LocalPref) obj; + return Objects.equals(localPref, other.localPref); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("localPref", localPref) + .toString(); + } + + @Override + public int write(ChannelBuffer cb) { + //Not to implement as of now + return 0; + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java new file mode 100644 index 00000000..7f1ab53f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of Med BGP Path Attribute. + */ +public class Med implements BgpValueType { + public static final byte MED_TYPE = 4; + public static final byte MED_MAX_LEN = 4; + + private int med; + + /** + * Constructor to initialize med. + * + * @param med MULTI_EXIT_DISC value + */ + public Med(int med) { + this.med = med; + } + + /** + * Returns Med value. + * + * @return Med value + */ + public int med() { + return this.med; + } + + /** + * Reads the channel buffer and returns object of Med. + * + * @param cb ChannelBuffer + * @return object of Med + * @throws BgpParseException while parsing Med path attribute + */ + public static Med read(ChannelBuffer cb) throws BgpParseException { + int med; + ChannelBuffer tempCb = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + + if ((parseFlags.getLength() > MED_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + parseFlags.getLength()); + } + int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags + .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + med = cb.readInt(); + return new Med(med); + } + + @Override + public short getType() { + return MED_TYPE; + } + + @Override + public int hashCode() { + return Objects.hash(med); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Med) { + Med other = (Med) obj; + return Objects.equals(med, other.med); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("med", med) + .toString(); + } + + @Override + public int write(ChannelBuffer cb) { + //Not to implement as of now + return 0; + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java new file mode 100644 index 00000000..2e4e6599 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java @@ -0,0 +1,225 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/* + * Provides Implementation of MpReach Nlri BGP Path Attribute. + */ +public class MpReachNlri implements BgpValueType { + + private static final Logger log = LoggerFactory.getLogger(MpReachNlri.class); + public static final byte MPREACHNLRI_TYPE = 14; + public static final byte LINK_NLRITYPE = 2; + + private boolean isMpReachNlri = false; + private final List mpReachNlri; + private final int length; + private final short afi; + private final byte safi; + private final Ip4Address ipNextHop; + + /** + * Constructor to initialize parameters. + * + * @param mpReachNlri MpReach Nlri attribute + * @param afi address family identifier + * @param safi subsequent address family identifier + * @param ipNextHop nexthop IpAddress + * @param length of MpReachNlri + */ + public MpReachNlri(List mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) { + this.mpReachNlri = mpReachNlri; + this.isMpReachNlri = true; + this.ipNextHop = ipNextHop; + this.afi = afi; + this.safi = safi; + this.length = length; + } + + /** + * Returns whether MpReachNlri is present. + * + * @return whether MpReachNlri is present + */ + public boolean isMpReachNlriSet() { + return this.isMpReachNlri; + } + + /** + * Returns list of MpReach Nlri. + * + * @return list of MpReach Nlri + */ + public List mpReachNlri() { + return this.mpReachNlri; + } + + /** + * Returns length of MpReachNlri. + * + * @return length of MpReachNlri + */ + public int mpReachNlriLen() { + return this.length; + } + + /** + * Reads from ChannelBuffer and parses MpReachNlri. + * + * @param cb channelBuffer + * @return object of MpReachNlri + * @throws BgpParseException while parsing MpReachNlri + */ + public static MpReachNlri read(ChannelBuffer cb) throws BgpParseException { + ChannelBuffer tempBuf = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : + parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempBuf.readBytes(len); + + if (cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + parseFlags.getLength()); + } + if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + BgpLSNlri bgpLSNlri = null; + List mpReachNlri = new LinkedList<>(); + ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); + short afi = 0; + byte safi = 0; + Ip4Address ipNextHop = null; + while (tempCb.readableBytes() > 0) { + afi = tempCb.readShort(); + safi = tempCb.readByte(); + + //Supporting for AFI 16388 / SAFI 71 and VPN AFI 16388 / SAFI 128 + if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) || (afi == Constants.AFI_VALUE) + && (safi == Constants.VPN_SAFI_VALUE)) { + byte nextHopLen = tempCb.readByte(); + InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb); + if (ipAddress.isMulticastAddress()) { + throw new BgpParseException("Multicast not supported"); + } + ipNextHop = Ip4Address.valueOf(ipAddress); + byte reserved = tempCb.readByte(); + + while (tempCb.readableBytes() > 0) { + short nlriType = tempCb.readShort(); + short totNlriLen = tempCb.readShort(); + if (tempCb.readableBytes() < totNlriLen) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen); + } + tempBuf = tempCb.readBytes(totNlriLen); + switch (nlriType) { + case BgpNodeLSNlriVer4.NODE_NLRITYPE: + bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi); + break; + case BgpLinkLsNlriVer4.LINK_NLRITYPE: + bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi); + break; + case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE: + bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi); + break; + default: + log.debug("nlriType not supported" + nlriType); + } + mpReachNlri.add(bgpLSNlri); + } + } else { + throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi); + } + } + return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength()); + } + + @Override + public short getType() { + return MPREACHNLRI_TYPE; + } + + /** + * Returns AFI. + * + * @return AFI + */ + public short afi() { + return this.afi; + } + + /** + * Returns Nexthop IpAddress. + * + * @return Nexthop IpAddress + */ + public Ip4Address nexthop4() { + return this.ipNextHop; + } + + /** + * Returns SAFI. + * + * @return SAFI + */ + public byte safi() { + return this.safi; + } + + @Override + public int write(ChannelBuffer cb) { + //Not to be Implemented as of now + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("mpReachNlri", mpReachNlri) + .add("afi", afi) + .add("safi", safi) + .add("ipNextHop", ipNextHop) + .add("length", length) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java new file mode 100644 index 00000000..f354b3ea --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java @@ -0,0 +1,210 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of MpUnReach Nlri BGP Path Attribute. + */ +public class MpUnReachNlri implements BgpValueType { + + private static final Logger log = LoggerFactory.getLogger(MpUnReachNlri.class); + public static final byte MPUNREACHNLRI_TYPE = 15; + public static final byte LINK_NLRITYPE = 2; + + private boolean isMpUnReachNlri = false; + private final short afi; + private final byte safi; + private final List mpUnReachNlri; + private final int length; + + /** + * Constructor to initialize parameters. + * + * @param mpUnReachNlri MpUnReach Nlri attribute + * @param afi address family identifier + * @param safi subsequent address family identifier + * @param length of MpUnReachNlri + */ + public MpUnReachNlri(List mpUnReachNlri, short afi, byte safi, + int length) { + this.mpUnReachNlri = mpUnReachNlri; + this.isMpUnReachNlri = true; + this.afi = afi; + this.safi = safi; + this.length = length; + } + + /** + * Reads from ChannelBuffer and parses MpUnReachNlri. + * + * @param cb ChannelBuffer + * @return object of MpUnReachNlri + * @throws BgpParseException while parsing MpUnReachNlri + */ + public static MpUnReachNlri read(ChannelBuffer cb) throws BgpParseException { + ChannelBuffer tempBuf = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT + : parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempBuf.readBytes(len); + + if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() + && parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + if (cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, parseFlags.getLength()); + } + + LinkedList mpUnReachNlri = new LinkedList<>(); + BgpLSNlri bgpLSNlri = null; + short afi = 0; + byte safi = 0; + ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength()); + while (tempCb.readableBytes() > 0) { + afi = tempCb.readShort(); + safi = tempCb.readByte(); + + //Supporting only for AFI 16388 / SAFI 71 + if ((afi == Constants.AFI_VALUE) && (safi == Constants.SAFI_VALUE) + || (afi == Constants.AFI_VALUE) && (safi == Constants.VPN_SAFI_VALUE)) { + while (tempCb.readableBytes() > 0) { + short nlriType = tempCb.readShort(); + short totNlriLen = tempCb.readShort(); + if (tempCb.readableBytes() < totNlriLen) { + Validation.validateLen( + BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen); + } + tempBuf = tempCb.readBytes(totNlriLen); + switch (nlriType) { + case BgpNodeLSNlriVer4.NODE_NLRITYPE: + bgpLSNlri = BgpNodeLSNlriVer4.read(tempBuf, afi, safi); + break; + case BgpLinkLsNlriVer4.LINK_NLRITYPE: + bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi); + break; + case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE: + bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, + safi); + break; + default: + log.debug("nlriType not supported" + nlriType); + } + mpUnReachNlri.add(bgpLSNlri); + } + } else { + //TODO: check with the values got from capability + throw new BgpParseException("Not Supporting afi " + afi + + "safi " + safi); + } + } + return new MpUnReachNlri(mpUnReachNlri, afi, safi, + parseFlags.getLength()); + } + + @Override + public short getType() { + return MPUNREACHNLRI_TYPE; + } + + /** + * Returns SAFI. + * + * @return SAFI + */ + public byte safi() { + return this.safi; + } + + /** + * Returns AFI. + * + * @return AFI + */ + public short afi() { + return this.afi; + } + + /** + * Returns list of MpUnReach Nlri. + * + * @return list of MpUnReach Nlri + */ + public List mpUnReachNlri() { + return this.mpUnReachNlri; + } + + /** + * Returns whether MpReachNlri is present. + * + * @return whether MpReachNlri is present + */ + public boolean isMpUnReachNlriSet() { + return this.isMpUnReachNlri; + } + + /** + * Returns length of MpUnReach. + * + * @return length of MpUnReach + */ + public int mpUnReachNlriLen() { + return this.length; + } + + @Override + public int write(ChannelBuffer cb) { + //Not to be Implemented as of now + return 0; + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("mpReachNlri", mpUnReachNlri) + .add("afi", afi) + .add("safi", safi) + .add("length", length) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java new file mode 100644 index 00000000..7082483e --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java @@ -0,0 +1,166 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; +import org.jboss.netty.buffer.ChannelBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Provides MultiProtocolExtnCapabilityTlv. + */ +public class MultiProtocolExtnCapabilityTlv implements BgpValueType { + + /* + 0 7 15 23 31 + +-------+-------+-------+-------+ + | AFI | Res | SAFI | + +-------+-------+-------+-------+ + + Multiprotocol Extensions CAPABILITY TLV format + REFERENCE : RFC 4760 + */ + protected static final Logger log = LoggerFactory + .getLogger(MultiProtocolExtnCapabilityTlv.class); + + public static final byte TYPE = 1; + public static final byte LENGTH = 4; + + private final short afi; + private final byte res; + private final byte safi; + + /** + * Constructor to initialize variables. + * @param afi Address Family Identifiers + * @param res reserved field + * @param safi Subsequent Address Family Identifier + */ + public MultiProtocolExtnCapabilityTlv(short afi, byte res, byte safi) { + this.afi = afi; + this.res = res; + this.safi = safi; + } + + /** + * Returns object of MultiProtocolExtnCapabilityTlv. + * @param afi Address Family Identifiers + * @param res reserved field + * @param safi Subsequent Address Family Identifier + * @return object of MultiProtocolExtnCapabilityTlv + */ + public static MultiProtocolExtnCapabilityTlv of(short afi, byte res, + byte safi) { + return new MultiProtocolExtnCapabilityTlv(afi, res, safi); + } + + /** + * Returns afi Address Family Identifiers value. + * @return afi Address Family Identifiers value + */ + public short getAFI() { + return afi; + } + + /** + * Returns res reserved field value. + * @return res reserved field value + */ + public byte getRes() { + return res; + } + + /** + * Returns safi Subsequent Address Family Identifier value. + * @return safi Subsequent Address Family Identifier value + */ + public byte getSAFI() { + return safi; + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int hashCode() { + return Objects.hash(afi, res, safi); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof MultiProtocolExtnCapabilityTlv) { + MultiProtocolExtnCapabilityTlv other = (MultiProtocolExtnCapabilityTlv) obj; + return Objects.equals(this.afi, other.afi) + && Objects.equals(this.res, other.res) + && Objects.equals(this.safi, other.safi); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + int iLenStartIndex = cb.writerIndex(); + cb.writeByte(TYPE); + cb.writeByte(LENGTH); + + // write afi + cb.writeShort(afi); + + // write res + cb.writeByte(res); + + // write safi + cb.writeByte(safi); + + return cb.writerIndex() - iLenStartIndex; + } + + /** + * Reads from channel buffer and returns object of MultiprotocolCapabilityTlv. + * @param cb of type channel buffer + * @return object of MultiProtocolExtnCapabilityTlv + */ + public static BgpValueType read(ChannelBuffer cb) { + short afi = cb.readShort(); + byte res = cb.readByte(); + byte safi = cb.readByte(); + return new MultiProtocolExtnCapabilityTlv(afi, res, safi); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("AFI", afi) + .add("Reserved", res) + .add("SAFI", safi).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java new file mode 100644 index 00000000..806efe52 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java @@ -0,0 +1,139 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.net.InetAddress; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; + +/** + * Implementation of NextHop BGP Path Attribute. + */ +public class NextHop implements BgpValueType { + public static final byte NEXTHOP_TYPE = 3; + + private boolean isNextHop = false; + private Ip4Address nextHop; + + /** + * Constructor to initialize parameters. + * + * @param nextHop nextHop address + */ + public NextHop(Ip4Address nextHop) { + this.nextHop = Preconditions.checkNotNull(nextHop); + this.isNextHop = true; + } + + /** + * Returns whether next hop is present. + * + * @return whether next hop is present + */ + public boolean isNextHopSet() { + return this.isNextHop; + } + + /** + * Reads from ChannelBuffer and parses NextHop. + * + * @param cb ChannelBuffer + * @return object of NextHop + * @throws BgpParseException while parsing nexthop attribute + */ + public static NextHop read(ChannelBuffer cb) throws BgpParseException { + Ip4Address nextHop; + ChannelBuffer tempCb = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + + if (cb.readableBytes() < parseFlags.getLength()) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + parseFlags.getLength()); + } + int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags + .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + InetAddress ipAddress = Validation.toInetAddress(parseFlags.getLength(), cb); + if (ipAddress.isMulticastAddress()) { + throw new BgpParseException("Multicast address is not supported"); + } + + nextHop = Ip4Address.valueOf(ipAddress); + return new NextHop(nextHop); + } + + /** + * Return nexthop address. + * + * @return nexthop address + */ + public Ip4Address nextHop() { + return nextHop; + } + + @Override + public short getType() { + return NEXTHOP_TYPE; + } + + @Override + public int write(ChannelBuffer cb) { + //Not required to be implemented now + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(nextHop); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NextHop) { + NextHop other = (NextHop) obj; + return Objects.equals(nextHop, other.nextHop); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("nextHop", nextHop) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java new file mode 100644 index 00000000..d281a4ef --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFNonPseudonode.java @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.protocol.IGPRouterID; + +import com.google.common.base.MoreObjects; + +/** + * Provides implementation of OSPFNonPseudonode Tlv. + */ +public class OSPFNonPseudonode implements IGPRouterID, BgpValueType { + public static final short TYPE = 515; + public static final short LENGTH = 4; + + private final int routerID; + + /** + * Constructor to initialize routerID. + * + * @param routerID routerID + */ + public OSPFNonPseudonode(int routerID) { + this.routerID = routerID; + } + + /** + * Returns object of this class with specified routerID. + * + * @param routerID routerID + * @return object of OSPFNonPseudonode + */ + public static OSPFNonPseudonode of(final int routerID) { + return new OSPFNonPseudonode(routerID); + } + + /** + * Returns RouterID. + * + * @return RouterID + */ + public int getrouterID() { + return this.routerID; + } + + @Override + public int hashCode() { + return Objects.hash(routerID); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof OSPFNonPseudonode) { + OSPFNonPseudonode other = (OSPFNonPseudonode) obj; + return Objects.equals(routerID, other.routerID); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeInt(routerID); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of OSPFNonPseudonode. + * + * @param cb ChannelBuffer + * @return object of OSPFNonPseudonode + */ + public static OSPFNonPseudonode read(ChannelBuffer cb) { + return OSPFNonPseudonode.of(cb.readInt()); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Integer) (this.routerID)).compareTo((Integer) (((OSPFNonPseudonode) o).routerID)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("RouterID", routerID) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java new file mode 100644 index 00000000..0d17651a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFPseudonode.java @@ -0,0 +1,132 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onosproject.bgpio.protocol.IGPRouterID; + +import com.google.common.base.MoreObjects; + +/** + * Provides implementation of OSPFPseudonode Tlv. + */ +public class OSPFPseudonode implements IGPRouterID, BgpValueType { + public static final short TYPE = 515; + public static final short LENGTH = 8; + + private final int routerID; + private final Ip4Address drInterface; + + /** + * Constructor to initialize parameters. + * + * @param routerID routerID + * @param drInterface IPv4 address of the DR's interface + */ + public OSPFPseudonode(int routerID, Ip4Address drInterface) { + this.routerID = routerID; + this.drInterface = drInterface; + } + + /** + * Returns object of this class with specified values. + * + * @param routerID routerID + * @param drInterface IPv4 address of the DR's interface + * @return object of OSPFPseudonode + */ + public static OSPFPseudonode of(final int routerID, final Ip4Address drInterface) { + return new OSPFPseudonode(routerID, drInterface); + } + + /** + * Returns RouterID. + * + * @return RouterID + */ + public int getrouterID() { + return this.routerID; + } + + @Override + public int hashCode() { + return Objects.hash(routerID, drInterface); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof OSPFPseudonode) { + OSPFPseudonode other = (OSPFPseudonode) obj; + return Objects.equals(routerID, other.routerID) && Objects.equals(drInterface, other.drInterface); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeInt(routerID); + c.writeInt(drInterface.toInt()); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads the channel buffer and returns object of OSPFPseudonode. + * + * @param cb ChannelBuffer + * @return object of OSPFPseudonode + */ + public static OSPFPseudonode read(ChannelBuffer cb) { + int routerID = cb.readInt(); + Ip4Address drInterface = Ip4Address.valueOf(cb.readInt()); + return OSPFPseudonode.of(routerID, drInterface); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + int result = ((Integer) (this.routerID)).compareTo((Integer) (((OSPFPseudonode) o).routerID)); + if (result != 0) { + return this.drInterface.compareTo(((OSPFPseudonode) o).drInterface); + } + return result; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("RouterID", routerID) + .add("DRInterface", drInterface) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java new file mode 100644 index 00000000..be321c95 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/OSPFRouteTypeTlv.java @@ -0,0 +1,168 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; + +import com.google.common.base.MoreObjects; + +/** + * Provides OSPF Route Type Tlv which contains route type. + */ +public class OSPFRouteTypeTlv implements BgpValueType { + + /* Reference :draft-ietf-idr-ls-distribution-11 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Route Type | + +-+-+-+-+-+-+-+-+ + + Figure : OSPF Route Type TLV Format + */ + + public static final short TYPE = 264; + public static final short LENGTH = 1; + public static final int INTRA_AREA_TYPE = 1; + public static final short INTER_AREA_TYPE = 2; + public static final short EXTERNAL_TYPE_1 = 3; + public static final short EXTERNAL_TYPE_2 = 4; + public static final short NSSA_TYPE_1 = 5; + public static final short NSSA_TYPE_2 = 6; + + private final byte routeType; + + /** + * Enum for Route Type. + */ + public enum RouteType { + Intra_Area(1), Inter_Area(2), External_1(3), External_2(4), NSSA_1(5), NSSA_2(6); + int value; + RouteType(int val) { + value = val; + } + public byte getType() { + return (byte) value; + } + } + + /** + * Constructor to initialize routeType. + * + * @param routeType Route type + */ + public OSPFRouteTypeTlv(byte routeType) { + this.routeType = routeType; + } + + /** + * Returns object of this class with specified routeType. + * + * @param routeType Route type + * @return object of OSPFRouteTypeTlv + */ + public static OSPFRouteTypeTlv of(final byte routeType) { + return new OSPFRouteTypeTlv(routeType); + } + + /** + * Returns RouteType. + * + * @return RouteType + * @throws BgpParseException if routeType is not matched + */ + public RouteType getValue() throws BgpParseException { + switch (routeType) { + case INTRA_AREA_TYPE: + return RouteType.Intra_Area; + case INTER_AREA_TYPE: + return RouteType.Inter_Area; + case EXTERNAL_TYPE_1: + return RouteType.External_1; + case EXTERNAL_TYPE_2: + return RouteType.External_2; + case NSSA_TYPE_1: + return RouteType.NSSA_1; + case NSSA_TYPE_2: + return RouteType.NSSA_2; + default: + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, (byte) 0, null); + } + } + + @Override + public int hashCode() { + return Objects.hash(routeType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof OSPFRouteTypeTlv) { + OSPFRouteTypeTlv other = (OSPFRouteTypeTlv) obj; + return Objects.equals(routeType, other.routeType); + } + return false; + } + + @Override + public int write(ChannelBuffer c) { + int iLenStartIndex = c.writerIndex(); + c.writeShort(TYPE); + c.writeShort(LENGTH); + c.writeByte(routeType); + return c.writerIndex() - iLenStartIndex; + } + + /** + * Reads from ChannelBuffer and parses OSPFRouteTypeTlv. + * + * @param cb channelBuffer + * @return object of OSPFRouteTypeTlv + */ + public static OSPFRouteTypeTlv read(ChannelBuffer cb) { + return OSPFRouteTypeTlv.of(cb.readByte()); + } + + @Override + public short getType() { + return TYPE; + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + return ((Byte) (this.routeType)).compareTo((Byte) (((OSPFRouteTypeTlv) o).routeType)); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("Type", TYPE) + .add("Length", LENGTH) + .add("Value", routeType) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java new file mode 100644 index 00000000..d642d83c --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java @@ -0,0 +1,168 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.util.Constants; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; + +/** + * Provides Implementation of mandatory BGP Origin path attribute. + */ +public class Origin implements BgpValueType { + + /** + * Enum to provide ORIGIN types. + */ + public enum ORIGINTYPE { + IGP(0), EGP(1), INCOMPLETE(2); + int value; + /** + * Assign val with the value as the ORIGIN type. + * + * @param val ORIGIN type + */ + ORIGINTYPE(int val) { + value = val; + } + + /** + * Returns value of ORIGIN type. + * + * @return ORIGIN type + */ + public byte getType() { + return (byte) value; + } + } + + public static final byte ORIGIN_TYPE = 1; + public static final byte ORIGIN_VALUE_LEN = 1; + + private boolean isOrigin = false; + private byte origin; + + /** + * Constructor to initialize parameters. + * + * @param origin origin value + */ + public Origin(byte origin) { + this.origin = origin; + this.isOrigin = true; + } + + /** + * Returns true if origin attribute is present otherwise false. + * + * @return whether origin is present or not + */ + public boolean isOriginSet() { + return this.isOrigin; + } + + /** + * Returns type of Origin in Enum values. + * + * @return type of Origin in Enum values + */ + public ORIGINTYPE origin() { + if (this.origin == 0) { + return ORIGINTYPE.IGP; + } else if (this.origin == 1) { + return ORIGINTYPE.EGP; + } else { + return ORIGINTYPE.INCOMPLETE; + } + } + + /** + * Reads from ChannelBuffer and parses Origin. + * + * @param cb ChannelBuffer + * @return object of Origin + * @throws BgpParseException while parsing Origin path attribute + */ + public static Origin read(ChannelBuffer cb) throws BgpParseException { + ChannelBuffer tempCb = cb.copy(); + Validation parseFlags = Validation.parseAttributeHeader(cb); + + int len = parseFlags.isShort() ? parseFlags.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : parseFlags + .getLength() + Constants.TYPE_AND_LEN_AS_BYTE; + ChannelBuffer data = tempCb.readBytes(len); + if ((parseFlags.getLength() > ORIGIN_VALUE_LEN) || (cb.readableBytes() < parseFlags.getLength())) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + parseFlags.getLength()); + } + if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data); + } + + byte originValue; + originValue = cb.readByte(); + if ((originValue != ORIGINTYPE.INCOMPLETE.value) && (originValue != ORIGINTYPE.IGP.value) && + (originValue != ORIGINTYPE.EGP.value)) { + throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.INVALID_ORIGIN_ATTRIBUTE, data); + } + return new Origin(originValue); + } + + @Override + public short getType() { + return ORIGIN_TYPE; + } + + @Override + public int write(ChannelBuffer cb) { + //Not required to Implement as of now + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(origin); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Origin) { + Origin other = (Origin) obj; + return Objects.equals(origin, other.origin); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("origin", origin) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java new file mode 100644 index 00000000..37632ad8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteDistinguisher.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.types; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of RouteDistinguisher. + */ +public class RouteDistinguisher implements Comparable { + + private long routeDistinguisher; + + /** + * Resets fields. + */ + public RouteDistinguisher() { + this.routeDistinguisher = 0; + } + + /** + * Constructor to initialize parameters. + * + * @param routeDistinguisher route distinguisher + */ + public RouteDistinguisher(long routeDistinguisher) { + this.routeDistinguisher = routeDistinguisher; + } + + /** + * Reads route distinguisher from channelBuffer. + * + * @param cb channelBuffer + * @return object of RouteDistinguisher + */ + public static RouteDistinguisher read(ChannelBuffer cb) { + return new RouteDistinguisher(cb.readLong()); + } + + /** + * Returns route distinguisher. + * + * @return route distinguisher + */ + public long getRouteDistinguisher() { + return this.routeDistinguisher; + } + + @Override + public int compareTo(RouteDistinguisher rd) { + if (this.equals(rd)) { + return 0; + } + return ((Long) (this.getRouteDistinguisher())).compareTo((Long) (rd.getRouteDistinguisher())); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("routeDistinguisher", routeDistinguisher) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java new file mode 100755 index 00000000..e0fef7c8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java @@ -0,0 +1,199 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute node flag. + */ +public final class BgpAttrNodeFlagBitTlv implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrNodeFlagBitTlv.class); + + public static final int ATTRNODE_FLAGBIT = 1024; + + /* Node flag bit TLV */ + private final boolean bOverloadBit; + private final boolean bAttachedBit; + private final boolean bExternalBit; + private final boolean bAbrBit; + + public static final byte FIRST_BIT = (byte) 0x80; + public static final byte SECOND_BIT = 0x40; + public static final byte THIRD_BIT = 0x20; + public static final byte FOURTH_BIT = 0x01; + + /** + * Constructor to initialize parameters. + * + * @param bOverloadBit Overload bit + * @param bAttachedBit Attached bit + * @param bExternalBit External bit + * @param bAbrBit ABR Bit + */ + private BgpAttrNodeFlagBitTlv(boolean bOverloadBit, boolean bAttachedBit, + boolean bExternalBit, boolean bAbrBit) { + this.bOverloadBit = bOverloadBit; + this.bAttachedBit = bAttachedBit; + this.bExternalBit = bExternalBit; + this.bAbrBit = bAbrBit; + } + + /** + * Returns object of this class with specified values. + * + * @param bOverloadBit Overload bit + * @param bAttachedBit Attached bit + * @param bExternalBit External bit + * @param bAbrBit ABR Bit + * @return object of BgpAttrNodeFlagBitTlv + */ + public static BgpAttrNodeFlagBitTlv of(final boolean bOverloadBit, + final boolean bAttachedBit, + final boolean bExternalBit, + final boolean bAbrBit) { + return new BgpAttrNodeFlagBitTlv(bOverloadBit, bAttachedBit, + bExternalBit, bAbrBit); + } + + /** + * Reads the Node Flag Bits. + * + * @param cb ChannelBuffer + * @return attribute node flag bit tlv + * @throws BgpParseException while parsing BgpAttrNodeFlagBitTlv + */ + public static BgpAttrNodeFlagBitTlv read(ChannelBuffer cb) + throws BgpParseException { + boolean bOverloadBit = false; + boolean bAttachedBit = false; + boolean bExternalBit = false; + boolean bAbrBit = false; + + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != 1) || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + byte nodeFlagBits = cb.readByte(); + + bOverloadBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT); + bAttachedBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT); + bExternalBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT); + bAbrBit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT); + + return BgpAttrNodeFlagBitTlv.of(bOverloadBit, bAttachedBit, + bExternalBit, bAbrBit); + } + + /** + * Returns Overload Bit. + * + * @return Overload Bit + */ + public boolean overLoadBit() { + return bOverloadBit; + } + + /** + * Returns Attached Bit. + * + * @return Attached Bit + */ + public boolean attachedBit() { + return bAttachedBit; + } + + /** + * Returns External Bit. + * + * @return External Bit + */ + public boolean externalBit() { + return bExternalBit; + } + + /** + * Returns ABR Bit. + * + * @return ABR Bit + */ + public boolean abrBit() { + return bAbrBit; + } + + @Override + public short getType() { + return ATTRNODE_FLAGBIT; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(bOverloadBit, bAttachedBit, bExternalBit, bAbrBit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrNodeFlagBitTlv) { + BgpAttrNodeFlagBitTlv other = (BgpAttrNodeFlagBitTlv) obj; + return Objects.equals(bOverloadBit, other.bOverloadBit) + && Objects.equals(bAttachedBit, other.bAttachedBit) + && Objects.equals(bExternalBit, other.bExternalBit) + && Objects.equals(bAbrBit, other.bAbrBit); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("bOverloadBit", bOverloadBit) + .add("bAttachedBit", bAttachedBit) + .add("bExternalBit", bExternalBit).add("bAbrBit", bAbrBit) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java new file mode 100644 index 00000000..0435a65f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeIsIsAreaId.java @@ -0,0 +1,136 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute ISIS Area Identifier. + */ +public class BgpAttrNodeIsIsAreaId implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrNodeIsIsAreaId.class); + + public static final int ATTRNODE_ISISAREAID = 1027; + + /* IS-IS Area Identifier TLV */ + private byte[] isisAreaId; + + /** + * Constructor to initialize value. + * + * @param isisAreaId ISIS area Identifier + */ + public BgpAttrNodeIsIsAreaId(byte[] isisAreaId) { + this.isisAreaId = Arrays.copyOf(isisAreaId, isisAreaId.length); + } + + /** + * Returns object of this class with specified values. + * + * @param isisAreaId ISIS area Identifier + * @return object of BgpAttrNodeIsIsAreaId + */ + public static BgpAttrNodeIsIsAreaId of(final byte[] isisAreaId) { + return new BgpAttrNodeIsIsAreaId(isisAreaId); + } + + /** + * Reads the IS-IS Area Identifier. + * + * @param cb ChannelBuffer + * @return object of BgpAttrNodeIsIsAreaId + * @throws BgpParseException while parsing BgpAttrNodeIsIsAreaId + */ + public static BgpAttrNodeIsIsAreaId read(ChannelBuffer cb) + throws BgpParseException { + byte[] isisAreaId; + + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + isisAreaId = new byte[lsAttrLength]; + cb.readBytes(isisAreaId); + + return BgpAttrNodeIsIsAreaId.of(isisAreaId); + } + + /** + * Returns ISIS area Identifier. + * + * @return Area ID + */ + public byte[] attrNodeIsIsAreaId() { + return isisAreaId; + } + + @Override + public short getType() { + return ATTRNODE_ISISAREAID; + } + + @Override + public int hashCode() { + return Arrays.hashCode(isisAreaId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrNodeIsIsAreaId) { + BgpAttrNodeIsIsAreaId other = (BgpAttrNodeIsIsAreaId) obj; + return Arrays.equals(isisAreaId, other.isisAreaId); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("isisAreaId", isisAreaId).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java new file mode 100644 index 00000000..31d855db --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeMultiTopologyId.java @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * BGP Multi-Topology ID of the LS attribute. + */ +public class BgpAttrNodeMultiTopologyId implements BgpValueType { + + private static final Logger log = LoggerFactory + .getLogger(BgpAttrNodeMultiTopologyId.class); + + public static final int ATTRNODE_MULTITOPOLOGY = 263; + + /* Opaque Node Attribute */ + private List multiTopologyId = new ArrayList(); + + /** + * Constructor to initialize the Node attribute multi-topology ID. + * + * @param multiTopologyId multi-topology ID + */ + public BgpAttrNodeMultiTopologyId(List multiTopologyId) { + this.multiTopologyId = multiTopologyId; + } + + /** + * Returns object of this class with specified values. + * + * @param multiTopologyId Prefix Metric + * @return object of BgpAttrNodeMultiTopologyId + */ + public static BgpAttrNodeMultiTopologyId of(ArrayList multiTopologyId) { + return new BgpAttrNodeMultiTopologyId(multiTopologyId); + } + + /** + * Reads the Multi-topology ID of Node attribute. + * + * @param cb ChannelBuffer + * @return Constructor of BgpAttrNodeMultiTopologyId + * @throws BgpParseException while parsing BgpAttrNodeMultiTopologyId + */ + public static BgpAttrNodeMultiTopologyId read(ChannelBuffer cb) + throws BgpParseException { + ArrayList multiTopologyId = new ArrayList(); + short tempMultiTopologyId; + short lsAttrLength = cb.readShort(); + int len = lsAttrLength / 2; // Length is 2*n and n is the number of MT-IDs + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + for (int i = 0; i < len; i++) { + tempMultiTopologyId = cb.readShort(); + multiTopologyId.add(new Short(tempMultiTopologyId)); + } + + return new BgpAttrNodeMultiTopologyId(multiTopologyId); + } + + /** + * to get the multi-topology ID. + * + * @return multitopology ID + */ + public List attrMultiTopologyId() { + return multiTopologyId; + } + + @Override + public short getType() { + return ATTRNODE_MULTITOPOLOGY; + } + + @Override + public int hashCode() { + return Objects.hash(multiTopologyId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrNodeMultiTopologyId) { + BgpAttrNodeMultiTopologyId other = (BgpAttrNodeMultiTopologyId) obj; + return Objects.equals(multiTopologyId, other.multiTopologyId); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("multiTopologyId", multiTopologyId) + .toString(); + } + + @Override + public int compareTo(Object o) { + if (this.equals(o)) { + return 0; + } + int countOtherSubTlv = ((BgpAttrNodeMultiTopologyId) o).multiTopologyId.size(); + int countObjSubTlv = multiTopologyId.size(); + if (countOtherSubTlv != countObjSubTlv) { + if (countOtherSubTlv > countObjSubTlv) { + return 1; + } else { + return -1; + } + } + ListIterator listIterator = multiTopologyId.listIterator(); + ListIterator listIteratorOther = ((BgpAttrNodeMultiTopologyId) o).multiTopologyId.listIterator(); + while (listIterator.hasNext()) { + short id = listIterator.next(); + short id1 = listIteratorOther.next(); + if (((Short) id).compareTo((Short) id1) != 0) { + return ((Short) id).compareTo((Short) id1); + } + } + return 0; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java new file mode 100644 index 00000000..2e1c7a05 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeName.java @@ -0,0 +1,135 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute node name. + */ +public class BgpAttrNodeName implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrNodeName.class); + + public static final int ATTRNODE_NAME = 1026; + + /* Node Name */ + private byte[] nodeName; + + /** + * Constructor to initialize value. + * + * @param nodeName node name + */ + public BgpAttrNodeName(byte[] nodeName) { + this.nodeName = Arrays.copyOf(nodeName, nodeName.length); + } + + /** + * Returns object of this class with specified values. + * + * @param nodeName node name + * @return object of BgpAttrNodeName + */ + public static BgpAttrNodeName of(final byte[] nodeName) { + return new BgpAttrNodeName(nodeName); + } + + /** + * Reads the LS attribute node name. + * + * @param cb ChannelBuffer + * @return object of BgpAttrNodeName + * @throws BgpParseException while parsing BgpAttrNodeName + */ + public static BgpAttrNodeName read(ChannelBuffer cb) + throws BgpParseException { + byte[] nodeName; + + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + nodeName = new byte[lsAttrLength]; + cb.readBytes(nodeName); + return BgpAttrNodeName.of(nodeName); + } + + /** + * Returns LS attribute node name. + * + * @return node name + */ + public byte[] attrNodeName() { + return nodeName; + } + + @Override + public short getType() { + return ATTRNODE_NAME; + } + + @Override + public int hashCode() { + return Arrays.hashCode(nodeName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrNodeName) { + BgpAttrNodeName other = (BgpAttrNodeName) obj; + return Arrays.equals(nodeName, other.nodeName); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("nodeName", nodeName).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java new file mode 100644 index 00000000..545755a7 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrOpaqueNode.java @@ -0,0 +1,138 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute opaque node. + */ +public class BgpAttrOpaqueNode implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrOpaqueNode.class); + + public static final int ATTRNODE_OPAQUEDATA = 1025; + + /* Opaque Node Attribute */ + private byte[] opaqueNodeAttribute; + + /** + * Constructor to initialize parameter. + * + * @param opaqueNodeAttribute opaque node attribute + */ + public BgpAttrOpaqueNode(byte[] opaqueNodeAttribute) { + this.opaqueNodeAttribute = Arrays.copyOf(opaqueNodeAttribute, opaqueNodeAttribute.length); + } + + /** + * Returns object of this class with specified values. + * + * @param opaqueNodeAttribute Prefix Metric + * @return object of BgpAttrOpaqueNode + */ + public static BgpAttrOpaqueNode of(byte[] opaqueNodeAttribute) { + return new BgpAttrOpaqueNode(opaqueNodeAttribute); + } + + /** + * Reads the Opaque Node Properties. + * + * @param cb ChannelBuffer + * @return object of BgpAttrOpaqueNode + * @throws BgpParseException while parsing BgpAttrOpaqueNode + */ + public static BgpAttrOpaqueNode read(ChannelBuffer cb) + throws BgpParseException { + + byte[] opaqueNodeAttribute; + + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + opaqueNodeAttribute = new byte[lsAttrLength]; + cb.readBytes(opaqueNodeAttribute); + + return BgpAttrOpaqueNode.of(opaqueNodeAttribute); + } + + /** + * Returns opaque node attribute. + * + * @return LS node attribute value + */ + public byte[] attrOpaqueNode() { + return opaqueNodeAttribute; + } + + @Override + public short getType() { + return ATTRNODE_OPAQUEDATA; + } + + @Override + public int hashCode() { + return Arrays.hashCode(opaqueNodeAttribute); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrOpaqueNode) { + BgpAttrOpaqueNode other = (BgpAttrOpaqueNode) obj; + return Arrays + .equals(opaqueNodeAttribute, other.opaqueNodeAttribute); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("opaqueNodeAttribute", opaqueNodeAttribute).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java new file mode 100644 index 00000000..f3c0d17b --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java @@ -0,0 +1,140 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute node router ID. + */ +public final class BgpAttrRouterIdV4 implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrRouterIdV4.class); + + private final short sType; + + /* IPv4 Router-ID of Node */ + private final Ip4Address ip4RouterId; + + /** + * Constructor to initialize the value. + * + * @param ip4RouterId IPV4 address of router + * @param sType TLV type + */ + private BgpAttrRouterIdV4(Ip4Address ip4RouterId, short sType) { + this.ip4RouterId = ip4RouterId; + this.sType = sType; + } + + /** + * Returns object of this class with specified values. + * + * @param ip4RouterId IPv4 address + * @param sType Type of this TLV + * @return object of BgpAttrRouterIdV4 + */ + public static BgpAttrRouterIdV4 of(final Ip4Address ip4RouterId, + final short sType) { + return new BgpAttrRouterIdV4(ip4RouterId, sType); + } + + /** + * Reads the IPv4 Router-ID. + * + * @param cb ChannelBuffer + * @param sType tag type + * @return object of BgpAttrRouterIdV4 + * @throws BgpParseException while parsing BgpAttrRouterIdV4 + */ + public static BgpAttrRouterIdV4 read(ChannelBuffer cb, short sType) + throws BgpParseException { + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != 4) || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + byte[] ipBytes = new byte[lsAttrLength]; + cb.readBytes(ipBytes, 0, lsAttrLength); + Ip4Address ip4RouterId = Ip4Address.valueOf(ipBytes); + return BgpAttrRouterIdV4.of(ip4RouterId, sType); + } + + /** + * Returns the IPV4 router ID. + * + * @return Router ID + */ + public Ip4Address attrRouterId() { + return ip4RouterId; + } + + @Override + public short getType() { + return sType; + } + + @Override + public int hashCode() { + return Objects.hash(ip4RouterId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrRouterIdV4) { + BgpAttrRouterIdV4 other = (BgpAttrRouterIdV4) obj; + return Objects.equals(ip4RouterId, other.ip4RouterId); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("ip4RouterId", ip4RouterId).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java new file mode 100644 index 00000000..648fd56e --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java @@ -0,0 +1,143 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip6Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute IPv6 router ID. + */ +public final class BgpAttrRouterIdV6 implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpAttrRouterIdV6.class); + + private final short sType; + + /* IPv4 Router-ID of Node */ + private final Ip6Address ip6RouterId; + + /** + * Constructor to initialize the value. + * + * @param ip6RouterId IPV6 address of the router ID + * @param sType TLV type + */ + private BgpAttrRouterIdV6(Ip6Address ip6RouterId, short sType) { + this.ip6RouterId = ip6RouterId; + this.sType = sType; + } + + /** + * Returns object of this class with specified values. + * + * @param ip6RouterId IPV6 address of the router ID + * @param sType TLV type + * @return object of BgpAttrRouterIdV6 + */ + public static BgpAttrRouterIdV6 of(final Ip6Address ip6RouterId, + final short sType) { + return new BgpAttrRouterIdV6(ip6RouterId, sType); + } + + /** + * Reads the IPv6 Router-ID. + * + * @param cb ChannelBuffer + * @param sType TLV type + * @return object of BgpAttrRouterIdV6 + * @throws BgpParseException while parsing BgpAttrRouterIdV6 + */ + public static BgpAttrRouterIdV6 read(ChannelBuffer cb, short sType) + throws BgpParseException { + byte[] ipBytes; + Ip6Address ip6RouterId; + + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != 16) || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + ipBytes = new byte[lsAttrLength]; + cb.readBytes(ipBytes); + ip6RouterId = Ip6Address.valueOf(ipBytes); + return BgpAttrRouterIdV6.of(ip6RouterId, sType); + } + + /** + * Returns IPV6 router ID. + * + * @return Router ID + */ + public Ip6Address attrRouterId() { + return ip6RouterId; + } + + @Override + public short getType() { + return sType; + } + + @Override + public int hashCode() { + return Objects.hash(ip6RouterId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpAttrRouterIdV6) { + BgpAttrRouterIdV6 other = (BgpAttrRouterIdV6) obj; + return Objects.equals(ip6RouterId, other.ip6RouterId); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("ip6RouterId", ip6RouterId).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java new file mode 100644 index 00000000..5721cf6c --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java @@ -0,0 +1,178 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link IGP metric attribute. + */ +public class BgpLinkAttrIgpMetric implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrIgpMetric.class); + + public static final int ATTRLINK_IGPMETRIC = 1095; + public static final int ATTRLINK_MAX_LEN = 3; + + /* Variable metric length based on protocol */ + public static final int ISIS_SMALL_METRIC = 1; + public static final int OSPF_LINK_METRIC = 2; + public static final int ISIS_WIDE_METRIC = 3; + + /* IGP Metric */ + private final int igpMetric; + private final int igpMetricLen; + + /** + * Constructor to initialize the value. + * + * @param igpMetric 3 byte IGP metric data. + * @param igpMetricLen length of IGP metric data. + */ + public BgpLinkAttrIgpMetric(final int igpMetric, final int igpMetricLen) { + this.igpMetric = igpMetric; + this.igpMetricLen = igpMetricLen; + } + + /** + * Returns object of this class with specified values. + * + * @param igpMetric 3 byte IGP metric data. + * @param igpMetricLen length of IGP metric data. + * @return object of BgpLinkAttrIgpMetric + */ + public static BgpLinkAttrIgpMetric of(final int igpMetric, + final int igpMetricLen) { + return new BgpLinkAttrIgpMetric(igpMetric, igpMetricLen); + } + + /** + * Reads the BGP link attributes IGP Metric. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrIgpMetric + * @throws BgpParseException while parsing BgpLinkAttrIgpMetric + */ + public static BgpLinkAttrIgpMetric read(ChannelBuffer cb) + throws BgpParseException { + + short linkigp; + int igpMetric = 0; + int igpMetricLen = 0; + + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength + || lsAttrLength > ATTRLINK_MAX_LEN) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + switch (lsAttrLength) { + case ISIS_SMALL_METRIC: + igpMetric = cb.readByte(); + igpMetricLen = ISIS_SMALL_METRIC; + break; + case OSPF_LINK_METRIC: + igpMetric = cb.readShort(); + igpMetricLen = OSPF_LINK_METRIC; + break; + case ISIS_WIDE_METRIC: + linkigp = cb.readShort(); + igpMetric = cb.readByte(); + igpMetric = (igpMetric << 16) | linkigp; + igpMetricLen = ISIS_WIDE_METRIC; + break; + default: // validation is already in place + break; + } + + return BgpLinkAttrIgpMetric.of(igpMetric, igpMetricLen); + } + + /** + * Returns the variable length IGP metric data. + * + * @return IGP metric data + */ + public int attrLinkIgpMetric() { + return igpMetric; + } + + /** + * Returns IGP metric data length. + * + * @return IGP metric length + */ + public int attrLinkIgpMetricLength() { + return igpMetricLen; + } + + @Override + public short getType() { + return ATTRLINK_IGPMETRIC; + } + + @Override + public int hashCode() { + return Objects.hash(igpMetric, igpMetricLen); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrIgpMetric) { + BgpLinkAttrIgpMetric other = (BgpLinkAttrIgpMetric) obj; + return Objects.equals(igpMetric, other.igpMetric) + && Objects.equals(igpMetricLen, other.igpMetricLen); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("igpMetric", igpMetric).add("igpMetricLen", igpMetricLen) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java new file mode 100644 index 00000000..448f1e58 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIsIsAdminstGrp.java @@ -0,0 +1,136 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute Is Is Administrative area. + */ +public final class BgpLinkAttrIsIsAdminstGrp implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrIsIsAdminstGrp.class); + + public static final int ATTRLINK_PROTECTIONTYPE = 1088; + public static final int ISIS_ADMIN_DATA_LEN = 4; + + /* ISIS administrative group */ + private final long isisAdminGrp; + + /** + * Constructor to initialize the values. + * + * @param isisAdminGrp ISIS protocol admin group + */ + public BgpLinkAttrIsIsAdminstGrp(long isisAdminGrp) { + this.isisAdminGrp = isisAdminGrp; + } + + /** + * Returns object of this class with specified values. + * + * @param isisAdminGrp ISIS admin group + * @return object of BgpLinkAttrIsIsAdminstGrp + */ + public static BgpLinkAttrIsIsAdminstGrp of(final long isisAdminGrp) { + return new BgpLinkAttrIsIsAdminstGrp(isisAdminGrp); + } + + /** + * Reads the BGP link attributes of ISIS administrative group area. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrIsIsAdminstGrp + * @throws BgpParseException while parsing BgpLinkAttrIsIsAdminstGrp + */ + public static BgpLinkAttrIsIsAdminstGrp read(ChannelBuffer cb) + throws BgpParseException { + long isisAdminGrp; + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != ISIS_ADMIN_DATA_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + isisAdminGrp = cb.readUnsignedInt(); + + return BgpLinkAttrIsIsAdminstGrp.of(isisAdminGrp); + } + + /** + * Link attributes of ISIS administrative group area. + * + * @return long value of the administrative group area + */ + public long linkAttrIsIsAdminGrp() { + return isisAdminGrp; + } + + @Override + public short getType() { + return ATTRLINK_PROTECTIONTYPE; + } + + @Override + public int hashCode() { + return Objects.hash(isisAdminGrp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrIsIsAdminstGrp) { + BgpLinkAttrIsIsAdminstGrp other = (BgpLinkAttrIsIsAdminstGrp) obj; + return Objects.equals(isisAdminGrp, other.isisAdminGrp); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("isisAdminGrp", isisAdminGrp).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java new file mode 100644 index 00000000..2711ca94 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidth.java @@ -0,0 +1,156 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP attribute Max Link bandwidth. + */ +public final class BgpLinkAttrMaxLinkBandwidth implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrMaxLinkBandwidth.class); + + public static final int MAX_BANDWIDTH_LEN = 4; + public static final int NO_OF_BITS = 8; + + public short type; + + /* ISIS administrative group */ + private final float maxBandwidth; + + /** + * Constructor to initialize the values. + * + * @param maxBandwidth Maximum link bandwidth. + * @param type TLV type + */ + private BgpLinkAttrMaxLinkBandwidth(float maxBandwidth, short type) { + this.maxBandwidth = maxBandwidth; + this.type = type; + } + + /** + * Returns object of this class with specified values. + * + * @param maxBandwidth Maximum link bandwidth. + * @param type TLV type + * @return object of BgpLinkAttrMaxLinkBandwidth + */ + public static BgpLinkAttrMaxLinkBandwidth of(final float maxBandwidth, + final short type) { + return new BgpLinkAttrMaxLinkBandwidth(maxBandwidth, type); + } + + /** + * Reads the BGP link attributes of Maximum link bandwidth. + * + * @param cb Channel buffer + * @param type type of this tlv + * @return object of type BgpLinkAttrMaxLinkBandwidth + * @throws BgpParseException while parsing BgpLinkAttrMaxLinkBandwidth + */ + public static BgpLinkAttrMaxLinkBandwidth read(ChannelBuffer cb, short type) + throws BgpParseException { + float maxBandwidth; + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != MAX_BANDWIDTH_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + maxBandwidth = ieeeToFloatRead(cb.readInt()) * NO_OF_BITS; + + return BgpLinkAttrMaxLinkBandwidth.of(maxBandwidth, type); + } + + /** + * Returns Maximum link bandwidth. + * + * @return Maximum link bandwidth + */ + float linkAttrMaxLinkBandwidth() { + return maxBandwidth; + } + + /** + * Parse the IEEE floating point notation and returns it in normal float. + * + * @param iVal IEEE floating point number + * @return normal float + */ + static float ieeeToFloatRead(int iVal) { + iVal = (((iVal & 0xFF) << 24) | ((iVal & 0xFF00) << 8) + | ((iVal & 0xFF0000) >> 8) | ((iVal >> 24) & 0xFF)); + + return Float.intBitsToFloat(iVal); + } + + @Override + public short getType() { + return this.type; + } + + @Override + public int hashCode() { + return Objects.hash(maxBandwidth); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrMaxLinkBandwidth) { + BgpLinkAttrMaxLinkBandwidth other = (BgpLinkAttrMaxLinkBandwidth) obj; + return Objects.equals(maxBandwidth, other.maxBandwidth); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("maxBandwidth", maxBandwidth).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java new file mode 100644 index 00000000..2bf1a59d --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java @@ -0,0 +1,158 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP MPLS protocol mask attribute. + */ +public class BgpLinkAttrMplsProtocolMask implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrMplsProtocolMask.class); + + public static final int ATTRLINK_MPLSPROTOMASK = 1094; + public static final int MASK_BYTE_LEN = 1; + + private final boolean bLdp; + private final boolean bRsvpTe; + + public static final byte FIRST_BIT = (byte) 0x80; + public static final byte SECOND_BIT = 0x40; + + /** + * Constructor to initialize the values. + * + * @param bLdp boolean value true if LDP flag is available + * @param bRsvpTe boolean value true if RSVP TE information is available + */ + public BgpLinkAttrMplsProtocolMask(boolean bLdp, boolean bRsvpTe) { + this.bLdp = bLdp; + this.bRsvpTe = bRsvpTe; + } + + /** + * Returns object of this class with specified values. + * + * @param bLdp boolean value true if LDP flag is available + * @param bRsvpTe boolean value true if RSVP TE information is available + * @return object of BgpLinkAttrMplsProtocolMask + */ + public static BgpLinkAttrMplsProtocolMask of(final boolean bLdp, + final boolean bRsvpTe) { + return new BgpLinkAttrMplsProtocolMask(bLdp, bRsvpTe); + } + + /** + * Reads the BGP link attributes MPLS protocol mask. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrMPLSProtocolMask + * @throws BgpParseException while parsing BgpLinkAttrMplsProtocolMask + */ + public static BgpLinkAttrMplsProtocolMask read(ChannelBuffer cb) + throws BgpParseException { + boolean bLdp = false; + boolean bRsvpTe = false; + + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != MASK_BYTE_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + byte flags = cb.readByte(); + + bLdp = ((flags & (byte) FIRST_BIT) == FIRST_BIT); + bRsvpTe = ((flags & (byte) SECOND_BIT) == SECOND_BIT); + + return BgpLinkAttrMplsProtocolMask.of(bLdp, bRsvpTe); + } + + /** + * Returns true if LDP bit is set. + * + * @return True if LDP information is set else false. + */ + public boolean ldpBit() { + return bLdp; + } + + /** + * Returns RSVP TE information. + * + * @return True if RSVP TE information is set else false. + */ + public boolean rsvpBit() { + return bRsvpTe; + } + + @Override + public short getType() { + return ATTRLINK_MPLSPROTOMASK; + } + + @Override + public int hashCode() { + return Objects.hash(bLdp, bRsvpTe); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrMplsProtocolMask) { + BgpLinkAttrMplsProtocolMask other = (BgpLinkAttrMplsProtocolMask) obj; + return Objects.equals(bLdp, other.bLdp) + && Objects.equals(bRsvpTe, other.bRsvpTe); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("bLdp", bLdp).add("bRsvpTe", bRsvpTe).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java new file mode 100644 index 00000000..856ffc36 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrName.java @@ -0,0 +1,134 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link name attribute. + */ +public class BgpLinkAttrName implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrName.class); + + public static final int ATTRLINK_NAME = 1098; + + /* Link Name */ + private byte[] linkName; + + /** + * Constructor to initialize the values. + * + * @param linkName link name + */ + public BgpLinkAttrName(byte[] linkName) { + this.linkName = Arrays.copyOf(linkName, linkName.length); + } + + /** + * Returns object of this class with specified values. + * + * @param linkName Prefix Metric + * @return object of BgpLinkAttrName + */ + public static BgpLinkAttrName of(byte[] linkName) { + return new BgpLinkAttrName(linkName); + } + + /** + * Reads the BGP link attributes Name. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrName + * @throws BgpParseException while parsing BgpLinkAttrName + */ + public static BgpLinkAttrName read(ChannelBuffer cb) + throws BgpParseException { + byte[] linkName; + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + linkName = new byte[lsAttrLength]; + cb.readBytes(linkName); + return BgpLinkAttrName.of(linkName); + } + + /** + * Returns the link name. + * + * @return link name + */ + public byte[] attrLinkName() { + return linkName; + } + + @Override + public short getType() { + return ATTRLINK_NAME; + } + + @Override + public int hashCode() { + return Arrays.hashCode(linkName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrName) { + BgpLinkAttrName other = (BgpLinkAttrName) obj; + return Arrays.equals(linkName, other.linkName); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("linkName", linkName).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java new file mode 100644 index 00000000..275b85be --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttrib.java @@ -0,0 +1,139 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link opaque attribute. + */ +public final class BgpLinkAttrOpaqLnkAttrib implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrOpaqLnkAttrib.class); + + public static final int ATTRNODE_OPAQUELNKATTRIB = 1097; + + /* Opaque Node Attribute */ + private final byte[] opaqueLinkAttribute; + + /** + * Constructor to initialize the data. + * + * @param opaqueLinkAttribute opaque link attribute + */ + private BgpLinkAttrOpaqLnkAttrib(byte[] opaqueLinkAttribute) { + this.opaqueLinkAttribute = Arrays.copyOf(opaqueLinkAttribute, + opaqueLinkAttribute.length); + } + + /** + * Returns object of this class with specified values. + * + * @param opaqueLinkAttribute opaque link attribute + * @return object of BgpLinkAttrOpaqLnkAttrib + */ + public static BgpLinkAttrOpaqLnkAttrib of(final byte[] opaqueLinkAttribute) { + return new BgpLinkAttrOpaqLnkAttrib(opaqueLinkAttribute); + } + + /** + * Reads the BGP link attributes Opaque link attribute. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrOpaqLnkAttrib + * @throws BgpParseException while parsing BgpLinkAttrOpaqLnkAttrib + */ + public static BgpLinkAttrOpaqLnkAttrib read(ChannelBuffer cb) + throws BgpParseException { + + byte[] opaqueLinkAttribute; + + short lsAttrLength = cb.readShort(); + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + opaqueLinkAttribute = new byte[lsAttrLength]; + cb.readBytes(opaqueLinkAttribute); + + return BgpLinkAttrOpaqLnkAttrib.of(opaqueLinkAttribute); + } + + /** + * Returns the Opaque link attribute. + * + * @return byte array of opaque link attribute. + */ + public byte[] attrOpaqueLnk() { + return opaqueLinkAttribute; + } + + @Override + public short getType() { + return ATTRNODE_OPAQUELNKATTRIB; + } + + @Override + public int hashCode() { + return Arrays.hashCode(opaqueLinkAttribute); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrOpaqLnkAttrib) { + BgpLinkAttrOpaqLnkAttrib other = (BgpLinkAttrOpaqLnkAttrib) obj; + return Arrays + .equals(opaqueLinkAttribute, other.opaqueLinkAttribute); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("opaqueLinkAttribute", opaqueLinkAttribute).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java new file mode 100644 index 00000000..59011d97 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java @@ -0,0 +1,246 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link protection type attribute. + */ +public final class BgpLinkAttrProtectionType implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrProtectionType.class); + + public static final int ATTRLINK_PROTECTIONTYPE = 1093; + public static final int LINK_PROTECTION_LEN = 2; + + public static final int EXTRA_TRAFFIC = 0x01; + public static final int UNPROTECTED = 0x02; + public static final int SHARED = 0x04; + public static final int DEDICATED_ONE_ISTO_ONE = 0x08; + public static final int DEDICATED_ONE_PLUS_ONE = 0x10; + public static final int ENHANCED = 0x20; + + /* Link Protection type flags */ + private final boolean bExtraTraffic; + private final boolean bUnprotected; + private final boolean bShared; + private final boolean bDedOneIstoOne; + private final boolean bDedOnePlusOne; + private final boolean bEnhanced; + + /** + * Constructor to initialize the value. + * + * @param bExtraTraffic Extra Traffic + * @param bUnprotected Unprotected + * @param bShared Shared + * @param bDedOneIstoOne Dedicated 1:1 + * @param bDedOnePlusOne Dedicated 1+1 + * @param bEnhanced Enhanced + */ + private BgpLinkAttrProtectionType(boolean bExtraTraffic, + boolean bUnprotected, + boolean bShared, boolean bDedOneIstoOne, + boolean bDedOnePlusOne, boolean bEnhanced) { + this.bExtraTraffic = bExtraTraffic; + this.bUnprotected = bUnprotected; + this.bShared = bShared; + this.bDedOneIstoOne = bDedOneIstoOne; + this.bDedOnePlusOne = bDedOnePlusOne; + this.bEnhanced = bEnhanced; + } + + /** + * Returns object of this class with specified values. + * + * @param bExtraTraffic Extra Traffic + * @param bUnprotected Unprotected + * @param bShared Shared + * @param bDedOneIstoOne Dedicated 1:1 + * @param bDedOnePlusOne Dedicated 1+1 + * @param bEnhanced Enhanced + * @return object of BgpLinkAttrProtectionType + */ + public static BgpLinkAttrProtectionType of(boolean bExtraTraffic, + boolean bUnprotected, + boolean bShared, + boolean bDedOneIstoOne, + boolean bDedOnePlusOne, + boolean bEnhanced) { + return new BgpLinkAttrProtectionType(bExtraTraffic, bUnprotected, + bShared, bDedOneIstoOne, + bDedOnePlusOne, bEnhanced); + } + + /** + * Reads the BGP link attributes protection type. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrProtectionType + * @throws BgpParseException while parsing BgpLinkAttrProtectionType + */ + public static BgpLinkAttrProtectionType read(ChannelBuffer cb) + throws BgpParseException { + short linkProtectionType; + byte higherByte; + short lsAttrLength = cb.readShort(); + + boolean bExtraTraffic; + boolean bUnprotected; + boolean bShared; + boolean bDedOneIstoOne; + boolean bDedOnePlusOne; + boolean bEnhanced; + + if ((lsAttrLength != LINK_PROTECTION_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + linkProtectionType = cb.readShort(); + higherByte = (byte) (linkProtectionType >> 8); + + bExtraTraffic = ((higherByte & (byte) EXTRA_TRAFFIC) == EXTRA_TRAFFIC); + bUnprotected = ((higherByte & (byte) UNPROTECTED) == UNPROTECTED); + bShared = ((higherByte & (byte) SHARED) == SHARED); + bDedOneIstoOne = ((higherByte & (byte) DEDICATED_ONE_ISTO_ONE) == DEDICATED_ONE_ISTO_ONE); + bDedOnePlusOne = ((higherByte & (byte) DEDICATED_ONE_PLUS_ONE) == DEDICATED_ONE_PLUS_ONE); + bEnhanced = ((higherByte & (byte) ENHANCED) == ENHANCED); + + return BgpLinkAttrProtectionType.of(bExtraTraffic, bUnprotected, + bShared, bDedOneIstoOne, + bDedOnePlusOne, bEnhanced); + } + + /** + * Returns ExtraTraffic Bit. + * + * @return ExtraTraffic Bit + */ + public boolean extraTraffic() { + return bExtraTraffic; + } + + /** + * Returns Unprotected Bit. + * + * @return Unprotected Bit + */ + public boolean unprotected() { + return bUnprotected; + } + + /** + * Returns Shared Bit. + * + * @return Shared Bit + */ + public boolean shared() { + return bShared; + } + + /** + * Returns DedOneIstoOne Bit. + * + * @return DedOneIstoOne Bit + */ + public boolean dedOneIstoOne() { + return bDedOneIstoOne; + } + + /** + * Returns DedOnePlusOne Bit. + * + * @return DedOnePlusOne Bit + */ + public boolean dedOnePlusOne() { + return bDedOnePlusOne; + } + + /** + * Returns Enhanced Bit. + * + * @return Enhanced Bit + */ + public boolean enhanced() { + return bEnhanced; + } + + @Override + public short getType() { + return ATTRLINK_PROTECTIONTYPE; + } + + @Override + public int hashCode() { + return Objects.hash(bExtraTraffic, bUnprotected, bShared, + bDedOneIstoOne, bDedOnePlusOne, bEnhanced); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrProtectionType) { + BgpLinkAttrProtectionType other = (BgpLinkAttrProtectionType) obj; + return Objects.equals(bExtraTraffic, other.bExtraTraffic) + && Objects.equals(bUnprotected, other.bUnprotected) + && Objects.equals(bShared, other.bShared) + && Objects.equals(bDedOneIstoOne, other.bDedOneIstoOne) + && Objects.equals(bDedOnePlusOne, other.bDedOnePlusOne) + && Objects.equals(bEnhanced, other.bEnhanced); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("bExtraTraffic", bExtraTraffic) + .add("bUnprotected", bUnprotected).add("bShared", bShared) + .add("bDedOneIstoOne", bDedOneIstoOne) + .add("bDedOnePlusOne", bDedOnePlusOne) + .add("bEnhanced", bEnhanced).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java new file mode 100644 index 00000000..4a6f23f9 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrSrlg.java @@ -0,0 +1,136 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link Shared Risk Link Group attribute. + */ +public class BgpLinkAttrSrlg implements BgpValueType { + + public static final short ATTRNODE_SRLG = 1097; + + /* Shared Risk Link Group */ + private List sRlg = new ArrayList(); + + /** + * Constructor to initialize the date. + * + * @param sRlg Shared Risk link group data + */ + public BgpLinkAttrSrlg(List sRlg) { + this.sRlg = sRlg; + } + + /** + * Returns object of this class with specified values. + * + * @param sRlg Shared Risk link group data + * @return object of BgpLinkAttrSrlg + */ + public static BgpLinkAttrSrlg of(ArrayList sRlg) { + return new BgpLinkAttrSrlg(sRlg); + } + + /** + * Reads the BGP link attributes Shared Risk link group data. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrSrlg + * @throws BgpParseException while parsing BgpLinkAttrSrlg + */ + public static BgpLinkAttrSrlg read(ChannelBuffer cb) + throws BgpParseException { + int tempSrlg; + ArrayList sRlg = new ArrayList(); + + short lsAttrLength = cb.readShort(); + int len = lsAttrLength / Integer.SIZE; // each element is of 4 octets + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + for (int i = 0; i < len; i++) { + tempSrlg = cb.readInt(); + sRlg.add(new Integer(tempSrlg)); + } + + return BgpLinkAttrSrlg.of(sRlg); + } + + /** + * Returns the Shared Risk link group data. + * + * @return array of Shared Risk link group data + */ + public List attrSrlg() { + return sRlg; + } + + @Override + public short getType() { + return ATTRNODE_SRLG; + } + + @Override + public int hashCode() { + return Objects.hash(sRlg); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrSrlg) { + BgpLinkAttrSrlg other = (BgpLinkAttrSrlg) obj; + return Objects.equals(sRlg, other.sRlg); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues().add("sRlg", sRlg).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java new file mode 100644 index 00000000..1ae7ecc5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetric.java @@ -0,0 +1,138 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP link state Default TE metric link attribute. + */ +public class BgpLinkAttrTeDefaultMetric implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrTeDefaultMetric.class); + + public static final int ATTRLINK_TEDEFAULTMETRIC = 1092; + public static final int TE_DATA_LEN = 4; + + /* TE Default Metric */ + private int linkTeMetric; + + /** + * Constructor to initialize the value. + * + * @param linkTeMetric TE default metric + * + */ + public BgpLinkAttrTeDefaultMetric(int linkTeMetric) { + this.linkTeMetric = linkTeMetric; + } + + /** + * Returns object of this class with specified values. + * + * @param linkTeMetric TE default metric + * @return object of BgpLinkAttrTeDefaultMetric + */ + public static BgpLinkAttrTeDefaultMetric of(final int linkTeMetric) { + return new BgpLinkAttrTeDefaultMetric(linkTeMetric); + } + + /** + * Reads the BGP link attributes of TE default metric. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrTeDefaultMetric + * @throws BgpParseException while parsing BgpLinkAttrTeDefaultMetric + */ + public static BgpLinkAttrTeDefaultMetric read(ChannelBuffer cb) + throws BgpParseException { + int linkTeMetric; + + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != TE_DATA_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + linkTeMetric = cb.readInt(); + + return new BgpLinkAttrTeDefaultMetric(linkTeMetric); + } + + /** + * Returns the TE default metrics. + * + * @return link default metric + */ + public int attrLinkDefTeMetric() { + return linkTeMetric; + } + + @Override + public short getType() { + return ATTRLINK_TEDEFAULTMETRIC; + } + + @Override + public int hashCode() { + return Objects.hash(linkTeMetric); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrTeDefaultMetric) { + BgpLinkAttrTeDefaultMetric other = (BgpLinkAttrTeDefaultMetric) obj; + return Objects.equals(linkTeMetric, other.linkTeMetric); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("linkTEMetric", linkTeMetric).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java new file mode 100644 index 00000000..c927eea5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidth.java @@ -0,0 +1,163 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP unreserved bandwidth attribute. + */ +public class BgpLinkAttrUnRsrvdLinkBandwidth implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpLinkAttrUnRsrvdLinkBandwidth.class); + + public static final int MAX_BANDWIDTH_LEN = 4; + public static final int NO_OF_BITS = 8; + public static final int NO_OF_PRIORITY = 8; + + public short sType; + + /* ISIS administrative group */ + private List maxUnResBandwidth = new ArrayList(); + + /** + * Constructor to initialize the values. + * + * @param maxUnResBandwidth Maximum Unreserved bandwidth + * @param sType returns the tag value + */ + public BgpLinkAttrUnRsrvdLinkBandwidth(List maxUnResBandwidth, + short sType) { + this.maxUnResBandwidth = maxUnResBandwidth; + this.sType = sType; + } + + /** + * Returns object of this class with specified values. + * + * @param linkPfxMetric Prefix Metric + * @param sType returns the tag value + * @return object of BgpLinkAttrUnRsrvdLinkBandwidth + */ + public static BgpLinkAttrUnRsrvdLinkBandwidth of(List linkPfxMetric, short sType) { + return new BgpLinkAttrUnRsrvdLinkBandwidth(linkPfxMetric, sType); + } + + /** + * Reads the BGP link attributes of Maximum link bandwidth. + * + * @param cb Channel buffer + * @return object of type BgpLinkAttrMaxLinkBandwidth + * @throws BgpParseException while parsing BgpLinkAttrMaxLinkBandwidth + */ + public static BgpLinkAttrUnRsrvdLinkBandwidth read(ChannelBuffer cb, + short sType) + throws BgpParseException { + ArrayList maxUnResBandwidth = new ArrayList(); + float tmp; + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != MAX_BANDWIDTH_LEN * NO_OF_PRIORITY) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + for (int i = 0; i < NO_OF_PRIORITY; i++) { + tmp = ieeeToFloatRead(cb.readInt()) * NO_OF_BITS; + maxUnResBandwidth.add(new Float(tmp)); + } + + return BgpLinkAttrUnRsrvdLinkBandwidth.of(maxUnResBandwidth, sType); + } + + /** + * Returns maximum unreserved bandwidth. + * + * @return unreserved bandwidth. + */ + public List getLinkAttrUnRsrvdLinkBandwidth() { + return maxUnResBandwidth; + } + + /** + * Parse the IEEE floating point notation and returns it in normal float. + * + * @param iVal IEEE floating point number + * @return normal float + */ + static float ieeeToFloatRead(int iVal) { + iVal = (((iVal & 0xFF) << 24) | ((iVal & 0xFF00) << 8) + | ((iVal & 0xFF0000) >> 8) | ((iVal >> 24) & 0xFF)); + + return Float.intBitsToFloat(iVal); + } + + @Override + public short getType() { + return this.sType; + } + + @Override + public int hashCode() { + return Objects.hash(maxUnResBandwidth); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpLinkAttrUnRsrvdLinkBandwidth) { + BgpLinkAttrUnRsrvdLinkBandwidth other = (BgpLinkAttrUnRsrvdLinkBandwidth) obj; + return Objects.equals(maxUnResBandwidth, other.maxUnResBandwidth); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("maxUnResBandwidth", maxUnResBandwidth).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java new file mode 100644 index 00000000..a2d7c57e --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrExtRouteTag.java @@ -0,0 +1,145 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix route Extended tag attribute. + */ +public class BgpPrefixAttrExtRouteTag implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrExtRouteTag.class); + + public static final int ATTR_PREFIX_EXTROUTETAG = 1154; + public static final int ATTR_PREFIX_EXT_LEN = 8; + + /* Prefix Route Tag */ + private List pfxExtRouteTag = new ArrayList(); + + /** + * Constructor to initialize the values. + * + * @param pfxExtRouteTag Extended route tag + */ + public BgpPrefixAttrExtRouteTag(List pfxExtRouteTag) { + this.pfxExtRouteTag = checkNotNull(pfxExtRouteTag); + } + + /** + * Returns object of this class with specified values. + * + * @param pfxExtRouteTag Prefix Metric + * @return object of BgpPrefixAttrMetric + */ + public static BgpPrefixAttrExtRouteTag of(ArrayList pfxExtRouteTag) { + return new BgpPrefixAttrExtRouteTag(pfxExtRouteTag); + } + + /** + * Reads the Extended Tag. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrExtRouteTag + * @throws BgpParseException while parsing BgpPrefixAttrExtRouteTag + */ + public static BgpPrefixAttrExtRouteTag read(ChannelBuffer cb) + throws BgpParseException { + ArrayList pfxExtRouteTag = new ArrayList(); + long temp; + + short lsAttrLength = cb.readShort(); + int len = lsAttrLength / ATTR_PREFIX_EXT_LEN; + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + for (int i = 0; i < len; i++) { + temp = cb.readLong(); + pfxExtRouteTag.add(new Long(temp)); + } + + return new BgpPrefixAttrExtRouteTag(pfxExtRouteTag); + } + + /** + * Returns Extended route tag. + * + * @return route tag + */ + public List pfxExtRouteTag() { + return pfxExtRouteTag; + } + + @Override + public short getType() { + return ATTR_PREFIX_EXTROUTETAG; + } + + @Override + public int hashCode() { + return Objects.hash(pfxExtRouteTag); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrExtRouteTag) { + BgpPrefixAttrExtRouteTag other = (BgpPrefixAttrExtRouteTag) obj; + return Objects.equals(pfxExtRouteTag, other.pfxExtRouteTag); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("pfxExtRouteTag", pfxExtRouteTag).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java new file mode 100644 index 00000000..4e84191a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlags.java @@ -0,0 +1,204 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix IGP Flag attribute. + */ +public final class BgpPrefixAttrIgpFlags implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrIgpFlags.class); + + public static final int ATTR_PREFIX_FLAGBIT = 1152; + public static final int ATTR_PREFIX_FLAG_LEN = 1; + + public static final byte FIRST_BIT = (byte) 0x80; + public static final byte SECOND_BIT = 0x40; + public static final byte THIRD_BIT = 0x20; + public static final byte FOURTH_BIT = 0x01; + + /* Prefix IGP flag bit TLV */ + private final boolean bisisUpDownBit; + private final boolean bOspfNoUnicastBit; + private final boolean bOspfLclAddrBit; + private final boolean bOspfNSSABit; + + /** + * Constructor to initialize the value. + * + * @param bisisUpDownBit IS-IS Up/Down Bit + * @param bOspfNoUnicastBit OSPF no unicast Bit + * @param bOspfLclAddrBit OSPF local address Bit + * @param bOspfNSSABit OSPF propagate NSSA Bit + */ + BgpPrefixAttrIgpFlags(boolean bisisUpDownBit, + boolean bOspfNoUnicastBit, + boolean bOspfLclAddrBit, boolean bOspfNSSABit) { + this.bisisUpDownBit = bisisUpDownBit; + this.bOspfNoUnicastBit = bOspfNoUnicastBit; + this.bOspfLclAddrBit = bOspfLclAddrBit; + this.bOspfNSSABit = bOspfNSSABit; + } + + /** + * Returns object of this class with specified values. + * + * @param bisisUpDownBit IS-IS Up/Down Bit + * @param bOspfNoUnicastBit OSPF no unicast Bit + * @param bOspfLclAddrBit OSPF local address Bit + * @param bOspfNSSABit OSPF propagate NSSA Bit + * @return object of BgpPrefixAttrIGPFlags + */ + public static BgpPrefixAttrIgpFlags of(final boolean bisisUpDownBit, + final boolean bOspfNoUnicastBit, + final boolean bOspfLclAddrBit, + final boolean bOspfNSSABit) { + return new BgpPrefixAttrIgpFlags(bisisUpDownBit, bOspfNoUnicastBit, + bOspfLclAddrBit, bOspfNSSABit); + } + + /** + * Reads the IGP Flags. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrIGPFlags + * @throws BgpParseException while parsing BgpPrefixAttrIGPFlags + */ + public static BgpPrefixAttrIgpFlags read(ChannelBuffer cb) + throws BgpParseException { + boolean bisisUpDownBit = false; + boolean bOspfNoUnicastBit = false; + boolean bOspfLclAddrBit = false; + boolean bOspfNSSABit = false; + + short lsAttrLength = cb.readShort(); + + if ((lsAttrLength != ATTR_PREFIX_FLAG_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + byte nodeFlagBits = cb.readByte(); + + bisisUpDownBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT); + bOspfNoUnicastBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT); + bOspfLclAddrBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT); + bOspfNSSABit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT); + + return BgpPrefixAttrIgpFlags.of(bisisUpDownBit, bOspfNoUnicastBit, + bOspfLclAddrBit, bOspfNSSABit); + } + + /** + * Returns the IS-IS Up/Down Bit set or not. + * + * @return IS-IS Up/Down Bit set or not + */ + public boolean isisUpDownBit() { + return bisisUpDownBit; + } + + /** + * Returns the OSPF no unicast Bit set or not. + * + * @return OSPF no unicast Bit set or not + */ + public boolean ospfNoUnicastBit() { + return bOspfNoUnicastBit; + } + + /** + * Returns the OSPF local address Bit set or not. + * + * @return OSPF local address Bit set or not + */ + public boolean ospfLclAddrBit() { + return bOspfLclAddrBit; + } + + /** + * Returns the OSPF propagate NSSA Bit set or not. + * + * @return OSPF propagate NSSA Bit set or not + */ + public boolean ospfNSSABit() { + return bOspfNSSABit; + } + + @Override + public short getType() { + return ATTR_PREFIX_FLAGBIT; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, + bOspfNSSABit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrIgpFlags) { + BgpPrefixAttrIgpFlags other = (BgpPrefixAttrIgpFlags) obj; + return Objects.equals(bisisUpDownBit, other.bisisUpDownBit) + && Objects.equals(bOspfNoUnicastBit, + other.bOspfNoUnicastBit) + && Objects.equals(bOspfLclAddrBit, other.bOspfLclAddrBit) + && Objects.equals(bOspfNSSABit, other.bOspfNSSABit); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("bisisUpDownBit", bisisUpDownBit) + .add("bOspfNoUnicastBit", bOspfNoUnicastBit) + .add("bOspfLclAddrBit", bOspfLclAddrBit) + .add("bOspfNSSABit", bOspfNSSABit).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java new file mode 100644 index 00000000..1886102c --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java @@ -0,0 +1,137 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix metric attribute. + */ +public class BgpPrefixAttrMetric implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrMetric.class); + + public static final int ATTR_PREFIX_METRIC = 1155; + public static final int ATTR_PREFIX_LEN = 4; + + /* TE Default Metric */ + private final int linkPfxMetric; + + /** + * Constructor to initialize value. + * + * @param linkPfxMetric Prefix Metric + */ + public BgpPrefixAttrMetric(int linkPfxMetric) { + this.linkPfxMetric = linkPfxMetric; + } + + /** + * Returns object of this class with specified values. + * + * @param linkPfxMetric Prefix Metric + * @return object of BgpPrefixAttrMetric + */ + public static BgpPrefixAttrMetric of(final int linkPfxMetric) { + return new BgpPrefixAttrMetric(linkPfxMetric); + } + + /** + * Reads the Prefix Metric. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrMetric + * @throws BgpParseException while parsing BgpPrefixAttrMetric + */ + public static BgpPrefixAttrMetric read(ChannelBuffer cb) + throws BgpParseException { + int linkPfxMetric; + + short lsAttrLength = cb.readShort(); // 4 Bytes + + if ((lsAttrLength != ATTR_PREFIX_LEN) + || (cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + linkPfxMetric = cb.readInt(); + + return BgpPrefixAttrMetric.of(linkPfxMetric); + } + + /** + * Returns the Prefix Metric. + * + * @return Prefix Metric + */ + public int attrPfxMetric() { + return linkPfxMetric; + } + + @Override + public short getType() { + return ATTR_PREFIX_METRIC; + } + + @Override + public int hashCode() { + return Objects.hash(linkPfxMetric); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrMetric) { + BgpPrefixAttrMetric other = (BgpPrefixAttrMetric) obj; + return Objects.equals(linkPfxMetric, other.linkPfxMetric); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("linkPfxMetric", linkPfxMetric).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java new file mode 100644 index 00000000..6f7a74bb --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueData.java @@ -0,0 +1,139 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix opaque data attribute. + */ +public final class BgpPrefixAttrOpaqueData implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrOpaqueData.class); + + public static final int ATTR_PREFIX_OPAQUEDATA = 1157; + + /* Opaque Node Attribute */ + private final byte[] opaquePrefixAttribute; + + /** + * Constructor to initialize the values. + * + * @param opaquePrefixAttribute opaque prefix data + */ + public BgpPrefixAttrOpaqueData(byte[] opaquePrefixAttribute) { + this.opaquePrefixAttribute = Arrays + .copyOf(opaquePrefixAttribute, opaquePrefixAttribute.length); + } + + /** + * Returns object of this class with specified values. + * + * @param opaquePrefixAttribute opaque prefix data + * @return object of BgpPrefixAttrOpaqueData + */ + public static BgpPrefixAttrOpaqueData of(final byte[] opaquePrefixAttribute) { + return new BgpPrefixAttrOpaqueData(opaquePrefixAttribute); + } + + /** + * Reads the Opaque Prefix Attribute. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrOpaqueData + * @throws BgpParseException while parsing BgpPrefixAttrOpaqueData + */ + public static BgpPrefixAttrOpaqueData read(ChannelBuffer cb) + throws BgpParseException { + byte[] opaquePrefixAttribute; + + short lsAttrLength = cb.readShort(); + opaquePrefixAttribute = new byte[lsAttrLength]; + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + cb.readBytes(opaquePrefixAttribute); + + return BgpPrefixAttrOpaqueData.of(opaquePrefixAttribute); + } + + /** + * Returns the Opaque prefix attribute name. + * + * @return opaque prefix name + */ + public byte[] getOpaquePrefixAttribute() { + return opaquePrefixAttribute; + } + + @Override + public short getType() { + return ATTR_PREFIX_OPAQUEDATA; + } + + @Override + public int hashCode() { + return Arrays.hashCode(opaquePrefixAttribute); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrOpaqueData) { + BgpPrefixAttrOpaqueData other = (BgpPrefixAttrOpaqueData) obj; + return Arrays.equals(opaquePrefixAttribute, + other.opaquePrefixAttribute); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("opaquePrefixAttribute", getOpaquePrefixAttribute()) + .toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java new file mode 100644 index 00000000..4e9db1ee --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java @@ -0,0 +1,193 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix OSPF Forwarding address attribute. + */ +public class BgpPrefixAttrOspfFwdAddr implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrOspfFwdAddr.class); + + public static final int ATTR_PREFIX_OSPFFWDADDR = 1156; + public static final int IPV4_LEN = 4; + public static final int IPV6_LEN = 16; + + /* OSPF Forwarding Address */ + private final short lsAttrLength; + private final Ip4Address ip4RouterId; + private final Ip6Address ip6RouterId; + + /** + * Constructor to initialize the value. + * + * @param lsAttrLength length of the IP address + * @param ip4RouterId Valid IPV4 address if length is 4 else null + * @param ip6RouterId Valid IPV6 address if length is 16 else null + */ + public BgpPrefixAttrOspfFwdAddr(short lsAttrLength, Ip4Address ip4RouterId, + Ip6Address ip6RouterId) { + this.lsAttrLength = lsAttrLength; + this.ip4RouterId = ip4RouterId; + this.ip6RouterId = ip6RouterId; + } + + /** + * Returns object of this class with specified values. + * + * @param lsAttrLength length of the IP address + * @param ip4RouterId Valid IPV4 address if length is 4 else null + * @param ip6RouterId Valid IPV6 address if length is 16 else null + * @return object of BgpPrefixAttrOspfFwdAddr + */ + public static BgpPrefixAttrOspfFwdAddr of(final short lsAttrLength, + final Ip4Address ip4RouterId, + final Ip6Address ip6RouterId) { + return new BgpPrefixAttrOspfFwdAddr(lsAttrLength, ip4RouterId, + ip6RouterId); + } + + /** + * Reads the OSPF Forwarding Address. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrOSPFFwdAddr + * @throws BgpParseException while parsing BgpPrefixAttrOspfFwdAddr + */ + public static BgpPrefixAttrOspfFwdAddr read(ChannelBuffer cb) + throws BgpParseException { + short lsAttrLength; + byte[] ipBytes; + Ip4Address ip4RouterId = null; + Ip6Address ip6RouterId = null; + + lsAttrLength = cb.readShort(); + ipBytes = new byte[lsAttrLength]; + + if ((cb.readableBytes() < lsAttrLength)) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + cb.readBytes(ipBytes); + + if (IPV4_LEN == lsAttrLength) { + ip4RouterId = Ip4Address.valueOf(ipBytes); + } else if (IPV6_LEN == lsAttrLength) { + ip6RouterId = Ip6Address.valueOf(ipBytes); + } + + return BgpPrefixAttrOspfFwdAddr.of(lsAttrLength, ip4RouterId, + ip6RouterId); + } + + /** + * Returns IPV4 Address of OSPF forwarding address. + * + * @return IPV4 address + */ + public Ip4Address ospfv4FwdAddr() { + return ip4RouterId; + } + + /** + * Returns IPV6 Address of OSPF forwarding address. + * + * @return IPV6 address + */ + public Ip6Address ospfv6FwdAddr() { + return ip6RouterId; + } + + /** + * Returns OSPF forwarding address length. + * + * @return length of the ip address + */ + public short ospfFwdAddrLen() { + return lsAttrLength; + } + + @Override + public short getType() { + return ATTR_PREFIX_OSPFFWDADDR; + } + + @Override + public int hashCode() { + if (IPV4_LEN == lsAttrLength) { + return Objects.hash(ip4RouterId); + } else { + return Objects.hash(ip6RouterId); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrOspfFwdAddr) { + BgpPrefixAttrOspfFwdAddr other = (BgpPrefixAttrOspfFwdAddr) obj; + if (IPV4_LEN == lsAttrLength) { + return Objects.equals(ip4RouterId, other.ip4RouterId); + } else { + return Objects.equals(ip6RouterId, other.ip6RouterId); + } + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + if (IPV4_LEN == lsAttrLength) { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("ip4RouterId", ip4RouterId).toString(); + } else { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("ip6RouterId", ip6RouterId).toString(); + } + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java new file mode 100644 index 00000000..3894c003 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTag.java @@ -0,0 +1,142 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.util.Validation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * Implements BGP prefix route tag attribute. + */ +public class BgpPrefixAttrRouteTag implements BgpValueType { + + protected static final Logger log = LoggerFactory + .getLogger(BgpPrefixAttrRouteTag.class); + + public static final short ATTR_PREFIX_ROUTETAG = 1153; + + /* Prefix Route Tag */ + private List pfxRouteTag = new ArrayList(); + + /** + * Constructor to initialize the values. + * + * @param pfxRouteTag prefix route tag + */ + public BgpPrefixAttrRouteTag(List pfxRouteTag) { + this.pfxRouteTag = pfxRouteTag; + } + + /** + * Returns object of this class with specified values. + * + * @param pfxRouteTag Prefix Metric + * @return object of BgpPrefixAttrRouteTag + */ + public static BgpPrefixAttrRouteTag of(ArrayList pfxRouteTag) { + return new BgpPrefixAttrRouteTag(pfxRouteTag); + } + + /** + * Reads the Route Tag. + * + * @param cb ChannelBuffer + * @return object of BgpPrefixAttrRouteTag + * @throws BgpParseException while parsing BgpPrefixAttrRouteTag + */ + public static BgpPrefixAttrRouteTag read(ChannelBuffer cb) + throws BgpParseException { + int tmp; + ArrayList pfxRouteTag = new ArrayList(); + + short lsAttrLength = cb.readShort(); + int len = lsAttrLength / Integer.SIZE; + + if (cb.readableBytes() < lsAttrLength) { + Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, + BgpErrorType.ATTRIBUTE_LENGTH_ERROR, + lsAttrLength); + } + + for (int i = 0; i < len; i++) { + tmp = cb.readInt(); + pfxRouteTag.add(new Integer(tmp)); + } + + return BgpPrefixAttrRouteTag.of(pfxRouteTag); + } + + /** + * Returns the prefix route tag. + * + * @return route tag + */ + public List getPfxRouteTag() { + return pfxRouteTag; + } + + @Override + public short getType() { + return ATTR_PREFIX_ROUTETAG; + } + + @Override + public int hashCode() { + return Objects.hash(pfxRouteTag); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BgpPrefixAttrRouteTag) { + BgpPrefixAttrRouteTag other = (BgpPrefixAttrRouteTag) obj; + return Objects.equals(pfxRouteTag, other.pfxRouteTag); + } + return false; + } + + @Override + public int write(ChannelBuffer cb) { + // TODO This will be implemented in the next version + return 0; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("pfxRouteTag", pfxRouteTag).toString(); + } + + @Override + public int compareTo(Object o) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java new file mode 100755 index 00000000..e2a74dbc --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of BGP Link state attribute Tlvs. + */ +package org.onosproject.bgpio.types.attr; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java new file mode 100755 index 00000000..1f2ed95e --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of Tlvs, Attributes and Descriptors. + */ +package org.onosproject.bgpio.types; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java new file mode 100644 index 00000000..9649bf16 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.util; + +/** + * Provides Constants usage for BGP. + */ +public final class Constants { + private Constants() { + } + + public static final short TYPE_AND_LEN = 4; + public static final short TYPE_AND_LEN_AS_SHORT = 4; + public static final short TYPE_AND_LEN_AS_BYTE = 3; + public static final int ISIS_LEVELONE = 1; + public static final int ISIS_LEVELTWO = 2; + public static final int OSPFV2 = 3; + public static final int DIRECT = 4; + public static final int STATIC_CONFIGURATION = 5; + public static final int OSPFV3 = 6; + public static final short AFI_VALUE = 16388; + public static final byte VPN_SAFI_VALUE = (byte) 0x80; + public static final byte SAFI_VALUE = 71; +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java new file mode 100644 index 00000000..663b1e9a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/UnSupportedAttribute.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.util; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides methods to handle UnSupportedAttribute. + */ +public final class UnSupportedAttribute { + protected static final Logger log = LoggerFactory.getLogger(UnSupportedAttribute.class); + + private UnSupportedAttribute() { + } + + /** + * Reads channel buffer parses attribute header and skips specified length. + * + * @param cb channelBuffer + */ + public static void read(ChannelBuffer cb) { + Validation parseFlags = Validation.parseAttributeHeader(cb); + cb.skipBytes(parseFlags.getLength()); + } + + /** + * Skip specified bytes in channel buffer. + * + * @param cb channelBuffer + * @param length to be skipped + */ + public static void skipBytes(ChannelBuffer cb, short length) { + cb.skipBytes(length); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java new file mode 100644 index 00000000..23dd1a75 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java @@ -0,0 +1,223 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgpio.util; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.primitives.Ints; + +/** + * Provides methods to parse attribute header, validate length and type. + */ +public class Validation { + private static final Logger log = LoggerFactory.getLogger(Validation.class); + public static final byte FIRST_BIT = (byte) 0x80; + public static final byte SECOND_BIT = 0x40; + public static final byte THIRD_BIT = 0x20; + public static final byte FOURTH_BIT = (byte) 0x10; + public static final byte IPV4_SIZE = 4; + private boolean firstBit; + private boolean secondBit; + private boolean thirdBit; + private boolean fourthBit; + private int len; + private boolean isShort; + + /** + * Constructor to initialize parameter. + * + * @param firstBit in AttributeFlags + * @param secondBit in AttributeFlags + * @param thirdBit in AttributeFlags + * @param fourthBit in AttributeFlags + * @param len length + * @param isShort true if length is read as short otherwise false + */ + Validation(boolean firstBit, boolean secondBit, boolean thirdBit, boolean fourthBit, int len, boolean isShort) { + this.firstBit = firstBit; + this.secondBit = secondBit; + this.thirdBit = thirdBit; + this.fourthBit = fourthBit; + this.len = len; + this.isShort = isShort; + } + + /** + * Parses attribute Header. + * + * @param cb ChannelBuffer + * @return object of Validation + */ + public static Validation parseAttributeHeader(ChannelBuffer cb) { + + boolean firstBit; + boolean secondBit; + boolean thirdBit; + boolean fourthBit; + boolean isShort; + byte flags = cb.readByte(); + byte typeCode = cb.readByte(); + byte temp = flags; + //first Bit : Optional (1) or well-known (0) + firstBit = ((temp & FIRST_BIT) == FIRST_BIT); + //second Bit : Transitive (1) or non-Transitive (0) + secondBit = ((temp & SECOND_BIT) == SECOND_BIT); + //third Bit : partial (1) or complete (0) + thirdBit = ((temp & THIRD_BIT) == THIRD_BIT); + //forth Bit(Extended Length bit) : Attribute Length is 1 octects (0) or 2 octects (1) + fourthBit = ((temp & FOURTH_BIT) == FOURTH_BIT); + int len; + if (fourthBit) { + isShort = true; + short length = cb.readShort(); + len = length; + } else { + isShort = false; + byte length = cb.readByte(); + len = length; + } + return new Validation(firstBit, secondBit, thirdBit, fourthBit, len, isShort); + } + + /** + * Throws exception if length is not correct. + * + * @param errorCode Error code + * @param subErrCode Sub Error Code + * @param length erroneous length + * @throws BgpParseException for erroneous length + */ + public static void validateLen(byte errorCode, byte subErrCode, int length) throws BgpParseException { + byte[] errLen = Ints.toByteArray(length); + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(errLen); + throw new BgpParseException(errorCode, subErrCode, buffer); + } + + /** + * Throws exception if type is not correct. + * + * @param errorCode Error code + * @param subErrCode Sub Error Code + * @param type erroneous type + * @throws BgpParseException for erroneous type + */ + public static void validateType(byte errorCode, byte subErrCode, int type) throws BgpParseException { + byte[] errType = Ints.toByteArray(type); + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(errType); + throw new BgpParseException(errorCode, subErrCode, buffer); + } + + /** + * Convert byte array to InetAddress. + * + * @param length of IpAddress + * @param cb channelBuffer + * @return InetAddress + */ + public static InetAddress toInetAddress(int length, ChannelBuffer cb) { + byte[] address = new byte[length]; + cb.readBytes(address, 0, length); + InetAddress ipAddress = null; + try { + ipAddress = InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + log.info("InetAddress convertion failed"); + } + return ipAddress; + } + + /** + * Returns first bit in type flags. + * + * @return first bit in type flags + */ + public boolean getFirstBit() { + return this.firstBit; + } + + /** + * Returns second bit in type flags. + * + * @return second bit in type flags + */ + public boolean getSecondBit() { + return this.secondBit; + } + + /** + * Returns third bit in type flags. + * + * @return third bit in type flags + */ + public boolean getThirdBit() { + return this.thirdBit; + } + + /** + * Returns fourth bit in type flags. + * + * @return fourth bit in type flags + */ + public boolean getFourthBit() { + return this.fourthBit; + } + + /** + * Returns attribute length. + * + * @return attribute length + */ + public int getLength() { + return this.len; + } + + /** + * Returns whether attribute length read in short or byte. + * + * @return whether attribute length read in short or byte + */ + public boolean isShort() { + return this.isShort; + } + + /** + * Converts byte array of prefix value to IpPrefix object. + * + * @param value byte array of prefix value + * @param length prefix length in bits + * @return object of IpPrefix + */ + public static IpPrefix bytesToPrefix(byte[] value, int length) { + if (value.length != IPV4_SIZE) { + value = Arrays.copyOf(value, IPV4_SIZE); + } + IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length); + return ipPrefix; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java new file mode 100755 index 00000000..3229d89a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of BGP utility functions. + */ +package org.onosproject.bgpio.util; diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java new file mode 100644 index 00000000..d4c3b610 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrMaxLinkBandwidthTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import org.junit.Test; +import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP link max bandwidth attribute. + */ +public class BgpLinkAttrMaxLinkBandwidthTest { + private final float val = 0x010203; + private final short valLen = 3; + private final float val1 = 0x01020304; + private final short val1Len = 4; + + private final BgpLinkAttrMaxLinkBandwidth data = BgpLinkAttrMaxLinkBandwidth + .of(val, valLen); + private final BgpLinkAttrMaxLinkBandwidth sameAsData = BgpLinkAttrMaxLinkBandwidth + .of(val, valLen); + private final BgpLinkAttrMaxLinkBandwidth diffData = BgpLinkAttrMaxLinkBandwidth + .of(val1, val1Len); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java new file mode 100644 index 00000000..b6453c45 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrTeDefaultMetricTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import org.junit.Test; +import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP link TE default metric attribute. + */ +public class BgpLinkAttrTeDefaultMetricTest { + private final int val = 0x010203; + private final int val1 = 0x01020304; + + private final BgpLinkAttrTeDefaultMetric data = BgpLinkAttrTeDefaultMetric + .of(val); + private final BgpLinkAttrTeDefaultMetric sameAsData = BgpLinkAttrTeDefaultMetric + .of(val); + private final BgpLinkAttrTeDefaultMetric diffData = BgpLinkAttrTeDefaultMetric + .of(val1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java new file mode 100644 index 00000000..7ba6a880 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOpaqueDataTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import org.junit.Test; +import org.onosproject.bgpio.types.attr.BgpPrefixAttrOpaqueData; + +import com.google.common.testing.EqualsTester; + +/** + * Test for prefix attribute opaque data Tlv. + */ +public class BgpPrefixAttrOpaqueDataTest { + private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; + private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; + + private final BgpPrefixAttrOpaqueData isisData = BgpPrefixAttrOpaqueData + .of(array); + private final BgpPrefixAttrOpaqueData sameAsIsisData = BgpPrefixAttrOpaqueData + .of(array); + private final BgpPrefixAttrOpaqueData isisDiff = BgpPrefixAttrOpaqueData + .of(array1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java new file mode 100755 index 00000000..682c1bc0 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpKeepaliveMsgTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.core.Is.is; + +/** + * Test case for BGP KEEPALIVE Message. + */ +public class BgpKeepaliveMsgTest { + + /** + * This test case checks BGP Keepalive message. + */ + @Test + public void keepaliveMessageTest1() throws BgpParseException { + + // BGP KEEPALIVE Message + byte[] keepaliveMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + 0x00, 0x13, 0x04}; + + byte[] testKeepaliveMsg; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(keepaliveMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpKeepaliveMsg.class)); + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + + int readLen = buf.writerIndex(); + testKeepaliveMsg = new byte[readLen]; + buf.readBytes(testKeepaliveMsg, 0, readLen); + + assertThat(testKeepaliveMsg, is(keepaliveMsg)); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java new file mode 100644 index 00000000..6dfa57ee --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpNotificationMsgTest.java @@ -0,0 +1,224 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.core.Is.is; + +/** + * Test for Notification message. + */ +public class BgpNotificationMsgTest { + + /** + * Notification message with error code, error subcode and data. + * + * @throws BgpParseException while decoding and encoding notification message + */ + @Test + public void bgpNotificationMessageTest1() throws BgpParseException { + byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, + 0x17, 0x03, 0x02, 0x02, + (byte) 0xfe, (byte) 0xb0}; + + byte[] testNotificationMsg = {0}; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(notificationMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpNotificationMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + testNotificationMsg = buf.array(); + + int iReadLen = buf.writerIndex() - 0; + testNotificationMsg = new byte[iReadLen]; + buf.readBytes(testNotificationMsg, 0, iReadLen); + assertThat(testNotificationMsg, is(notificationMsg)); + } + + /** + * Notification message without data. + * + * @throws BgpParseException while decoding and encoding notification message + */ + @Test + public void bgpNotificationMessageTest2() throws BgpParseException { + byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, + 0x15, 0x03, 0x02, 0x00}; + + byte[] testNotificationMsg = {0}; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(notificationMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpNotificationMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + testNotificationMsg = buf.array(); + + int iReadLen = buf.writerIndex() - 0; + testNotificationMsg = new byte[iReadLen]; + buf.readBytes(testNotificationMsg, 0, iReadLen); + assertThat(testNotificationMsg, is(notificationMsg)); + } + + //Negative scenarios + /** + * Notification message with wrong maker value. + * + * @throws BgpParseException while decoding and encoding notification message + */ + @Test(expected = BgpParseException.class) + public void bgpNotificationMessageTest3() throws BgpParseException { + byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + 0x01, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, + 0x15, 0x03, 0x02, 0x00}; + + byte[] testNotificationMsg = {0}; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(notificationMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpNotificationMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + testNotificationMsg = buf.array(); + + int iReadLen = buf.writerIndex() - 0; + testNotificationMsg = new byte[iReadLen]; + buf.readBytes(testNotificationMsg, 0, iReadLen); + assertThat(testNotificationMsg, is(notificationMsg)); + } + + /** + * Notification message without error subcode. + * + * @throws BgpParseException while decoding and encoding notification message + */ + @Test(expected = BgpParseException.class) + public void bgpNotificationMessageTest4() throws BgpParseException { + byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, + 0x14, 0x03, 0x02}; + + byte[] testNotificationMsg = {0}; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(notificationMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpNotificationMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + testNotificationMsg = buf.array(); + + int iReadLen = buf.writerIndex() - 0; + testNotificationMsg = new byte[iReadLen]; + buf.readBytes(testNotificationMsg, 0, iReadLen); + assertThat(testNotificationMsg, is(notificationMsg)); + } + + /** + * Notification message with wrong message length. + * + * @throws BgpParseException while decoding and encoding notification message + */ + @Test(expected = BgpParseException.class) + public void bgpNotificationMessageTest5() throws BgpParseException { + byte[] notificationMsg = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, + 0x14, 0x03, 0x02, 0x02}; + + byte[] testNotificationMsg = {0}; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(notificationMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpNotificationMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + testNotificationMsg = buf.array(); + + int iReadLen = buf.writerIndex() - 0; + testNotificationMsg = new byte[iReadLen]; + buf.readBytes(testNotificationMsg, 0, iReadLen); + assertThat(testNotificationMsg, is(notificationMsg)); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java new file mode 100755 index 00000000..1fe4036f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpOpenMsgTest.java @@ -0,0 +1,314 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.types.BgpHeader; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.core.Is.is; + +/** + * Test cases for BGP Open Message. + */ +public class BgpOpenMsgTest { + + /** + * This test case checks open message without optional parameter. + */ + @Test + public void openMessageTest1() throws BgpParseException { + //Open message without optional parameter + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + 0x00, 0x1d, 0x01, 0X04, (byte) 0xfe, 0x09, 0x00, + (byte) 0xb4, (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, + 0x00}; + + byte[] testOpenMsg; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + + int readLen = buf.writerIndex(); + testOpenMsg = new byte[readLen]; + buf.readBytes(testOpenMsg, 0, readLen); + + assertThat(testOpenMsg, is(openMsg)); + } + + /** + * This test case checks open message with Multiprotocol extension + * capability. + */ + @Test + public void openMessageTest2() throws BgpParseException { + + // OPEN Message (MultiProtocolExtension-CAPABILITY). + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x25, + 0x01, //BGP Header + 0X04, //Version + (byte) 0x00, (byte) 0xc8, // AS Number + 0x00, (byte) 0xb4, // Hold time + (byte) 0xb6, (byte) 0x02, 0x5d, + (byte) 0xc8, // BGP Identifier + 0x08, 0x02, 0x06, // Opt Parameter length + 0x01, 0x04, 0x00, 0x00, 0x00, (byte) 0xc8}; // Multiprotocol CAPABILITY + + byte[] testOpenMsg; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + + int readLen = buf.writerIndex(); + testOpenMsg = new byte[readLen]; + buf.readBytes(testOpenMsg, 0, readLen); + + assertThat(testOpenMsg, is(openMsg)); + } + + /** + * This test case checks open message with Four-octet AS number + * capability. + */ + @Test + public void openMessageTest3() throws BgpParseException { + + // OPEN Message (Four-Octet AS number capability). + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x25, + 0x01, //BGPHeader + 0X04, //Version + (byte) 0x00, (byte) 0xc8, //AS Number + 0x00, (byte) 0xb4, //Hold Time + (byte) 0xb6, (byte) 0x02, 0x5d, + (byte) 0xc8, //BGP Identifier + 0x08, 0x02, 0x06, //Opt Parameter Length + 0x41, 0x04, 0x00, 0x01, 0x00, 0x01}; //Four Octet AS Number-CAPABILITY-TLV + + byte[] testOpenMsg; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + + int readLen = buf.writerIndex(); + testOpenMsg = new byte[readLen]; + buf.readBytes(testOpenMsg, 0, readLen); + + assertThat(testOpenMsg, is(openMsg)); + } + + /** + * This test case checks open message with capabilities. + */ + @Test + public void openMessageTest4() throws BgpParseException { + + // OPEN Message with capabilities. + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x2b, + 0x01, //BGPHeader + 0X04, //Version + (byte) 0x00, (byte) 0xc8, //AS Number + 0x00, (byte) 0xb4, //Hold Time + (byte) 0xb6, (byte) 0x02, 0x5d, (byte) 0xc8, //BGP Identifier + 0x0e, 0x02, 0x0c, //Opt Parameter Length + 0x01, 0x04, 0x00, 0x00, 0x00, (byte) 0xc8, // Multiprotocol extension capability + 0x41, 0x04, 0x00, 0x01, 0x00, 0x01}; //Four Octet AS Number-CAPABILITY-TLV + + byte[] testOpenMsg; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + message.writeTo(buf); + + int readLen = buf.writerIndex(); + testOpenMsg = new byte[readLen]; + buf.readBytes(testOpenMsg, 0, readLen); + + assertThat(testOpenMsg, is(openMsg)); + } + + /** + * In this test case, Invalid version is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void openMessageTest5() throws BgpParseException { + + // OPEN Message with invalid version number. + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x1d, 0x01, 0X05, + (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, + (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, + 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + } + + /** + * In this test case, Marker is set as 0 in input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void openMessageTest6() throws BgpParseException { + + // OPEN Message with marker set to 0. + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x00, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + 0x00, 0x00, 0x1d, 0x01, 0X04, + (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, + (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, + 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + } + + /** + * In this test case, Invalid message length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void openMessageTest7() throws BgpParseException { + + // OPEN Message with invalid header length. + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x1e, 0x01, 0X04, + (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, + (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, + 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + } + + /** + * In this test case, Invalid message type is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void openMessageTest8() throws BgpParseException { + + // OPEN Message with invalid message type. + byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, 0x00, 0x1d, 0x05, 0X04, + (byte) 0xfe, 0x09, 0x00, (byte) 0xb4, + (byte) 0xc0, (byte) 0xa8, 0x00, 0x0f, + 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(openMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpOpenMsg.class)); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpUpdateMsgTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpUpdateMsgTest.java new file mode 100755 index 00000000..8e1cd202 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/BgpUpdateMsgTest.java @@ -0,0 +1,1496 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.protocol; + + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.core.Is.is; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors; +import org.onosproject.bgpio.protocol.ver4.BgpPathAttributes; +import org.onosproject.bgpio.types.As4Path; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.AutonomousSystemTlv; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.types.BgpLSIdentifierTlv; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.IPReachabilityInformationTlv; +import org.onosproject.bgpio.types.IsIsNonPseudonode; +import org.onosproject.bgpio.types.IsIsPseudonode; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.MpReachNlri; +import org.onosproject.bgpio.types.MpUnReachNlri; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgpio.types.NextHop; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Origin.ORIGINTYPE; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +/** + * Test cases for BGP update Message. + */ +public class BgpUpdateMsgTest { + protected static final Logger log = LoggerFactory.getLogger(BgpUpdateMsgTest.class); + public static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + public static final byte UPDATE_MSG_TYPE = 0x2; + + /** + * This test case checks update message with no withdrawn routes + * and path attributes. + */ + @Test + public void bgpUpdateMessageTest01() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x17, 0x02, 0x00, 0x00, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 23)); + } + + /** + * In this test case, Marker is set as 0 in input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest02() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x17, 0x02, 0x00, 0x00, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid message length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest03() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid message type is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest04() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x17, 0x06, 0x00, 0x00, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with withdrawn routes. + */ + @Test + public void bgpUpdateMessageTest05() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x1b, 0x02, 0x00, 0x04, 0x18, 0x0a, 0x01, 0x01, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 27)); + + ListIterator listIterator1 = other.withdrawnRoutes().listIterator(); + byte[] prefix = new byte[] {0x0a, 0x01, 0x01, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 24)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + } + + /** + * In this test case, Invalid withdrawn route length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest06() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x1b, 0x02, 0x00, 0x04, 0x19, 0x0a, 0x01, 0x01, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with path attributes. + */ + @Test + public void bgpUpdateMessageTest07() throws BgpParseException { + byte[] updateMsg = new byte [] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x01, 0x01, + 0x00, 0x40, 0x02, 0x00, 0x40, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03, (byte) 0x80, 0x04, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x64, 0x18, 0x0a, 0x1e, 0x03, 0x18, 0x0a, 0x1e, + 0x02, 0x18, 0x0a, 0x1e, 0x01}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 63)); + + BgpValueType testPathAttribute; + Origin origin; + AsPath asPath; + NextHop nexthop; + Med med; + LocalPref localPref; + + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); // AS PATH value is empty in hex dump + asPath = (AsPath) testPathAttribute; + List asPathValues = asPath.asPathSeq(); + assertThat(asPathValues.isEmpty(), is(true)); + + testPathAttribute = listIterator.next(); + nexthop = (NextHop) testPathAttribute; + byte[] nextHopAddr = new byte[] {0x03, 0x03, 0x03, 0x03}; + assertThat(nexthop.nextHop().toOctets(), is(nextHopAddr)); + + testPathAttribute = listIterator.next(); + med = (Med) testPathAttribute; + assertThat(med.med(), is(0)); + + testPathAttribute = listIterator.next(); + localPref = (LocalPref) testPathAttribute; + assertThat(localPref.localPref(), is(100)); + + ListIterator listIterator1 = other.nlri().listIterator(); + byte[] prefix = new byte[] {0x0a, 0x1e, 0x03, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 24)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + } + + /** + * In this test case, Invalid ORIGIN flags is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest08() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid ORIGIN value is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest09() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x04, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, update message without path attribute is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest10() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x1a, 0x02, 0x00, 0x04, 0x18, 0x0a, 0x01, 0x01, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, update message with incorrect path attribute length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest11() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x1b, 0x02, 0x00, 0x04, 0x18, 0x0a, 0x01, 0x01, 0x00, 0x01}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid MED flags is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest12() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0xff, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid AS Path flags is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest13() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + (byte) 0xff, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid MP reach flags is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest14() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0xff, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid SAFI is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest15() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x49, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid AFI is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest16() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x06, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid res is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest17() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + (byte) 0xff, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x01, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with node NLRI. + */ + @Test + public void bgpUpdateMessageTest18() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 96)); + + BgpValueType testPathAttribute; + Origin origin; + AsPath asPath; + Med med; + MpReachNlri mpReach; + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); + asPath = (AsPath) testPathAttribute; + ListIterator listIterator2 = asPath.asPathSeq().listIterator(); + assertThat(listIterator2.next(), is((short) 65001)); + + testPathAttribute = listIterator.next(); + med = (Med) testPathAttribute; + assertThat(med.med(), is(0)); + + testPathAttribute = listIterator.next(); + mpReach = (MpReachNlri) testPathAttribute; + assertThat(mpReach.mpReachNlriLen(), is((int) 52)); + assertThat(mpReach.getType(), is((short) 14)); + + List testMpReachNlri = new LinkedList<>(); + testMpReachNlri = mpReach.mpReachNlri(); + + ListIterator list1 = testMpReachNlri.listIterator(); + BgpLSNlri testnlri = list1.next(); + NlriType nlriType = org.onosproject.bgpio.protocol.NlriType.NODE; + ProtocolType protocolId = org.onosproject.bgpio.protocol.linkstate. + BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO; + assertThat(testnlri.getIdentifier(), is((long) 0)); + assertThat(testnlri.getNlriType(), is(nlriType)); + assertThat(testnlri.getProtocolId(), is(protocolId)); + + BgpNodeLSNlriVer4 testNodenlri = (BgpNodeLSNlriVer4) testnlri; + + BgpNodeLSIdentifier testLocalNodeDescriptors = testNodenlri.getLocalNodeDescriptors(); + + List testSubTlvs = new LinkedList<>(); + NodeDescriptors localNodeDescriptors = testLocalNodeDescriptors.getNodedescriptors(); + testSubTlvs = localNodeDescriptors.getSubTlvs(); + ListIterator subtlvlist1 = testSubTlvs.listIterator(); + + AutonomousSystemTlv testAutonomousSystemTlv = (AutonomousSystemTlv) subtlvlist1.next(); + assertThat(testAutonomousSystemTlv.getAsNum(), is(2222)); + assertThat(testAutonomousSystemTlv.getType(), is((short) 512)); + + BgpLSIdentifierTlv testBGPLSIdentifierTlv = (BgpLSIdentifierTlv) subtlvlist1.next(); + assertThat(testBGPLSIdentifierTlv.getBgpLsIdentifier(), is(33686018)); + assertThat(testBGPLSIdentifierTlv.getType(), is((short) 513)); + + IsIsNonPseudonode testIsIsNonPseudonode = (IsIsNonPseudonode) subtlvlist1.next(); + byte[] expISONodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; + assertThat(testIsIsNonPseudonode.getISONodeID(), is(expISONodeID)); + assertThat(testIsIsNonPseudonode.getType(), is((short) 515)); + + } + + /** + * This test case checks update message with prefix NLRI. + */ + @Test + public void bgpUpdateMessageTest19() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, (byte) 0xd6, 0x02, 0x00, 0x04, + 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, (byte) 0xbb, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x90, 0x0e, 0x00, (byte) 0xa5, 0x40, 0x04, 0x47, //mpreach + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x19, 0x21, 0x68, + 0x07, 0x70, 0x01, 0x01, 0x09, 0x00, 0x05, 0x20, + (byte) 0xc0, (byte) 0xa8, 0x4d, 0x01, 0x00, 0x03, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, + 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, + 0x06, 0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21, 0x01, + 0x09, 0x00, 0x05, 0x20, 0x15, 0x15, 0x15, 0x15, + 0x00, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x02, 0x20, 0x22, + 0x02, 0x20, 0x22, 0x01, 0x09, 0x00, 0x05, 0x20, + 0x16, 0x16, 0x16, 0x16}; // prefix nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 214)); + + ListIterator listIterator1 = other.withdrawnRoutes().listIterator(); + byte[] prefix = new byte[] {0x0a, 0x01, 0x01, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 24)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + + BgpValueType testPathAttribute; + Origin origin; + AsPath asPath; + Med med; + MpReachNlri mpReach; + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); + asPath = (AsPath) testPathAttribute; + ListIterator listIterator2 = asPath.asPathSeq().listIterator(); + assertThat(listIterator2.next(), is((short) 65001)); + + testPathAttribute = listIterator.next(); + med = (Med) testPathAttribute; + assertThat(med.med(), is(0)); + + testPathAttribute = listIterator.next(); + mpReach = (MpReachNlri) testPathAttribute; + assertThat(mpReach.mpReachNlriLen(), is((int) 165)); + assertThat(mpReach.getType(), is((short) 14)); + + List testMpReachNlri = new LinkedList<>(); + testMpReachNlri = mpReach.mpReachNlri(); + + ListIterator list1 = testMpReachNlri.listIterator(); + BgpLSNlri testnlri = list1.next(); + NlriType nlriType = org.onosproject.bgpio.protocol.NlriType.PREFIX_IPV4; + ProtocolType protocolId = org.onosproject.bgpio.protocol.linkstate. + BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO; + assertThat(testnlri.getIdentifier(), is((long) 0)); + assertThat(testnlri.getNlriType(), is(nlriType)); + assertThat(testnlri.getProtocolId(), is(protocolId)); + + BgpPrefixLSNlri testprefixnlri = (BgpPrefixLSNlri) testnlri; + + NodeDescriptors testLocalNodeDescriptors = testprefixnlri.getLocalNodeDescriptors(); + + List testSubTlvs = new LinkedList<>(); + testSubTlvs = testLocalNodeDescriptors.getSubTlvs(); + ListIterator subtlvlist1 = testSubTlvs.listIterator(); + + AutonomousSystemTlv testAutonomousSystemTlv = (AutonomousSystemTlv) subtlvlist1.next(); + assertThat(testAutonomousSystemTlv.getAsNum(), is(2222)); + assertThat(testAutonomousSystemTlv.getType(), is((short) 512)); + + BgpLSIdentifierTlv testBGPLSIdentifierTlv = (BgpLSIdentifierTlv) subtlvlist1.next(); + assertThat(testBGPLSIdentifierTlv.getBgpLsIdentifier(), is(33686018)); + assertThat(testBGPLSIdentifierTlv.getType(), is((short) 513)); + + IsIsNonPseudonode testIsIsNonPseudonode = (IsIsNonPseudonode) subtlvlist1.next(); + byte[] expISONodeID = new byte[] {0x19, 0x21, 0x68, 0x07, 0x70, 0x01}; + assertThat(testIsIsNonPseudonode.getISONodeID(), is(expISONodeID)); + assertThat(testIsIsNonPseudonode.getType(), is((short) 515)); + + List testPrefixDescriptors = new LinkedList<>(); + testPrefixDescriptors = testprefixnlri.getPrefixdescriptor(); + ListIterator subtlvlist2 = testPrefixDescriptors.listIterator(); + IPReachabilityInformationTlv testIPReachabilityInformationTlv = (IPReachabilityInformationTlv) + subtlvlist2.next(); + byte[] address = new byte[] {(byte) 0xc0, (byte) 0xa8, 0x4d, 0x01}; + IpPrefix prefix1 = IpPrefix.valueOf(IpAddress.Version.INET, address, 32); + assertThat(testIPReachabilityInformationTlv.getPrefixValue(), is(prefix1)); + assertThat(testIPReachabilityInformationTlv.getPrefixLen(), is((byte) 32)); + } + + /** + * This test case checks update message with link NLRI. + */ + @Test + public void bgpUpdateMessageTest20() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, (byte) 0x83, 0x02, 0x00, 0x04, + 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, 0x68, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x53, 0x40, 0x04, 0x47, //mpreach + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x02, 0x00, 0x46, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x07, 0x19, 0x00, + (byte) 0x95, 0x02, 0x50, 0x21, 0x03, 0x01, 0x01, 0x00, 0x1a, 0x02, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, + 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x06, 0x19, + 0x00, (byte) 0x95, 0x02, 0x50, 0x21//link nlri + }; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 131)); + + ListIterator listIterator1 = other.withdrawnRoutes().listIterator(); + byte[] prefix = new byte[] {0x0a, 0x01, 0x01, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 24)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + + BgpValueType testPathAttribute; + Origin origin; + AsPath asPath; + Med med; + MpReachNlri mpReach; + + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); + asPath = (AsPath) testPathAttribute; + ListIterator listIterator2 = asPath.asPathSeq().listIterator(); + assertThat(listIterator2.next(), is((short) 65001)); + + testPathAttribute = listIterator.next(); + med = (Med) testPathAttribute; + assertThat(med.med(), is(0)); + + testPathAttribute = listIterator.next(); + mpReach = (MpReachNlri) testPathAttribute; + assertThat(mpReach.mpReachNlriLen(), is((int) 83)); + assertThat(mpReach.getType(), is((short) 14)); + + List testMpReachNlri = new LinkedList<>(); + testMpReachNlri = mpReach.mpReachNlri(); + + ListIterator list1 = testMpReachNlri.listIterator(); + BgpLSNlri testnlri = list1.next(); + NlriType nlriType = org.onosproject.bgpio.protocol.NlriType.LINK; + ProtocolType protocolId = org.onosproject.bgpio.protocol.linkstate. + BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO; + assertThat(testnlri.getIdentifier(), is((long) 0)); + assertThat(testnlri.getNlriType(), is(nlriType)); + assertThat(testnlri.getProtocolId(), is(protocolId)); + + BgpLinkLsNlriVer4 testlinknlri = (BgpLinkLsNlriVer4) testnlri; + + NodeDescriptors testLocalNodeDescriptors = testlinknlri.localNodeDescriptors(); + + List testSubTlvs = new LinkedList<>(); + testSubTlvs = testLocalNodeDescriptors.getSubTlvs(); + ListIterator subtlvlist1 = testSubTlvs.listIterator(); + + AutonomousSystemTlv testAutonomousSystemTlv = (AutonomousSystemTlv) subtlvlist1.next(); + + assertThat(testAutonomousSystemTlv.getAsNum(), is(2222)); + assertThat(testAutonomousSystemTlv.getType(), is((short) 512)); + + BgpLSIdentifierTlv testBGPLSIdentifierTlv = (BgpLSIdentifierTlv) subtlvlist1.next(); + assertThat(testBGPLSIdentifierTlv.getBgpLsIdentifier(), is(33686018)); + assertThat(testBGPLSIdentifierTlv.getType(), is((short) 513)); + + IsIsPseudonode testIsIsPseudonode = (IsIsPseudonode) subtlvlist1.next(); + assertThat(testIsIsPseudonode.getPSNIdentifier(), is((byte) 3)); + assertThat(testIsIsPseudonode.getType(), is((short) 515)); + + NodeDescriptors testRemoteNodeDescriptors = testlinknlri.remoteNodeDescriptors(); + testSubTlvs = testRemoteNodeDescriptors.getSubTlvs(); + ListIterator subtlvlist2 = testSubTlvs.listIterator(); + + testAutonomousSystemTlv = (AutonomousSystemTlv) subtlvlist2.next(); + + assertThat(testAutonomousSystemTlv.getAsNum(), is(2222)); + assertThat(testAutonomousSystemTlv.getType(), is((short) 512)); + + testBGPLSIdentifierTlv = (BgpLSIdentifierTlv) subtlvlist2.next(); + assertThat(testBGPLSIdentifierTlv.getBgpLsIdentifier(), is(33686018)); + assertThat(testBGPLSIdentifierTlv.getType(), is((short) 513)); + + IsIsNonPseudonode testIsIsNonPseudonode = (IsIsNonPseudonode) subtlvlist2.next(); + byte[] expISONodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21}; + assertThat(testIsIsNonPseudonode.getISONodeID(), is(expISONodeID)); + assertThat(testIsIsNonPseudonode.getType(), is((short) 515)); + } + + /** + * In this test case, Invalid withdrawn route length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest21() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x1b, 0x02, 0x00, 0x07, 0x18, 0x0a, 0x01, 0x01, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid withdrawn route length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest22() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x25, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x0e, //path attribute len + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}; //med + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Mandatory attributes are not given in input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest23() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x29, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x12, //path attribute len + 0x0e, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}; //med + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid origin length is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest24() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x29, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x12, //path attribute len + 0x04, 0x01, 0x02, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}; //med + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid origin value is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest25() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x29, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x12, //path attribute len + 0x04, 0x01, 0x01, 0x04, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}; //med + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid descriptor type in node nlri is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest26() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, Invalid node nlri length field in is given as input and expecting + * an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest27() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x60, 0x02, 0x00, 0x00, //withdrawn len + 0x00, 0x49, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x34, 0x40, 0x04, 0x47, //mpreach with safi = 71 + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, withdrawn routes with prefix length 0 is given as input and expecting + * an exception. + */ + @Test + public void bgpUpdateMessageTest28() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, //marker + 0x00, 0x18, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * In this test case, update message without total Path Attribute Length field is given as + * input and expecting an exception. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest29() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, //marker + 0x00, 0x16, 0x02, 0x00, 0x01, 0x00}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with as4 path attribute. + */ + @Test + public void bgpUpdateMessageTest30() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + 0x00, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x21, 0x40, 0x01, 0x01, 0x00, (byte) 0xc0, + 0x11, 0x0a, 0x02, 0x02, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x28, 0x00, 0x01, 0x40, + 0x02, 0x06, 0x02, 0x02, 0x5b, (byte) 0xa0, 0x5b, (byte) 0xa0, 0x40, 0x03, 0x04, + (byte) 0xac, 0x10, 0x03, 0x01, 0x08, 0x28}; + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message = null; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 58)); + + BgpValueType testPathAttribute; + Origin origin; + As4Path as4Path; + AsPath asPath; + NextHop nextHop; + + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); + as4Path = (As4Path) testPathAttribute; + ListIterator listIterator2 = as4Path.as4PathSEQ().listIterator(); + assertThat(listIterator2.next(), is(655361)); + + testPathAttribute = listIterator.next(); + asPath = (AsPath) testPathAttribute; + ListIterator listIterator3 = asPath.asPathSeq().listIterator(); + assertThat(listIterator3.next(), is((short) 23456)); + + testPathAttribute = listIterator.next(); + nextHop = (NextHop) testPathAttribute; + byte[] nextHopAddr = new byte[] {(byte) 0xac, 0x10, 0x03, 0x01}; + assertThat(nextHop.nextHop().toOctets(), is(nextHopAddr)); + + ListIterator listIterator1 = other.nlri().listIterator(); + byte[] prefix = new byte[] {0x28, 0x00, 0x00, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 8)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + } + + /** + * This test case checks update message with MPUnreach. + */ + @Test + public void bgpUpdateMessageTest31() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, 0x5e, 0x02, 0x00, 0x04, 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, 0x43, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0f, 0x2e, 0x40, 0x04, 0x47, //mpunreach with safi = 71 + 0x00, 0x01, 0x00, + 0x27, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x06, 0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; //node nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + assertThat(message, instanceOf(BgpUpdateMsg.class)); + BgpUpdateMsg other = (BgpUpdateMsg) message; + + assertThat(other.getHeader().getMarker(), is(MARKER)); + assertThat(other.getHeader().getType(), is(UPDATE_MSG_TYPE)); + assertThat(other.getHeader().getLength(), is((short) 94)); + + ListIterator listIterator1 = other.withdrawnRoutes().listIterator(); + byte[] prefix = new byte[] {0x0a, 0x01, 0x01, 0x00}; + + IpPrefix testPrefixValue = listIterator1.next(); + assertThat(testPrefixValue.prefixLength(), is((int) 24)); + assertThat(testPrefixValue.address().toOctets(), is(prefix)); + + BgpValueType testPathAttribute; + Origin origin; + AsPath asPath; + Med med; + MpUnReachNlri mpUnReach; + List pathAttributes = new LinkedList<>(); + BgpPathAttributes actualpathAttribute = other.bgpPathAttributes(); + pathAttributes = actualpathAttribute.pathAttributes(); + ListIterator listIterator = pathAttributes.listIterator(); + ORIGINTYPE originValue = org.onosproject.bgpio.types.Origin.ORIGINTYPE.IGP; + + testPathAttribute = listIterator.next(); + origin = (Origin) testPathAttribute; + assertThat(origin.origin(), is(originValue)); + + testPathAttribute = listIterator.next(); + asPath = (AsPath) testPathAttribute; + ListIterator listIterator2 = asPath.asPathSeq().listIterator(); + assertThat(listIterator2.next(), is((short) 65001)); + + testPathAttribute = listIterator.next(); + med = (Med) testPathAttribute; + assertThat(med.med(), is(0)); + + testPathAttribute = listIterator.next(); + mpUnReach = (MpUnReachNlri) testPathAttribute; + assertThat(mpUnReach.mpUnReachNlriLen(), is((int) 46)); + assertThat(mpUnReach.getType(), is((short) 15)); + + List testMpUnReachNlri = new LinkedList<>(); + testMpUnReachNlri = mpUnReach.mpUnReachNlri(); + + ListIterator list1 = testMpUnReachNlri.listIterator(); + BgpLSNlri testnlri = list1.next(); + NlriType nlriType = org.onosproject.bgpio.protocol.NlriType.NODE; + ProtocolType protocolId = org.onosproject.bgpio.protocol.linkstate. + BgpNodeLSNlriVer4.ProtocolType.ISIS_LEVEL_TWO; + assertThat(testnlri.getIdentifier(), is((long) 0)); + assertThat(testnlri.getNlriType(), is(nlriType)); + assertThat(testnlri.getProtocolId(), is(protocolId)); + + BgpNodeLSNlriVer4 testNodenlri = (BgpNodeLSNlriVer4) testnlri; + + BgpNodeLSIdentifier testLocalNodeDescriptors = testNodenlri.getLocalNodeDescriptors(); + + List testSubTlvs = new LinkedList<>(); + NodeDescriptors localNodeDescriptors = testLocalNodeDescriptors.getNodedescriptors(); + testSubTlvs = localNodeDescriptors.getSubTlvs(); + ListIterator subtlvlist1 = testSubTlvs.listIterator(); + + AutonomousSystemTlv testAutonomousSystemTlv = (AutonomousSystemTlv) subtlvlist1.next(); + + assertThat(testAutonomousSystemTlv.getAsNum(), is(2222)); + assertThat(testAutonomousSystemTlv.getType(), is((short) 512)); + + BgpLSIdentifierTlv testBGPLSIdentifierTlv = (BgpLSIdentifierTlv) subtlvlist1.next(); + assertThat(testBGPLSIdentifierTlv.getBgpLsIdentifier(), is(33686018)); + assertThat(testBGPLSIdentifierTlv.getType(), is((short) 513)); + + IsIsNonPseudonode testIsIsNonPseudonode = (IsIsNonPseudonode) subtlvlist1.next(); + byte[] expISONodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; + assertThat(testIsIsNonPseudonode.getISONodeID(), is(expISONodeID)); + assertThat(testIsIsNonPseudonode.getType(), is((short) 515)); + } + + /** + * This test case checks update message with invalid mpreach packet. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest32() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, (byte) 0xd6, 0x02, 0x00, 0x04, + 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, (byte) 0xbb, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x90, 0x0e, 0x00, (byte) 0xa5, 0x40, 0x04, 0x47, //mpreach + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x19, 0x21, 0x68, + 0x07, 0x70, 0x01, 0x01, 0x09, 0x00, 0x05, 0x20, + (byte) 0xc0, (byte) 0xa8, 0x4d, 0x01, 0x00, 0x03, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, + 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, + 0x06, 0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21, 0x01, + 0x09, 0x00, 0x05, 0x20, 0x15, 0x15, 0x15, 0x15, + 0x00, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x02, 0x20, 0x22, + 0x02, 0x20, 0x22, 0x01, 0x09, 0x00, 0x05, 0x20, + 0x16, 0x16, 0x16, 0x16}; // prefix nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with invalid prefix nlri length in input. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest33() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, (byte) 0xd6, 0x02, 0x00, 0x04, + 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, (byte) 0xbb, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x90, 0x0e, 0x00, (byte) 0xa5, 0x40, 0x04, 0x47, //mpreach + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x03, 0x00, 0x35, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x19, 0x21, 0x68, + 0x07, 0x70, 0x01, 0x01, 0x09, 0x00, 0x05, 0x20, + (byte) 0xc0, (byte) 0xa8, 0x4d, 0x01, 0x00, 0x03, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1a, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, + 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, + 0x06, 0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21, 0x01, + 0x09, 0x00, 0x05, 0x20, 0x15, 0x15, 0x15, 0x15, + 0x00, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1a, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, + (byte) 0xae, 0x02, 0x01, 0x00, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x00, 0x06, 0x02, 0x20, 0x22, + 0x02, 0x20, 0x22, 0x01, 0x09, 0x00, 0x05, 0x20, + 0x16, 0x16, 0x16, 0x16}; // prefix nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } + + /** + * This test case checks update message with invalid link nlri length in input. + */ + @Test(expected = BgpParseException.class) + public void bgpUpdateMessageTest34() throws BgpParseException { + byte[] updateMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00, (byte) 0x83, 0x02, 0x00, 0x04, + 0x18, 0x0a, 0x01, 0x01, //withdrawn routes + 0x00, 0x68, //path attribute len + 0x04, 0x01, 0x01, 0x00, //origin + 0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, (byte) 0xe9, //as_path + (byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, //med + (byte) 0x80, 0x0e, 0x53, 0x40, 0x04, 0x47, //mpreach + 0x04, 0x04, 0x00, 0x00, 0x01, //nexthop + 0x00, //reserved + 0x00, 0x02, 0x00, 0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, 0x04, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x07, 0x19, 0x00, + (byte) 0x95, 0x02, 0x50, 0x21, 0x03, 0x01, 0x01, 0x00, 0x1a, 0x02, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, (byte) 0xae, 0x02, 0x01, 0x00, + 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x06, 0x19, + 0x00, (byte) 0x95, 0x02, 0x50, 0x21}; //link nlri + + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(updateMsg); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + BgpMessage message; + BgpHeader bgpHeader = new BgpHeader(); + + message = reader.readFrom(buffer, bgpHeader); + + assertThat(message, instanceOf(BgpUpdateMsg.class)); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java new file mode 100644 index 00000000..e11564ab --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AreaIdTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for AreaID Tlv. + */ +public class AreaIdTest { + private final int value1 = 10; + private final int value2 = 20; + private final AreaIDTlv tlv1 = AreaIDTlv.of(value1); + private final AreaIDTlv sameAsTlv1 = AreaIDTlv.of(value1); + private final AreaIDTlv tlv2 = AreaIDTlv.of(value2); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java new file mode 100755 index 00000000..3ea56b64 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/As4PathTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for As4Path BGP Path Attribute. + */ +public class As4PathTest { + //Two scenarios as4path set and sequence + private final List as4pathSet1 = new ArrayList<>(); + private final List as4pathSeq1 = new ArrayList<>(); + private final List as4pathSet2 = new ArrayList<>(); + private final List as4pathSeq2 = new ArrayList<>(); + private final As4Path attr1 = new As4Path(as4pathSet1, null); + private final As4Path sameAsAttr1 = new As4Path(as4pathSet1, null); + private final As4Path attr2 = new As4Path(as4pathSet2, null); + private final As4Path attr3 = new As4Path(null, as4pathSeq1); + private final As4Path sameAsAttr3 = new As4Path(null, as4pathSeq1); + private final As4Path attr4 = new As4Path(null, as4pathSeq2); + + @Test + public void basics() { + as4pathSet1.add(197358); + as4pathSet1.add(12883); + as4pathSet2.add(2008989); + as4pathSeq1.add(3009009); + as4pathSeq2.add(409900); + new EqualsTester() + .addEqualityGroup(attr1, sameAsAttr1) + .addEqualityGroup(attr2) + .addEqualityGroup(attr3, sameAsAttr3) + .addEqualityGroup(attr4) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java new file mode 100644 index 00000000..e56ec5a5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AsPathTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for AsPath BGP Path Attribute. + */ +public class AsPathTest { + //Two scenarios aspath set and sequence + private final List aspathSet1 = new ArrayList<>(); + private final List aspathSet2 = new ArrayList<>(); + private final List aspathSeq1 = new ArrayList<>(); + private final List aspathSeq2 = new ArrayList<>(); + private final AsPath attr1 = new AsPath(aspathSet1, null); + private final AsPath sameAsAttr1 = new AsPath(aspathSet1, null); + private final AsPath attr2 = new AsPath(aspathSet2, null); + private final AsPath attr3 = new AsPath(null, aspathSeq1); + private final AsPath sameAsAttr3 = new AsPath(null, aspathSeq1); + private final AsPath attr4 = new AsPath(null, aspathSeq2); + + @Test + public void basics() { + aspathSet1.add((short) 100); + aspathSet1.add((short) 300); + aspathSet2.add((short) 200); + aspathSeq2.add((short) 400); + aspathSeq1.add((short) 300); + new EqualsTester() + .addEqualityGroup(attr1, sameAsAttr1) + .addEqualityGroup(attr2) + .addEqualityGroup(attr3, sameAsAttr3) + .addEqualityGroup(attr4) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java new file mode 100644 index 00000000..1695583b --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/AutonomousSystemTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for AutonomousSystem Tlv. + */ +public class AutonomousSystemTest { + private final int value1 = 101; + private final int value2 = 201; + private final AutonomousSystemTlv tlv1 = AutonomousSystemTlv.of(value1); + private final AutonomousSystemTlv sameAsTlv1 = AutonomousSystemTlv.of(value1); + private final AutonomousSystemTlv tlv2 = AutonomousSystemTlv.of(value2); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java new file mode 100644 index 00000000..59cf96fa --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/BgpLSIdentifierTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGPLSIdentifier Tlv. + */ +public class BgpLSIdentifierTest { + private final int value1 = 8738; + private final int value2 = 13107; + private final BgpLSIdentifierTlv tlv1 = BgpLSIdentifierTlv.of(value1); + private final BgpLSIdentifierTlv sameAsTlv1 = new BgpLSIdentifierTlv(value1); + private final BgpLSIdentifierTlv tlv2 = new BgpLSIdentifierTlv(value2); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java new file mode 100644 index 00000000..7bea518a --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPReachabilityInformationTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for IPReachabilityInformation Tlv. + */ +public class IPReachabilityInformationTest { + private final byte[] value1 = new byte[] {(byte) 0xc0, (byte) 0xa8, 0x4d, 0x01}; + private final byte[] value2 = new byte[] {(byte) 0xc0}; + private final IPReachabilityInformationTlv tlv1 = IPReachabilityInformationTlv.of((byte) 0x17, value1, (short) 4); + private final IPReachabilityInformationTlv sameAsTlv1 = IPReachabilityInformationTlv + .of((byte) 0x17, value1, (short) 4); + private final IPReachabilityInformationTlv tlv2 = IPReachabilityInformationTlv.of((byte) 0x05, value2, (short) 1); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java new file mode 100755 index 00000000..fdb71189 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv4AddressTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; +import org.onlab.packet.Ip4Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for IPv4Address Tlv. + */ +public class IPv4AddressTest { + private final Ip4Address value1 = Ip4Address.valueOf("127.0.0.1"); + private final Ip4Address value2 = Ip4Address.valueOf("127.0.0.1"); + private final IPv4AddressTlv tlv1 = IPv4AddressTlv.of(value1, (short) 259); + private final IPv4AddressTlv sameAsTlv1 = IPv4AddressTlv.of(value1, (short) 259); + private final IPv4AddressTlv tlv2 = IPv4AddressTlv.of(value2, (short) 260); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java new file mode 100644 index 00000000..781935b4 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IPv6AddressTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; +import org.onlab.packet.Ip6Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for IPv6Address Tlv. + */ +public class IPv6AddressTest { + private final Ip6Address value1 = Ip6Address.valueOf("2001:db8:0:0:0:0:2:1"); + private final Ip6Address value2 = Ip6Address.valueOf("2001:db8:0:0:0:0:2:1"); + private final IPv6AddressTlv tlv1 = IPv6AddressTlv.of(value1, (short) 261); + private final IPv6AddressTlv sameAsTlv1 = IPv6AddressTlv.of(value1, (short) 261); + private final IPv6AddressTlv tlv2 = IPv6AddressTlv.of(value2, (short) 262); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java new file mode 100644 index 00000000..7ce4d5d3 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsNonPseudonodeTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for IsIsNonPseudonode Tlv. + */ +public class IsIsNonPseudonodeTest { + private final byte[] value1 = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58}; + private final byte[] value2 = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x59}; + private final IsIsNonPseudonode tlv1 = IsIsNonPseudonode.of(value1); + private final IsIsNonPseudonode sameAsTlv1 = IsIsNonPseudonode.of(value1); + private final IsIsNonPseudonode tlv2 = IsIsNonPseudonode.of(value2); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java new file mode 100644 index 00000000..a2a7c2b5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/IsIsPseudonodeTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for IsIsPseudonode Tlv. + */ +public class IsIsPseudonodeTest { + private final byte[] value1 = new byte[] {0x01, 0x02, 0x01, 0x02, 0x01, 0x02}; + private final byte[] value2 = new byte[] {0x01, 0x02, 0x01, 0x02, 0x01, 0x03}; + private final IsIsPseudonode tlv1 = IsIsPseudonode.of(value1, (byte) 1); + private final IsIsPseudonode sameAsTlv1 = IsIsPseudonode.of(value1, (byte) 1); + private final IsIsPseudonode tlv2 = IsIsPseudonode.of(value2, (byte) 1); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java new file mode 100644 index 00000000..f1510b17 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LinkLocalRemoteIdentifiersTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for LinkLocalRemoteIdentifiers Tlv. + */ +public class LinkLocalRemoteIdentifiersTest { + private final int value1 = 0x12101010; + private final int value2 = 0x12101012; + private final LinkLocalRemoteIdentifiersTlv tlv1 = LinkLocalRemoteIdentifiersTlv.of(value1, value2); + private final LinkLocalRemoteIdentifiersTlv sameAsTlv1 = LinkLocalRemoteIdentifiersTlv.of(value1, value2); + private final LinkLocalRemoteIdentifiersTlv tlv2 = LinkLocalRemoteIdentifiersTlv.of(value2, value1); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java new file mode 100644 index 00000000..1bd34385 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/LocalPrefTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for LocalPref BGP Path Attribute. + */ +public class LocalPrefTest { + private final int value1 = 800; + private final int value2 = 300; + private final LocalPref attr1 = new LocalPref(value1); + private final LocalPref sameAsAttr1 = new LocalPref(value1); + private final LocalPref attr2 = new LocalPref(value2); + + @Test + public void testEquality() { + new EqualsTester().addEqualityGroup(attr1, sameAsAttr1).addEqualityGroup(attr2).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java new file mode 100644 index 00000000..2ee5b33f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MedTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for MED BGP Path Attribute. + */ +public class MedTest { + private final int value1 = 800; + private final int value2 = 200; + private final Med attr1 = new Med(value1); + private final Med sameAsAttr1 = new Med(value1); + private final Med attr2 = new Med(value2); + + @Test + public void testEquality() { + new EqualsTester().addEqualityGroup(attr1, sameAsAttr1).addEqualityGroup(attr2).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java new file mode 100755 index 00000000..799419a1 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/NextHopTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; +import org.onlab.packet.Ip4Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for NextHop BGP Path Attribute. + */ +public class NextHopTest { + private final Ip4Address value1 = Ip4Address.valueOf("12.12.12.12"); + private final Ip4Address value2 = Ip4Address.valueOf("12.12.12.13"); + private final NextHop attr1 = new NextHop(value1); + private final NextHop sameAsAttr1 = new NextHop(value1); + private final NextHop attr2 = new NextHop(value2); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(attr1, sameAsAttr1) + .addEqualityGroup(attr2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java new file mode 100644 index 00000000..da7b5570 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OriginTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for Origin BGP Path Attribute. + */ +public class OriginTest { + private final byte value1 = 0x01; + private final byte value2 = 0x02; + private final Origin attr1 = new Origin(value1); + private final Origin sameAsAttr1 = new Origin(value1); + private final Origin attr2 = new Origin(value2); + + @Test + public void basics() { + new EqualsTester() + .addEqualityGroup(attr1, sameAsAttr1) + .addEqualityGroup(attr2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java new file mode 100644 index 00000000..a8002311 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfPseudonodeTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; +import org.onlab.packet.Ip4Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for OSPFPseudonode Tlv. + */ +public class OspfPseudonodeTest { + private final int value1 = 0xc3223409; + private final int value2 = 0xc3223406; + private final Ip4Address drInterface1 = Ip4Address.valueOf(0xaf91e01); + private final Ip4Address drInterface2 = Ip4Address.valueOf(0xaf91e02); + private final OSPFPseudonode tlv1 = OSPFPseudonode.of(value1, drInterface1); + private final OSPFPseudonode sameAsTlv1 = OSPFPseudonode.of(value1, drInterface1); + private final OSPFPseudonode tlv2 = OSPFPseudonode.of(value2, drInterface2); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java new file mode 100644 index 00000000..859bdbe5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/OspfRouteTypeTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for OSPFRouteType Tlv. + */ +public class OspfRouteTypeTest { + private final byte value1 = 5; + private final byte value2 = 4; + private final OSPFRouteTypeTlv tlv1 = OSPFRouteTypeTlv.of(value1); + private final OSPFRouteTypeTlv sameAsTlv1 = OSPFRouteTypeTlv.of(value1); + private final OSPFRouteTypeTlv tlv2 = OSPFRouteTypeTlv.of(value2); + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup(tlv1, sameAsTlv1) + .addEqualityGroup(tlv2) + .testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java new file mode 100644 index 00000000..4efb7f5b --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlvTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP attribute node flag. + */ +public class BgpAttrNodeFlagBitTlvTest { + + private final boolean bOverloadBit = true; + private final boolean bAttachedBit = true; + private final boolean bExternalBit = true; + private final boolean bABRBit = true; + + private final boolean bOverloadBit1 = false; + private final boolean bAttachedBit1 = false; + private final boolean bExternalBit1 = false; + private final boolean bABRBit1 = false; + + private final BgpAttrNodeFlagBitTlv data = BgpAttrNodeFlagBitTlv + .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit); + private final BgpAttrNodeFlagBitTlv sameAsData = BgpAttrNodeFlagBitTlv + .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit); + private final BgpAttrNodeFlagBitTlv diffData = BgpAttrNodeFlagBitTlv + .of(bOverloadBit1, bAttachedBit1, bExternalBit1, bABRBit1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java new file mode 100644 index 00000000..16ca58ee --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6Test.java @@ -0,0 +1,49 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; +import org.onlab.packet.Ip6Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP attribute node router ID. + */ +public class BgpAttrRouterIdV6Test { + + private final short sType = 1; + private final Ip6Address ip6RouterId = Ip6Address + .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001"); + + private final short sType1 = 2; + private final Ip6Address ip6RouterId1 = Ip6Address + .valueOf("2004:0db8:0a0b:12f0:0000:0000:0000:0004"); + + private final BgpAttrRouterIdV6 data = BgpAttrRouterIdV6.of(ip6RouterId, + sType); + private final BgpAttrRouterIdV6 sameAsData = BgpAttrRouterIdV6 + .of(ip6RouterId, sType); + private final BgpAttrRouterIdV6 diffData = BgpAttrRouterIdV6 + .of(ip6RouterId1, sType1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java new file mode 100644 index 00000000..ef1cfcea --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetricTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP link IGP metric attribute. + */ +public class BgpLinkAttrIgpMetricTest { + private final int val = 0x010203; + private final int valLen = 3; + private final int val1 = 0x01020304; + private final int val1Len = 4; + + private final BgpLinkAttrIgpMetric data = BgpLinkAttrIgpMetric.of(val, + valLen); + private final BgpLinkAttrIgpMetric sameAsData = BgpLinkAttrIgpMetric + .of(val, valLen); + private final BgpLinkAttrIgpMetric diffData = BgpLinkAttrIgpMetric + .of(val1, val1Len); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java new file mode 100644 index 00000000..06fecc92 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMaxLinkBandwidthTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP link max bandwidth attribute. + */ +public class BgpLinkAttrMaxLinkBandwidthTest { + private final float val = 0x010203; + private final short valLen = 3; + private final float val1 = 0x01020304; + private final short val1Len = 4; + + private final BgpLinkAttrMaxLinkBandwidth data = BgpLinkAttrMaxLinkBandwidth + .of(val, valLen); + private final BgpLinkAttrMaxLinkBandwidth sameAsData = BgpLinkAttrMaxLinkBandwidth + .of(val, valLen); + private final BgpLinkAttrMaxLinkBandwidth diffData = BgpLinkAttrMaxLinkBandwidth + .of(val1, val1Len); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java new file mode 100644 index 00000000..c0d7f986 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMaskTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for MPLS protocol mask attribute. + */ +public class BgpLinkAttrMplsProtocolMaskTest { + private final boolean val = true; + private final boolean val1 = false; + + private final BgpLinkAttrMplsProtocolMask data = BgpLinkAttrMplsProtocolMask + .of(val, val); + private final BgpLinkAttrMplsProtocolMask sameAsData = BgpLinkAttrMplsProtocolMask + .of(val, val); + private final BgpLinkAttrMplsProtocolMask diffData = BgpLinkAttrMplsProtocolMask + .of(val, val1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java new file mode 100644 index 00000000..45048527 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrNameTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for Link attribute name Tlv. + */ +public class BgpLinkAttrNameTest { + private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; + private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; + + private final BgpLinkAttrName isisData = BgpLinkAttrName.of(array); + private final BgpLinkAttrName sameAsIsisData = BgpLinkAttrName.of(array); + private final BgpLinkAttrName isisDiff = BgpLinkAttrName.of(array1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java new file mode 100644 index 00000000..71d05f85 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrOpaqLnkAttribTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for Opaque Link attribute Tlv. + */ +public class BgpLinkAttrOpaqLnkAttribTest { + private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; + private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; + + private final BgpLinkAttrOpaqLnkAttrib isisData = BgpLinkAttrOpaqLnkAttrib + .of(array); + private final BgpLinkAttrOpaqLnkAttrib sameAsIsisData = BgpLinkAttrOpaqLnkAttrib + .of(array); + private final BgpLinkAttrOpaqLnkAttrib isisDiff = BgpLinkAttrOpaqLnkAttrib + .of(array1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java new file mode 100644 index 00000000..2fb76352 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionTypeTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for MPLS protocol mask attribute. + */ +public class BgpLinkAttrProtectionTypeTest { + boolean bExtraTraffic = true; + boolean bUnprotected = true; + boolean bShared = true; + boolean bDedOneIstoOne = true; + boolean bDedOnePlusOne = true; + boolean bEnhanced = true; + + boolean bExtraTraffic1 = false; + boolean bUnprotected1 = false; + boolean bShared1 = false; + boolean bDedOneIstoOne1 = false; + boolean bDedOnePlusOne1 = false; + boolean bEnhanced1 = false; + + private final BgpLinkAttrProtectionType data = BgpLinkAttrProtectionType + .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne, + bDedOnePlusOne, bEnhanced); + private final BgpLinkAttrProtectionType sameAsData = BgpLinkAttrProtectionType + .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne, + bDedOnePlusOne, bEnhanced); + private final BgpLinkAttrProtectionType diffData = BgpLinkAttrProtectionType + .of(bExtraTraffic1, bUnprotected1, bShared1, bDedOneIstoOne1, + bDedOnePlusOne1, bEnhanced1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java new file mode 100644 index 00000000..9f3a7fad --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrTeDefaultMetricTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP link TE default metric attribute. + */ +public class BgpLinkAttrTeDefaultMetricTest { + private final int val = 0x010203; + private final int val1 = 0x01020304; + + private final BgpLinkAttrTeDefaultMetric data = BgpLinkAttrTeDefaultMetric + .of(val); + private final BgpLinkAttrTeDefaultMetric sameAsData = BgpLinkAttrTeDefaultMetric + .of(val); + private final BgpLinkAttrTeDefaultMetric diffData = BgpLinkAttrTeDefaultMetric + .of(val1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java new file mode 100644 index 00000000..f1d2a1fa --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpLinkAttrUnRsrvdLinkBandwidthTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP unreserved bandwidth attribute. + */ +public class BgpLinkAttrUnRsrvdLinkBandwidthTest { + ArrayList maxUnResBandwidth = new ArrayList(); + ArrayList maxUnResBandwidth1 = new ArrayList(); + short sType = 10; + + private final BgpLinkAttrUnRsrvdLinkBandwidth isisData = BgpLinkAttrUnRsrvdLinkBandwidth + .of(maxUnResBandwidth, sType); + private final BgpLinkAttrUnRsrvdLinkBandwidth sameAsIsisData = BgpLinkAttrUnRsrvdLinkBandwidth + .of(maxUnResBandwidth, sType); + private final BgpLinkAttrUnRsrvdLinkBandwidth isisDiff = BgpLinkAttrUnRsrvdLinkBandwidth + .of(maxUnResBandwidth1, sType); + + @Test + public void basics() { + + maxUnResBandwidth.add(new Float(1)); + maxUnResBandwidth.add(new Float(2)); + maxUnResBandwidth.add(new Float(3)); + maxUnResBandwidth.add(new Float(4)); + + maxUnResBandwidth1.add(new Float(1)); + maxUnResBandwidth1.add(new Float(2)); + maxUnResBandwidth1.add(new Float(3)); + maxUnResBandwidth1.add(new Float(1)); + + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java new file mode 100644 index 00000000..535518f8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrIgpFlagsTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP prefix IGP Flag attribute. + */ +public class BgpPrefixAttrIgpFlagsTest { + + private final boolean bisisUpDownBit = true; + private final boolean bOspfNoUnicastBit = true; + private final boolean bOspfLclAddrBit = true; + private final boolean bOspfNSSABit = true; + + private final boolean bisisUpDownBit1 = false; + private final boolean bOspfNoUnicastBit1 = false; + private final boolean bOspfLclAddrBit1 = false; + private final boolean bOspfNSSABit1 = false; + + private final BgpPrefixAttrIgpFlags data = BgpPrefixAttrIgpFlags + .of(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, + bOspfNSSABit); + private final BgpPrefixAttrIgpFlags sameAsData = BgpPrefixAttrIgpFlags + .of(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit, + bOspfNSSABit); + private final BgpPrefixAttrIgpFlags diffData = BgpPrefixAttrIgpFlags + .of(bisisUpDownBit1, bOspfNoUnicastBit1, bOspfLclAddrBit1, + bOspfNSSABit1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java new file mode 100644 index 00000000..fe6079fd --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetricTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP prefix metric attribute. + */ +public class BgpPrefixAttrMetricTest { + private final int val = 1111; + private final int val1 = 2222; + + private final BgpPrefixAttrMetric data = BgpPrefixAttrMetric.of(val); + private final BgpPrefixAttrMetric sameAsData = BgpPrefixAttrMetric.of(val); + private final BgpPrefixAttrMetric diffData = BgpPrefixAttrMetric.of(val1); + + @Test + public void basics() { + + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java new file mode 100644 index 00000000..17dafbb7 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOpaqueDataTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for prefix attribute opaque data Tlv. + */ +public class BgpPrefixAttrOpaqueDataTest { + private final byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04}; + private final byte[] array1 = new byte[] {0x01, 0x02, 0x03, 0x01}; + + private final BgpPrefixAttrOpaqueData isisData = BgpPrefixAttrOpaqueData + .of(array); + private final BgpPrefixAttrOpaqueData sameAsIsisData = BgpPrefixAttrOpaqueData + .of(array); + private final BgpPrefixAttrOpaqueData isisDiff = BgpPrefixAttrOpaqueData + .of(array1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java new file mode 100644 index 00000000..f6fe39f8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddrTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import org.junit.Test; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP prefix metric attribute. + */ +public class BgpPrefixAttrOspfFwdAddrTest { + + private final short lsAttrLength = 4; + private final Ip4Address ip4RouterId = Ip4Address.valueOf("192.168.1.1"); + private final Ip6Address ip6RouterId = Ip6Address + .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001"); + + private final short lsAttrLength1 = 16; + private final Ip4Address ip4RouterId1 = Ip4Address.valueOf("192.168.1.2"); + private final Ip6Address ip6RouterId1 = Ip6Address + .valueOf("1002:0db8:0a0b:12f0:0000:0000:0000:0002"); + + private final BgpPrefixAttrOspfFwdAddr data = BgpPrefixAttrOspfFwdAddr + .of(lsAttrLength, ip4RouterId, ip6RouterId); + private final BgpPrefixAttrOspfFwdAddr sameAsData = BgpPrefixAttrOspfFwdAddr + .of(lsAttrLength, ip4RouterId, ip6RouterId); + private final BgpPrefixAttrOspfFwdAddr diffData = BgpPrefixAttrOspfFwdAddr + .of(lsAttrLength1, ip4RouterId1, ip6RouterId1); + + @Test + public void basics() { + new EqualsTester().addEqualityGroup(data, sameAsData) + .addEqualityGroup(diffData).testEquals(); + } +} diff --git a/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java new file mode 100644 index 00000000..25ced61f --- /dev/null +++ b/framework/src/onos/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrRouteTagTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgpio.types.attr; + +import java.util.ArrayList; + +import org.junit.Test; + +import com.google.common.testing.EqualsTester; + +/** + * Test for BGP prefix route tag attribute. + */ +public class BgpPrefixAttrRouteTagTest { + ArrayList maxUnResBandwidth = new ArrayList(); + ArrayList maxUnResBandwidth1 = new ArrayList(); + + private final BgpPrefixAttrRouteTag isisData = BgpPrefixAttrRouteTag + .of(maxUnResBandwidth); + private final BgpPrefixAttrRouteTag sameAsIsisData = BgpPrefixAttrRouteTag + .of(maxUnResBandwidth); + private final BgpPrefixAttrRouteTag isisDiff = BgpPrefixAttrRouteTag + .of(maxUnResBandwidth1); + + @Test + public void basics() { + + maxUnResBandwidth.add(new Integer(1)); + maxUnResBandwidth.add(new Integer(2)); + maxUnResBandwidth.add(new Integer(3)); + maxUnResBandwidth.add(new Integer(4)); + + maxUnResBandwidth1.add(new Integer(1)); + maxUnResBandwidth1.add(new Integer(2)); + maxUnResBandwidth1.add(new Integer(3)); + maxUnResBandwidth1.add(new Integer(1)); + + new EqualsTester().addEqualityGroup(isisData, sameAsIsisData) + .addEqualityGroup(isisDiff).testEquals(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/pom.xml b/framework/src/onos/protocols/bgp/ctl/pom.xml new file mode 100755 index 00000000..629e9ee7 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + + org.onosproject + onos-bgp + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-bgp-ctl + bundle + + ONOS BGP controller subsystem API + + + + org.onosproject + onos-bgp-api + + + io.netty + netty + + + org.apache.felix + org.apache.felix.scr.annotations + + + org.osgi + org.osgi.compendium + + + + + + + org.apache.felix + maven-scr-plugin + + + + + diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java new file mode 100644 index 00000000..9cbfbf65 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/AdjRibIn.java @@ -0,0 +1,132 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Map; +import java.util.TreeMap; + +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Adj-RIB-In for each peer. + */ +public class AdjRibIn { + private Map nodeTree = new TreeMap<>(); + private Map linkTree = new TreeMap<>(); + private Map prefixTree = new TreeMap<>(); + + /** + * Returns the adjacency node. + * + * @return node adjacency RIB node + */ + public Map nodeTree() { + return nodeTree; + } + + /** + * Returns the adjacency link. + * + * @return link adjacency RIB node + */ + public Map linkTree() { + return linkTree; + } + + /** + * Returns the adjacency prefix. + * + * @return prefix adjacency RIB node + */ + public Map prefixTree() { + return prefixTree; + } + + /** + * Update nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. + * + * @param nlri NLRI Info + * @param details has pathattribute , protocolID and identifier + */ + public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.replace(nodeLSIdentifier, details); + } else { + nodeTree.put(nodeLSIdentifier, details); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.replace(linkLSIdentifier, details); + } else { + linkTree.put(linkLSIdentifier, details); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.replace(prefixIdentifier, details); + } else { + prefixTree.put(prefixIdentifier, details); + } + } + } + + /** + * Removes nlri identifier if it exists in the adjacency tree. + * + * @param nlri NLRI Info + */ + public void remove(BgpLSNlri nlri) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.remove(nodeLSIdentifier); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.remove(linkLSIdentifier); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.remove(prefixIdentifier); + } + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("nodeTree", nodeTree) + .add("linkTree", linkTree) + .add("prefixTree", prefixTree) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java new file mode 100755 index 00000000..0c55eadc --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java @@ -0,0 +1,896 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; +import java.nio.channels.ClosedChannelException; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.concurrent.RejectedExecutionException; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.ExceptionEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; +import org.jboss.netty.handler.timeout.ReadTimeoutException; +import org.jboss.netty.handler.timeout.ReadTimeoutHandler; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpPeerCfg; +import org.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.BgpOpenMsg; +import org.onosproject.bgpio.protocol.BgpType; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.onosproject.bgpio.types.BgpErrorType; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Channel handler deals with the bgp peer connection and dispatches messages from peer to the appropriate locations. + */ +class BgpChannelHandler extends IdleStateAwareChannelHandler { + + private static final Logger log = LoggerFactory.getLogger(BgpChannelHandler.class); + static final int BGP_MIN_HOLDTIME = 3; + static final int BGP_MAX_KEEPALIVE_INTERVAL = 3; + private BgpPeer bgpPeer; + private BgpId thisbgpId; + private Channel channel; + private BgpKeepAliveTimer keepAliveTimer = null; + private short peerHoldTime = 0; + private short negotiatedHoldTime = 0; + private long peerAsNum; + private int peerIdentifier; + private BgpPacketStatsImpl bgpPacketStats; + static final int MAX_WRONG_COUNT_PACKET = 5; + static final byte MULTI_PROTOCOL_EXTN_CAPA_TYPE = 1; + static final byte FOUR_OCTET_AS_NUM_CAPA_TYPE = 65; + static final int AS_TRANS = 23456; + static final int MAX_AS2_NUM = 65535; + static final short AFI = 16388; + static final byte RES = 0; + static final byte SAFI = 71; + + // State needs to be volatile because the HandshakeTimeoutHandler + // needs to check if the handshake is complete + private volatile ChannelState state; + + // When a bgp peer with a ip addresss is found (i.e we already have a + // connected peer with the same ip), the new peer is immediately + // disconnected. At that point netty callsback channelDisconnected() which + // proceeds to cleaup peer state - we need to ensure that it does not + // cleanup + // peer state for the older (still connected) peer + private volatile Boolean duplicateBGPIdFound; + // Indicates the bgp version used by this bgp peer + protected BgpVersion bgpVersion; + private BgpController bgpController; + protected BgpFactory factory4; + private boolean isIbgpSession; + private BgpSessionInfoImpl sessionInfo; + private BgpPeerManagerImpl peerManager; + private InetSocketAddress inetAddress; + private IpAddress ipAddress; + private SocketAddress address; + private String peerAddr; + private BgpCfg bgpconfig; + + /** + * Create a new unconnected BGPChannelHandler. + * + * @param bgpController bgp controller + */ + BgpChannelHandler(BgpController bgpController) { + this.bgpController = bgpController; + this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager(); + this.state = ChannelState.IDLE; + this.factory4 = Controller.getBgpMessageFactory4(); + this.duplicateBGPIdFound = Boolean.FALSE; + this.bgpPacketStats = new BgpPacketStatsImpl(); + this.bgpconfig = bgpController.getConfig(); + } + + // To disconnect peer session. + public void disconnectPeer() { + bgpPeer.disconnectPeer(); + } + + // ************************* + // Channel State Machine + // ************************* + + /** + * The state machine for handling the peer/channel state. All state transitions should happen from within the state + * machine (and not from other parts of the code) + */ + enum ChannelState { + /** + * Initial state before channel is connected. + */ + IDLE(false) { + + }, + + OPENSENT(false) { + @Override + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { + log.debug("message received in OPENSENT state"); + // check for OPEN message + if (m.getType() != BgpType.OPEN) { + // When the message type is not keep alive message increment the wrong packet statistics + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, + BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE, + m.getType().getType()); + log.debug("Message is not OPEN message"); + } else { + log.debug("Sending keep alive message in OPENSENT state"); + h.bgpPacketStats.addInPacket(); + + BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; + h.peerIdentifier = pOpenmsg.getBgpId(); + + // validate capabilities and open msg + if (h.openMsgValidation(h, pOpenmsg)) { + if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENCONFIRM, + h.peerIdentifier, h.peerAddr)) { + h.channel.close(); + return; + } + log.debug("Sending handshake OPEN message"); + + /* + * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the + * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time + * received in the OPEN message + */ + h.peerHoldTime = pOpenmsg.getHoldTime(); + if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { + h.channel.getPipeline().replace("holdTime", + "holdTime", + new ReadTimeoutHandler(BgpPipelineFactory.TIMER, + h.peerHoldTime)); + } + + log.info("Hold Time : " + h.peerHoldTime); + + // update AS number + h.peerAsNum = pOpenmsg.getAsNumber(); + } + + // Send keepalive message to peer. + h.sendKeepAliveMessage(); + h.bgpPacketStats.addOutPacket(); + h.setState(OPENCONFIRM); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); + } + } + }, + + OPENWAIT(false) { + @Override + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { + log.debug("Message received in OPEN WAIT State"); + + // check for open message + if (m.getType() != BgpType.OPEN) { + // When the message type is not open message increment the wrong packet statistics + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, BgpErrorType.UNSPECIFIED_ERROR, + m.getType().getType()); + log.debug("Message is not OPEN message"); + } else { + h.bgpPacketStats.addInPacket(); + + BgpOpenMsg pOpenmsg = (BgpOpenMsg) m; + h.peerIdentifier = pOpenmsg.getBgpId(); + + // Validate open message + if (h.openMsgValidation(h, pOpenmsg)) { + if (h.connectionCollisionDetection(BgpPeerCfg.State.OPENSENT, + h.peerIdentifier, h.peerAddr)) { + h.channel.close(); + return; + } + log.debug("Sending handshake OPEN message"); + + /* + * RFC 4271, section 4.2: Upon receipt of an OPEN message, a BGP speaker MUST calculate the + * value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time + * received in the OPEN message + */ + h.peerHoldTime = pOpenmsg.getHoldTime(); + if (h.peerHoldTime < h.bgpconfig.getHoldTime()) { + h.channel.getPipeline().replace("holdTime", + "holdTime", + new ReadTimeoutHandler(BgpPipelineFactory.TIMER, + h.peerHoldTime)); + } + + log.debug("Hold Time : " + h.peerHoldTime); + + // update AS number + h.peerAsNum = pOpenmsg.getAsNumber(); + + h.sendHandshakeOpenMessage(); + h.bgpPacketStats.addOutPacket(); + h.setState(OPENCONFIRM); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.OPENCONFIRM); + } + } + } + }, + + OPENCONFIRM(false) { + @Override + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { + log.debug("Message received in OPENCONFIRM state"); + // check for keep alive message + if (m.getType() != BgpType.KEEP_ALIVE) { + // When the message type is not keep alive message handle the wrong packet + h.processUnknownMsg(BgpErrorType.FINITE_STATE_MACHINE_ERROR, + BgpErrorType.RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE, + m.getType().getType()); + log.debug("Message is not KEEPALIVE message"); + } else { + + // Set the peer connected status + h.bgpPacketStats.addInPacket(); + log.debug("Sending keep alive message in OPENCONFIRM state"); + + final InetSocketAddress inetAddress = (InetSocketAddress) h.address; + h.thisbgpId = BgpId.bgpId(IpAddress.valueOf(inetAddress.getAddress())); + + // set session parameters + h.negotiatedHoldTime = (h.peerHoldTime < h.bgpconfig.getHoldTime()) ? h.peerHoldTime + : h.bgpconfig.getHoldTime(); + h.sessionInfo = new BgpSessionInfoImpl(h.thisbgpId, h.bgpVersion, h.peerAsNum, h.peerHoldTime, + h.peerIdentifier, h.negotiatedHoldTime, h.isIbgpSession); + + h.bgpPeer = h.peerManager.getBgpPeerInstance(h.bgpController, h.sessionInfo, h.bgpPacketStats); + // set the status of bgp as connected + h.bgpPeer.setConnected(true); + h.bgpPeer.setChannel(h.channel); + + /* + * RFC 4271, When an OPEN message is received, sends a KEEPALIVE message, If the negotiated hold + * time value is zero, then the HoldTimer and KeepaliveTimer are not started. A reasonable maximum + * time between KEEPALIVE messages would be one third of the Hold Time interval. + */ + + if (h.negotiatedHoldTime != 0) { + h.keepAliveTimer = new BgpKeepAliveTimer(h, + (h.negotiatedHoldTime / BGP_MAX_KEEPALIVE_INTERVAL)); + } else { + h.sendKeepAliveMessage(); + } + + h.bgpPacketStats.addOutPacket(); + + // set the state handshake completion. + h.setHandshakeComplete(true); + + if (!h.peerManager.addConnectedPeer(h.thisbgpId, h.bgpPeer)) { + disconnectDuplicate(h); + } else { + h.setState(ESTABLISHED); + h.bgpconfig.setPeerConnState(h.peerAddr, BgpPeerCfg.State.ESTABLISHED); + } + } + } + }, + + ESTABLISHED(true) { + @Override + void processBgpMessage(BgpChannelHandler h, BgpMessage m) throws IOException, BgpParseException { + log.debug("Message received in established state " + m.getType()); + // dispatch the message + h.dispatchMessage(m); + } + }; + + private boolean handshakeComplete; + + ChannelState(boolean handshakeComplete) { + this.handshakeComplete = handshakeComplete; + } + + /** + * Is this a state in which the handshake has completed? + * + * @return true if the handshake is complete + */ + public boolean isHandshakeComplete() { + return this.handshakeComplete; + } + + /** + * Disconnect duplicate peer connection. + * + * @param h channel handler + */ + protected void disconnectDuplicate(BgpChannelHandler h) { + log.error("Duplicated BGP IP or incompleted cleanup - " + "" + "disconnecting channel {}", + h.getPeerInfoString()); + h.duplicateBGPIdFound = Boolean.TRUE; + h.channel.disconnect(); + } + + // set handshake completion status + public void setHandshakeComplete(boolean handshakeComplete) { + this.handshakeComplete = handshakeComplete; + } + + void processBgpMessage(BgpChannelHandler bgpChannelHandler, BgpMessage pm) + throws IOException, BgpParseException { + // TODO Auto-generated method stub + log.debug("BGP message stub"); + } + + } + + // ************************* + // Channel handler methods + // ************************* + + @Override + public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { + + channel = e.getChannel(); + log.info("BGP connected from {}", channel.getRemoteAddress()); + + address = channel.getRemoteAddress(); + if (!(address instanceof InetSocketAddress)) { + throw new IOException("Invalid peer connection."); + } + + + inetAddress = (InetSocketAddress) address; + peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); + + + // if connection is already established close channel + if (peerManager.isPeerConnected(BgpId.bgpId(IpAddress.valueOf(peerAddr)))) { + log.debug("Duplicate connection received, peer {}", peerAddr); + channel.close(); + return; + } + + if (null != channel.getPipeline().get("PassiveHandler")) { + log.info("BGP handle connection request from peer"); + // Wait for open message from bgp peer + setState(ChannelState.OPENWAIT); + } else if (null != channel.getPipeline().get("ActiveHandler")) { + log.info("BGP handle connection response from peer"); + + sendHandshakeOpenMessage(); + bgpPacketStats.addOutPacket(); + setState(ChannelState.OPENSENT); + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.OPENSENT); + } + } + + @Override + public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { + + channel = e.getChannel(); + log.info("BGP disconnected callback for bgp:{}. Cleaning up ...", getPeerInfoString()); + + address = channel.getRemoteAddress(); + if (!(address instanceof InetSocketAddress)) { + throw new IOException("Invalid peer connection."); + } + + inetAddress = (InetSocketAddress) address; + peerAddr = IpAddress.valueOf(inetAddress.getAddress()).toString(); + + if (thisbgpId != null) { + if (!duplicateBGPIdFound) { + // if the disconnected peer (on this ChannelHandler) + // was not one with a duplicate, it is safe to remove all + // state for it at the controller. Notice that if the disconnected + // peer was a duplicate-ip, calling the method below would clear + // all state for the original peer (with the same ip), + // which we obviously don't want. + log.debug("{}:removal called", getPeerInfoString()); + if (bgpPeer != null) { + BgpPeerImpl peer = (BgpPeerImpl) bgpPeer; + peerManager.removeConnectedPeer(thisbgpId); + peer.updateLocalRIBOnPeerDisconnect(); + } + + // Retry connection if connection is lost to bgp speaker/peer + if ((channel != null) && (null != channel.getPipeline().get("ActiveHandler"))) { + BgpConnectPeerImpl connectPeer; + BgpPeerCfg.State peerCfgState; + + peerCfgState = bgpconfig.getPeerConnState(peerAddr); + // on session disconnect using configuration, do not retry + if (!peerCfgState.equals(BgpPeerCfg.State.IDLE)) { + log.debug("Connection reset by peer, retry, STATE:{}", peerCfgState); + BgpPeerConfig peerConfig = (BgpPeerConfig) bgpconfig.displayPeers(peerAddr); + + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); + connectPeer = new BgpConnectPeerImpl(bgpController, peerAddr, Controller.getBgpPortNum()); + peerConfig.setConnectPeer(connectPeer); + } + } else { + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); + } + } else { + // A duplicate was disconnected on this ChannelHandler, + // this is the same peer reconnecting, but the original state was + // not cleaned up - XXX check liveness of original ChannelHandler + log.debug("{}:duplicate found", getPeerInfoString()); + duplicateBGPIdFound = Boolean.FALSE; + } + + if (null != keepAliveTimer) { + keepAliveTimer.getKeepAliveTimer().cancel(); + } + } else { + bgpconfig.setPeerConnState(peerAddr, BgpPeerCfg.State.IDLE); + log.warn("No bgp ip in channelHandler registered for " + "disconnected peer {}", getPeerInfoString()); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { + + log.info("[exceptionCaught]: " + e.toString()); + + if (e.getCause() instanceof ReadTimeoutException) { + if ((ChannelState.OPENWAIT == state) || (ChannelState.OPENSENT == state)) { + + // When ReadTimeout timer is expired in OPENWAIT/OPENSENT state, it is considered + sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); + channel.close(); + state = ChannelState.IDLE; + return; + } else if (ChannelState.OPENCONFIRM == state) { + + // When ReadTimeout timer is expired in OPENCONFIRM state. + sendNotification(BgpErrorType.HOLD_TIMER_EXPIRED, (byte) 0, null); + channel.close(); + state = ChannelState.IDLE; + return; + } + } else if (e.getCause() instanceof ClosedChannelException) { + log.debug("Channel for bgp {} already closed", getPeerInfoString()); + } else if (e.getCause() instanceof IOException) { + log.error("Disconnecting peer {} due to IO Error: {}", getPeerInfoString(), e.getCause().getMessage()); + if (log.isDebugEnabled()) { + // still print stack trace if debug is enabled + log.debug("StackTrace for previous Exception: ", e.getCause()); + } + channel.close(); + } else if (e.getCause() instanceof BgpParseException) { + byte[] data = new byte[] {}; + BgpParseException errMsg = (BgpParseException) e.getCause(); + byte errorCode = errMsg.getErrorCode(); + byte errorSubCode = errMsg.getErrorSubCode(); + ChannelBuffer tempCb = errMsg.getData(); + if (tempCb != null) { + int dataLength = tempCb.capacity(); + data = new byte[dataLength]; + tempCb.readBytes(data, 0, dataLength); + } + sendNotification(errorCode, errorSubCode, data); + } else if (e.getCause() instanceof RejectedExecutionException) { + log.warn("Could not process message: queue full"); + } else { + log.error("Error while processing message from peer " + getPeerInfoString() + "state " + this.state); + channel.close(); + } + } + + @Override + public String toString() { + return getPeerInfoString(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + if (e.getMessage() instanceof List) { + @SuppressWarnings("Unchecked") + List msglist = (List) e.getMessage(); + for (BgpMessage pm : msglist) { + // Do the actual packet processing + state.processBgpMessage(this, pm); + } + } else { + state.processBgpMessage(this, (BgpMessage) e.getMessage()); + } + } + + /** + * Check for connection collision. + * + * @param state connection state + * @param peerIdentifier BGP peer identifier + * @param peerAddr BGP peer address + * @return true if bgp spreakers initiated connection + * @throws BgpParseException on error while procession collision detection + * @throws IOException on error while procession collision detection + */ + public boolean connectionCollisionDetection(BgpPeerCfg.State state, int peerIdentifier, String peerAddr) + throws IOException, BgpParseException { + /* + * RFC 4271, Section 6.8, Based on the value of the BGP identifier, a convention is established for detecting + * which BGP connection is to be preserved when a collision occurs. The convention is to compare the BGP + * Identifiers of the peers involved in the collision and to retain only the connection initiated by the BGP + * speaker with the higher-valued BGP Identifier.. + */ + BgpPeerCfg.State currentState = bgpconfig.getPeerConnState(peerAddr); + if (currentState.equals(state)) { + if (((Ip4Address.valueOf(bgpconfig.getRouterId())).compareTo(Ip4Address.valueOf(peerIdentifier))) > 0) { + // send notification + sendNotification(BgpErrorType.CEASE, BgpErrorType.CONNECTION_COLLISION_RESOLUTION, null); + log.debug("Connection collision detected, local id: {}, peer id: {}, peer state:{}, in state:{}", + (Ip4Address.valueOf(bgpconfig.getRouterId())), (Ip4Address.valueOf(peerIdentifier)), + currentState, state); + return true; + } + } + + return false; + } + + // ************************* + // Channel utility methods + // ************************* + /** + * Set handshake status. + * + * @param handshakeComplete handshake complete status + */ + public void setHandshakeComplete(boolean handshakeComplete) { + this.state.setHandshakeComplete(handshakeComplete); + } + + /** + * Is this a state in which the handshake has completed? + * + * @return true if the handshake is complete + */ + public boolean isHandshakeComplete() { + return state.isHandshakeComplete(); + } + + /** + * To handle the BGP message. + * + * @param m bgp message + * @throws BgpParseException throw exception + */ + private void dispatchMessage(BgpMessage m) throws BgpParseException { + bgpPacketStats.addInPacket(); + bgpController.processBGPPacket(thisbgpId, m); + } + + /** + * Return a string describing this peer based on the already available information (ip address and/or remote + * socket). + * + * @return display string + */ + private String getPeerInfoString() { + if (bgpPeer != null) { + return bgpPeer.toString(); + } + String channelString; + if (channel == null || channel.getRemoteAddress() == null) { + channelString = "?"; + } else { + channelString = channel.getRemoteAddress().toString(); + } + String bgpIpString; + // TODO: implement functionality to get bgp id string + bgpIpString = "?"; + return String.format("[%s BGP-IP[%s]]", channelString, bgpIpString); + } + + /** + * Update the channels state. Only called from the state machine. TODO: enforce restricted state transitions + * + * @param state + */ + private void setState(ChannelState state) { + this.state = state; + } + + /** + * get packet statistics. + * + * @return packet statistics + */ + public BgpPacketStatsImpl getBgpPacketStats() { + return bgpPacketStats; + } + + /** + * Send handshake open message to the peer. + * + * @throws IOException, BgpParseException + */ + private void sendHandshakeOpenMessage() throws IOException, BgpParseException { + int bgpId; + + InetSocketAddress localAddress = (InetSocketAddress) channel.getLocalAddress(); + + bgpId = Ip4Address.valueOf(IpAddress.valueOf(localAddress.getAddress()).toString()).toInt(); + BgpMessage msg = factory4.openMessageBuilder().setAsNumber((short) peerAsNum) + .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId).setLsCapabilityTlv(bgpconfig.getLsCapability()) + .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability()).build(); + log.debug("Sending open message to {}", channel.getRemoteAddress()); + channel.write(Collections.singletonList(msg)); + + } + + /** + * Send notification message to peer. + * + * @param errorCode error code send in notification + * @param errorSubCode sub error code send in notification + * @param data data to send in notification + * @throws IOException, BgpParseException while building message + */ + private void sendNotification(byte errorCode, byte errorSubCode, byte[] data) + throws IOException, BgpParseException { + BgpMessage msg = factory4.notificationMessageBuilder().setErrorCode(errorCode) + .setErrorSubCode(errorSubCode).setData(data).build(); + log.debug("Sending notification message to {}", channel.getRemoteAddress()); + channel.write(Collections.singletonList(msg)); + } + + /** + * Send keep alive message. + * + * @throws IOException when channel is disconnected + * @throws BgpParseException while building keep alive message + */ + synchronized void sendKeepAliveMessage() throws IOException, BgpParseException { + + BgpMessage msg = factory4.keepaliveMessageBuilder().build(); + log.debug("Sending keepalive message to {}", channel.getRemoteAddress()); + channel.write(Collections.singletonList(msg)); + } + + /** + * Process unknown BGP message received. + * + * @param errorCode error code + * @param errorSubCode error sub code + * @param data message type + * @throws BgpParseException while processing error messsage + * @throws IOException while processing error message + */ + public void processUnknownMsg(byte errorCode, byte errorSubCode, byte data) throws BgpParseException, IOException { + log.debug("UNKNOWN message received"); + byte[] byteArray = new byte[1]; + byteArray[0] = data; + sendNotification(errorCode, errorSubCode, byteArray); + channel.close(); + } + + /** + * BGP open message validation. + * + * @param h channel handler + * @param openMsg open message + * @return true if valid message, otherwise false + * @throws BgpParseException throw exception + */ + public boolean openMsgValidation(BgpChannelHandler h, BgpOpenMsg openMsg) throws BgpParseException { + boolean result; + + // Validate BGP ID + result = bgpIdValidation(openMsg); + if (!result) { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_BGP_IDENTIFIER, null); + } + + + // Validate hold timer + if ((openMsg.getHoldTime() != 0) && (openMsg.getHoldTime() < BGP_MIN_HOLDTIME)) { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNACCEPTABLE_HOLD_TIME, null); + } + + // Validate capabilities + result = capabilityValidation(h, openMsg); + return result; + } + + /** + * Capability Validation. + * + * @param h channel handler + * @param openmsg open message + * @return success or failure + * @throws BgpParseException + */ + private boolean capabilityValidation(BgpChannelHandler h, BgpOpenMsg openmsg) throws BgpParseException { + log.debug("capabilityValidation"); + + boolean isMultiProtocolcapabilityExists = false; + boolean isFourOctetCapabilityExits = false; + int capAsNum = 0; + + List capabilityTlv = openmsg.getCapabilityTlv(); + ListIterator listIterator = capabilityTlv.listIterator(); + List unSupportedCapabilityTlv = new LinkedList<>(); + ListIterator unSupportedCaplistIterator = unSupportedCapabilityTlv.listIterator(); + BgpValueType tempTlv; + boolean isLargeAsCapabilityCfg = h.bgpconfig.getLargeASCapability(); + boolean isLsCapabilityCfg = h.bgpconfig.getLsCapability(); + + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (tlv.getType() == MULTI_PROTOCOL_EXTN_CAPA_TYPE) { + isMultiProtocolcapabilityExists = true; + } + if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { + isFourOctetCapabilityExits = true; + capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); + } + } + + if (isFourOctetCapabilityExits) { + if (capAsNum > MAX_AS2_NUM) { + if (openmsg.getAsNumber() != AS_TRANS) { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); + } + } else { + if (capAsNum != openmsg.getAsNumber()) { + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_PEER_AS, null); + } + } + } + + if ((isLsCapabilityCfg)) { + if (!isMultiProtocolcapabilityExists) { + tempTlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI); + unSupportedCapabilityTlv.add(tempTlv); + } + } + + if ((isLargeAsCapabilityCfg)) { + if (!isFourOctetCapabilityExits) { + tempTlv = new FourOctetAsNumCapabilityTlv(h.bgpconfig.getAsNumber()); + unSupportedCapabilityTlv.add(tempTlv); + } + } + + if (unSupportedCaplistIterator.hasNext()) { + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + while (unSupportedCaplistIterator.hasNext()) { + BgpValueType tlv = unSupportedCaplistIterator.next(); + tlv.write(buffer); + } + throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNSUPPORTED_CAPABILITY, buffer); + } else { + return true; + } + } + + /** + * AS Number Validation. + * + * @param h channel Handler + * @param openMsg open message + * @return true or false + */ + private boolean asNumberValidation(BgpChannelHandler h, BgpOpenMsg openMsg) { + log.debug("AS Num validation"); + + int capAsNum = 0; + boolean isFourOctetCapabilityExits = false; + + BgpPeerCfg peerCfg = h.bgpconfig.displayPeers(peerAddr); + List capabilityTlv = openMsg.getCapabilityTlv(); + ListIterator listIterator = capabilityTlv.listIterator(); + + while (listIterator.hasNext()) { + BgpValueType tlv = listIterator.next(); + if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) { + isFourOctetCapabilityExits = true; + capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt(); + } + } + + if (peerCfg.getAsNumber() > MAX_AS2_NUM) { + if (openMsg.getAsNumber() != AS_TRANS) { + return false; + } + + if (!isFourOctetCapabilityExits) { + return false; + } + + if (peerCfg.getAsNumber() != capAsNum) { + return false; + } + + isIbgpSession = peerCfg.getIsIBgp(); + if (isIbgpSession) { + // IBGP - AS number should be same for Peer and local if it is IBGP + if (h.bgpconfig.getAsNumber() != capAsNum) { + return false; + } + } + } else { + + if (openMsg.getAsNumber() != peerCfg.getAsNumber()) { + return false; + } + + if (isFourOctetCapabilityExits) { + if (capAsNum != peerCfg.getAsNumber()) { + return false; + } + } + + isIbgpSession = peerCfg.getIsIBgp(); + if (isIbgpSession) { + // IBGP - AS number should be same for Peer and local if it is IBGP + if (openMsg.getAsNumber() != h.bgpconfig.getAsNumber()) { + return false; + } + } + } + return true; + } + + /** + * Validates BGP ID. + * + * @param openMsg open message + * @return true or false + */ + private boolean bgpIdValidation(BgpOpenMsg openMsg) { + String openMsgBgpId = Ip4Address.valueOf(openMsg.getBgpId()).toString(); + + InetAddress ipAddress; + try { + ipAddress = InetAddress.getByName(openMsgBgpId); + if (ipAddress.isMulticastAddress()) { + return false; + } + } catch (UnknownHostException e) { + log.debug("InetAddress convertion failed"); + } + return true; + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java new file mode 100755 index 00000000..95a07ad5 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java @@ -0,0 +1,364 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpConnectPeer; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpPeerCfg; +import org.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides BGP configuration of this BGP speaker. + */ +public class BgpConfig implements BgpCfg { + + protected static final Logger log = LoggerFactory.getLogger(BgpConfig.class); + + private static final short DEFAULT_HOLD_TIMER = 120; + private static final short DEFAULT_CONN_RETRY_TIME = 120; + private static final short DEFAULT_CONN_RETRY_COUNT = 5; + + private State state = State.INIT; + private int localAs; + private int maxSession; + private boolean lsCapability; + private short holdTime; + private boolean largeAs = false; + private int maxConnRetryTime; + private int maxConnRetryCount; + + private Ip4Address routerId = null; + private TreeMap bgpPeerTree = new TreeMap<>(); + private BgpConnectPeer connectPeer; + private BgpPeerManagerImpl peerManager; + private BgpController bgpController; + + /* + * Constructor to initialize the values. + */ + public BgpConfig(BgpController bgpController) { + this.bgpController = bgpController; + this.peerManager = (BgpPeerManagerImpl) bgpController.peerManager(); + this.holdTime = DEFAULT_HOLD_TIMER; + this.maxConnRetryTime = DEFAULT_CONN_RETRY_TIME; + this.maxConnRetryCount = DEFAULT_CONN_RETRY_COUNT; + this.lsCapability = true; + } + + @Override + public State getState() { + return state; + } + + @Override + public void setState(State state) { + this.state = state; + } + + @Override + public int getAsNumber() { + return this.localAs; + } + + @Override + public void setAsNumber(int localAs) { + + State localState = getState(); + this.localAs = localAs; + + /* Set configuration state */ + if (localState == State.IP_CONFIGURED) { + setState(State.IP_AS_CONFIGURED); + } else { + setState(State.AS_CONFIGURED); + } + } + + @Override + public int getMaxSession() { + return this.maxSession; + } + + @Override + public void setMaxSession(int maxSession) { + this.maxSession = maxSession; + } + + @Override + public boolean getLsCapability() { + return this.lsCapability; + } + + @Override + public void setLsCapability(boolean lsCapability) { + this.lsCapability = lsCapability; + } + + @Override + public String getRouterId() { + if (this.routerId != null) { + return this.routerId.toString(); + } else { + return null; + } + } + + @Override + public void setRouterId(String routerId) { + State localState = getState(); + this.routerId = Ip4Address.valueOf(routerId); + + /* Set configuration state */ + if (localState == State.AS_CONFIGURED) { + setState(State.IP_AS_CONFIGURED); + } else { + setState(State.IP_CONFIGURED); + } + } + + @Override + public boolean addPeer(String routerid, int remoteAs) { + return addPeer(routerid, remoteAs, DEFAULT_HOLD_TIMER); + } + + @Override + public boolean addPeer(String routerid, short holdTime) { + return addPeer(routerid, this.getAsNumber(), holdTime); + } + + @Override + public boolean addPeer(String routerid, int remoteAs, short holdTime) { + BgpPeerConfig lspeer = new BgpPeerConfig(); + if (this.bgpPeerTree.get(routerid) == null) { + + lspeer.setPeerRouterId(routerid); + lspeer.setAsNumber(remoteAs); + lspeer.setHoldtime(holdTime); + lspeer.setState(BgpPeerCfg.State.IDLE); + lspeer.setSelfInnitConnection(false); + + if (this.getAsNumber() == remoteAs) { + lspeer.setIsIBgp(true); + } else { + lspeer.setIsIBgp(false); + } + + this.bgpPeerTree.put(routerid, lspeer); + log.debug("added successfully"); + return true; + } else { + log.debug("already exists"); + return false; + } + } + + @Override + public boolean connectPeer(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if (lspeer != null) { + lspeer.setSelfInnitConnection(true); + + if (lspeer.connectPeer() == null) { + connectPeer = new BgpConnectPeerImpl(bgpController, routerid, Controller.getBgpPortNum()); + lspeer.setConnectPeer(connectPeer); + connectPeer.connectPeer(); + } + return true; + } + + return false; + } + + @Override + public boolean removePeer(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if (lspeer != null) { + + disconnectPeer(routerid); + lspeer.setSelfInnitConnection(false); + lspeer = this.bgpPeerTree.remove(routerid); + log.debug("Deleted : " + routerid + " successfully"); + + return true; + } else { + log.debug("Did not find : " + routerid); + return false; + } + } + + @Override + public boolean disconnectPeer(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if (lspeer != null) { + + BgpPeer disconnPeer = peerManager.getPeer(BgpId.bgpId(IpAddress.valueOf(routerid))); + if (disconnPeer != null) { + // TODO: send notification peer deconfigured + disconnPeer.disconnectPeer(); + } + lspeer.connectPeer().disconnectPeer(); + lspeer.setState(BgpPeerCfg.State.IDLE); + lspeer.setSelfInnitConnection(false); + log.debug("Disconnected : " + routerid + " successfully"); + + return true; + } else { + log.debug("Did not find : " + routerid); + return false; + } + } + + @Override + public void setPeerConnState(String routerid, BgpPeerCfg.State state) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if (lspeer != null) { + lspeer.setState(state); + log.debug("Peer : " + routerid + " is not available"); + + return; + } else { + log.debug("Did not find : " + routerid); + return; + } + } + + @Override + public BgpPeerCfg.State getPeerConnState(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if (lspeer != null) { + return lspeer.getState(); + } else { + return BgpPeerCfg.State.INVALID; //No instance + } + } + + @Override + public boolean isPeerConnectable(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + + if ((lspeer != null) && lspeer.getState().equals(BgpPeerCfg.State.IDLE)) { + return true; + } + + return false; + } + + @Override + public TreeMap getPeerTree() { + return this.bgpPeerTree; + } + + @Override + public TreeMap displayPeers() { + if (this.bgpPeerTree.isEmpty()) { + log.debug("There are no BGP peers"); + } else { + Set> set = this.bgpPeerTree.entrySet(); + Iterator> list = set.iterator(); + BgpPeerCfg lspeer; + + while (list.hasNext()) { + Entry me = list.next(); + lspeer = me.getValue(); + log.debug("Peer neighbor IP :" + me.getKey()); + log.debug(", AS Number : " + lspeer.getAsNumber()); + log.debug(", Hold Timer : " + lspeer.getHoldtime()); + log.debug(", Is iBGP : " + lspeer.getIsIBgp()); + } + } + return null; + } + + @Override + public BgpPeerCfg displayPeers(String routerid) { + + if (this.bgpPeerTree.isEmpty()) { + log.debug("There are no Bgp peers"); + } else { + return this.bgpPeerTree.get(routerid); + } + return null; + } + + @Override + public void setHoldTime(short holdTime) { + this.holdTime = holdTime; + } + + @Override + public short getHoldTime() { + return this.holdTime; + } + + @Override + public boolean getLargeASCapability() { + return this.largeAs; + } + + @Override + public void setLargeASCapability(boolean largeAs) { + this.largeAs = largeAs; + } + + @Override + public boolean isPeerConfigured(String routerid) { + BgpPeerCfg lspeer = this.bgpPeerTree.get(routerid); + return (lspeer != null) ? true : false; + } + + @Override + public boolean isPeerConnected(String routerid) { + // TODO: is peer connected + return true; + } + + @Override + public int getMaxConnRetryCount() { + return this.maxConnRetryCount; + } + + @Override + public void setMaxConnRetryCout(int retryCount) { + this.maxConnRetryCount = retryCount; + } + + @Override + public int getMaxConnRetryTime() { + return this.maxConnRetryTime; + } + + @Override + public void setMaxConnRetryTime(int retryTime) { + this.maxConnRetryTime = retryTime; + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java new file mode 100755 index 00000000..27db618d --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConnectPeerImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpPeerCfg; +import org.onosproject.bgp.controller.BgpConnectPeer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implements connection initiation to peer on peer configuration and manage channel using netty channel handler. + */ +public class BgpConnectPeerImpl implements BgpConnectPeer { + private static final Logger log = LoggerFactory.getLogger(BgpConnectPeerImpl.class); + + private ScheduledExecutorService connectExecutor = null; + private final String peerHost; + private static final int RETRY_INTERVAL = 4; + private final int peerPort; + private int connectRetryCounter = 0; + private int connectRetryTime; + private ChannelPipelineFactory pfact; + private ClientBootstrap peerBootstrap; + private BgpCfg bgpconfig; + + /** + * Initialize timer and initiate pipeline factory. + * + * @param bgpController parent BGP controller + * @param remoteHost remote host to connect + * @param remotePort remote port to connect + */ + public BgpConnectPeerImpl(BgpController bgpController, String remoteHost, int remotePort) { + + this.bgpconfig = bgpController.getConfig(); + this.pfact = new BgpPipelineFactory(bgpController, false); + this.peerBootstrap = Controller.peerBootstrap(); + this.peerBootstrap.setPipelineFactory(pfact); + this.peerHost = remoteHost; + this.peerPort = remotePort; + this.connectRetryTime = 0; + } + + @Override + public void disconnectPeer() { + if (connectExecutor != null) { + connectExecutor.shutdown(); + connectExecutor = null; + } + } + + @Override + public void connectPeer() { + scheduleConnectionRetry(this.connectRetryTime); + } + + /** + * Retry connection with exponential back-off mechanism. + * + * @param retryDelay retry delay + */ + private void scheduleConnectionRetry(long retryDelay) { + if (this.connectExecutor == null) { + this.connectExecutor = Executors.newSingleThreadScheduledExecutor(); + } + this.connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES); + } + + /** + * Implements BGP connection and manages connection to peer with back-off mechanism in case of failure. + */ + class ConnectionRetry implements Runnable { + @Override + public void run() { + log.debug("Connect to peer {}", peerHost); + + InetSocketAddress connectToSocket = new InetSocketAddress(peerHost, peerPort); + + try { + bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.CONNECT); + peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + bgpconfig.setPeerConnState(peerHost, BgpPeerCfg.State.ACTIVE); + connectRetryCounter++; + log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter, + peerHost); + /* + * Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4 + * mins. + */ + if (connectRetryTime < RETRY_INTERVAL) { + connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1; + } + scheduleConnectionRetry(connectRetryTime); + } else { + + connectRetryCounter++; + log.info("Connected to remote host {}, Connect Counter {}", peerHost, connectRetryCounter); + disconnectPeer(); + return; + } + } + }); + } catch (Exception e) { + log.info("Connect peer exception : " + e.toString()); + disconnectPeer(); + } + } + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java new file mode 100755 index 00000000..51ab68be --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java @@ -0,0 +1,266 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpLocalRib; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpNodeListener; +import org.onosproject.bgp.controller.BgpPeerManager; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.BgpUpdateMsg; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.MpReachNlri; +import org.onosproject.bgpio.types.MpUnReachNlri; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component(immediate = true) +@Service +public class BgpControllerImpl implements BgpController { + + private static final Logger log = LoggerFactory.getLogger(BgpControllerImpl.class); + + protected ConcurrentHashMap connectedPeers = new ConcurrentHashMap(); + + protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl(); + + private BgpLocalRib bgplocalRIB = new BgpLocalRibImpl(this); + private BgpLocalRib bgplocalRIBVpn = new BgpLocalRibImpl(this); + + protected Set bgpNodeListener = new CopyOnWriteArraySet<>(); + + final Controller ctrl = new Controller(this); + + private BgpConfig bgpconfig = new BgpConfig(this); + + @Activate + public void activate() { + this.ctrl.start(); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + // Close all connected peers + closeConnectedPeers(); + this.ctrl.stop(); + log.info("Stopped"); + } + + @Override + public Iterable getPeers() { + return this.connectedPeers.values(); + } + + @Override + public BgpPeer getPeer(BgpId bgpId) { + return this.connectedPeers.get(bgpId); + } + + @Override + public void addListener(BgpNodeListener listener) { + this.bgpNodeListener.add(listener); + } + + @Override + public void removeListener(BgpNodeListener listener) { + this.bgpNodeListener.remove(listener); + } + + @Override + public Set listener() { + return bgpNodeListener; + } + + @Override + public void writeMsg(BgpId bgpId, BgpMessage msg) { + this.getPeer(bgpId).sendMessage(msg); + } + + @Override + public void processBGPPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException { + + BgpPeer peer = getPeer(bgpId); + + switch (msg.getType()) { + case OPEN: + // TODO: Process Open message + break; + case KEEP_ALIVE: + // TODO: Process keepalive message + break; + case NOTIFICATION: + // TODO: Process notificatoin message + break; + case UPDATE: + BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg; + List pathAttr = updateMsg.bgpPathAttributes().pathAttributes(); + if (pathAttr == null) { + log.debug("llPathAttr is null, cannot process update message"); + break; + } + Iterator listIterator = pathAttr.iterator(); + boolean isLinkstate = false; + while (listIterator.hasNext()) { + BgpValueType attr = listIterator.next(); + if ((attr instanceof MpReachNlri) || (attr instanceof MpUnReachNlri)) { + isLinkstate = true; + } + } + if (isLinkstate) { + peer.buildAdjRibIn(pathAttr); + } + break; + default: + // TODO: Process other message + break; + } + } + + @Override + public void closeConnectedPeers() { + BgpPeer bgpPeer; + for (BgpId id : this.connectedPeers.keySet()) { + bgpPeer = getPeer(id); + bgpPeer.disconnectPeer(); + } + } + + /** + * Implementation of an BGP Peer which is responsible for keeping track of connected peers and the state in which + * they are. + */ + public class BgpPeerManagerImpl implements BgpPeerManager { + + private final Logger log = LoggerFactory.getLogger(BgpPeerManagerImpl.class); + private final Lock peerLock = new ReentrantLock(); + + @Override + public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer) { + + if (connectedPeers.get(bgpId) != null) { + this.log.error("Trying to add connectedPeer but found previous " + "value for bgp ip: {}", + bgpId.toString()); + return false; + } else { + this.log.debug("Added Peer {}", bgpId.toString()); + connectedPeers.put(bgpId, bgpPeer); + return true; + } + } + + @Override + public boolean isPeerConnected(BgpId bgpId) { + if (connectedPeers.get(bgpId) == null) { + this.log.error("Is peer connected: bgpIp {}.", bgpId.toString()); + return false; + } + + return true; + } + + @Override + public void removeConnectedPeer(BgpId bgpId) { + connectedPeers.remove(bgpId); + } + + @Override + public BgpPeer getPeer(BgpId bgpId) { + return connectedPeers.get(bgpId); + } + + /** + * Gets bgp peer instance. + * + * @param bgpController controller instance. + * @param sessionInfo bgp session info. + * @param pktStats packet statistics. + * @return BGPPeer peer instance. + */ + public BgpPeer getBgpPeerInstance(BgpController bgpController, BgpSessionInfoImpl sessionInfo, + BgpPacketStatsImpl pktStats) { + BgpPeer bgpPeer = new BgpPeerImpl(bgpController, sessionInfo, pktStats); + return bgpPeer; + } + + } + + /** + * Returns controller. + * + * @return controller + */ + public Controller controller() { + return this.ctrl; + } + + @Override + public ConcurrentHashMap connectedPeers() { + return connectedPeers; + } + + @Override + public BgpPeerManagerImpl peerManager() { + return peerManager; + } + + @Override + public BgpCfg getConfig() { + return this.bgpconfig; + } + + @Override + public int connectedPeerCount() { + return connectedPeers.size(); + } + + /** + * Gets the BGP local RIB. + * + * @return bgplocalRIB BGP local RIB. + */ + @Override + public BgpLocalRib bgpLocalRib() { + return bgplocalRIB; + } + + /** + * Gets the BGP local RIB with VPN. + * + * @return bgplocalRIBVpn BGP VPN local RIB . + */ + @Override + public BgpLocalRib bgpLocalRibVpn() { + return bgplocalRIBVpn; + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java new file mode 100755 index 00000000..524ac4c1 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpKeepAliveTimer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Timer; +import java.util.TimerTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implement sending keepalive message to connected peer periodically based on negotiated holdtime. + */ +public class BgpKeepAliveTimer { + + private Timer keepAliveTimer; + private BgpChannelHandler handler; + private static final Logger log = LoggerFactory.getLogger(BgpKeepAliveTimer.class); + + /** + * Gets keepalive timer object. + * + * @return keepAliveTimer keepalive timer. + */ + public Timer getKeepAliveTimer() { + return keepAliveTimer; + } + + /** + * Initialize timer to send keepalive message periodically. + * + * @param h channel handler + * @param seconds time interval. + */ + public BgpKeepAliveTimer(BgpChannelHandler h, int seconds) { + this.handler = h; + this.keepAliveTimer = new Timer(); + this.keepAliveTimer.schedule(new SendKeepAlive(), 0, seconds * 1000); + } + + /** + * Send keepalive message to connected peer on schedule. + */ + class SendKeepAlive extends TimerTask { + @Override + public void run() { + log.debug("Sending periodic KeepAlive"); + + try { + // Send keep alive message + handler.sendKeepAliveMessage(); + handler.getBgpPacketStats().addOutPacket(); + } catch (Exception e) { + log.info("Exception occured while sending keepAlive message" + e.toString()); + } + } + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java new file mode 100755 index 00000000..44b19057 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpLocalRibImpl.java @@ -0,0 +1,603 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpLocalRib; +import org.onosproject.bgp.controller.BgpNodeListener; +import org.onosproject.bgp.controller.BgpSessionInfo; +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; +import org.onosproject.bgpio.types.RouteDistinguisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.MoreObjects; + +/** + * Implementation of local RIB. + */ +public class BgpLocalRibImpl implements BgpLocalRib { + + private static final Logger log = LoggerFactory.getLogger(BgpLocalRibImpl.class); + private BgpController bgpController; + + private Map nodeTree = new TreeMap<>(); + private Map linkTree = new TreeMap<>(); + private Map prefixTree = new TreeMap<>(); + + private Map> vpnNodeTree + = new TreeMap<>(); + private Map> vpnLinkTree + = new TreeMap<>(); + private Map> vpnPrefixTree + = new TreeMap<>(); + + public BgpLocalRibImpl(BgpController bgpController) { + this.bgpController = bgpController; + } + + /** + * Gets node NLRI tree. + * + * @return node tree + */ + public Map nodeTree() { + return nodeTree; + } + + /** + * Gets link NLRI tree. + * + * @return link tree + */ + public Map linkTree() { + return linkTree; + } + + /** + * Gets prefix NLRI tree. + * + * @return prefix tree + */ + public Map prefixTree() { + return prefixTree; + } + + /** + * Gets VPN node NLRI tree. + * + * @return vpn node NLRI tree + */ + public Map> vpnNodeTree() { + return vpnNodeTree; + } + + /** + * Gets VPN link NLRI tree. + * + * @return vpn link NLRI Tree + */ + public Map> vpnLinkTree() { + return vpnLinkTree; + } + + /** + * Gets VPN prefix NLRI tree. + * + * @return vpn prefix NLRI Tree + */ + public Map> vpnPrefixTree() { + return vpnPrefixTree; + } + + @Override + public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details) { + int decisionResult; + + log.debug("Add to local RIB {}", details.toString()); + + PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib( + sessionInfo.remoteBgpId().ipAddress(), + sessionInfo.remoteBgpIdentifier(), + sessionInfo.remoteBgpASNum(), + sessionInfo.isIbgpSession(), details); + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLsIdentifier)) { + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + // Compare local RIB entry with the current attribute + decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib); + if (decisionResult < 0) { + nodeTree.replace(nodeLsIdentifier, detailsLocRib); + log.debug("Local RIB update node: {}", detailsLocRib.toString()); + } + } else { + nodeTree.put(nodeLsIdentifier, detailsLocRib); + for (BgpNodeListener l : bgpController.listener()) { + l.addNode((BgpNodeLSNlriVer4) nlri); + } + log.debug("Local RIB ad node: {}", detailsLocRib.toString()); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLsIdentifier)) { + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + // Compare local RIB entry with the current attribute + decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib); + if (decisionResult < 0) { + linkTree.replace(linkLsIdentifier, detailsLocRib); + log.debug("Local RIB update link: {}", detailsLocRib.toString()); + } + } else { + linkTree.put(linkLsIdentifier, detailsLocRib); + log.debug("Local RIB add link: {}", detailsLocRib.toString()); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + // Compare local RIB entry with the current attribute + decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib); + if (decisionResult < 0) { + prefixTree.replace(prefixIdentifier, detailsLocRib); + log.debug("Local RIB update prefix: {}", detailsLocRib.toString()); + } + } else { + prefixTree.put(prefixIdentifier, detailsLocRib); + log.debug("Local RIB add prefix: {}", detailsLocRib.toString()); + } + } + } + + @Override + public void delete(BgpLSNlri nlri) { + log.debug("Delete from local RIB."); + + // Update local RIB + decisionProcess(nlri); + } + + /** + * Update local RIB based on selection algorithm. + * + * @param nlri NLRI to update + */ + public void decisionProcess(BgpLSNlri nlri) { + checkNotNull(nlri); + if (nlri instanceof BgpNodeLSNlriVer4) { + selectionProcessNode(nlri, false); + } else if (nlri instanceof BgpLinkLsNlriVer4) { + selectionProcessLink(nlri, false); + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + selectionProcessPrefix(nlri, false); + } + } + + /** + * Update VPN local RIB . + * + * @param nlri NLRI to update + * @param routeDistinguisher VPN id to update + */ + public void decisionProcess(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) { + checkNotNull(nlri); + if (nlri instanceof BgpNodeLSNlriVer4) { + if (vpnNodeTree.containsKey(routeDistinguisher)) { + selectionProcessNode(nlri, true); + if (nodeTree.size() == 0) { + vpnNodeTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (vpnLinkTree.containsKey(routeDistinguisher)) { + selectionProcessLink(nlri, true); + if (linkTree.size() == 0) { + vpnLinkTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (vpnPrefixTree.containsKey(routeDistinguisher)) { + selectionProcessPrefix(nlri, true); + if (prefixTree.size() == 0) { + vpnPrefixTree.remove(routeDistinguisher); + } + } + } + } + + /** + * Selection process for local RIB node. + * + * @param nlri NLRI to update + * @param isVpnRib true if VPN local RIB, otherwise false + */ + public void selectionProcessNode(BgpLSNlri nlri, boolean isVpnRib) { + BgpPeerImpl peer; + BgpSessionInfo sessionInfo; + int decisionResult; + boolean containsKey; + + BgpNodeLSIdentifier nodeLsIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + + if (nodeTree.containsKey(nodeLsIdentifier)) { + for (BgpNodeListener l : bgpController.listener()) { + l.deleteNode((BgpNodeLSNlriVer4) nlri); + } + log.debug("Local RIB delete node: {}", nodeLsIdentifier.toString()); + nodeTree.remove(nodeLsIdentifier); + } + + for (BgpId bgpId : bgpController.connectedPeers().keySet()) { + peer = (BgpPeerImpl) (bgpController.getPeer(bgpId)); + + if (nodeTree.containsKey(nodeLsIdentifier)) { + containsKey = (!isVpnRib) ? (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) : + (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier)); + + if (!containsKey) { + continue; + } + sessionInfo = peer.sessionInfo(); + PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib( + sessionInfo.remoteBgpId().ipAddress(), + sessionInfo.remoteBgpIdentifier(), + sessionInfo.remoteBgpASNum(), + sessionInfo.isIbgpSession(), + (!isVpnRib) ? + (peer.adjacencyRib().nodeTree() + .get(nodeLsIdentifier)) : + (peer.vpnAdjacencyRib().nodeTree() + .get(nodeLsIdentifier))); + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + decisionResult = selectionAlgo.compare(nodeTree.get(nodeLsIdentifier), detailsLocRib); + if (decisionResult < 0) { + nodeTree.replace(nodeLsIdentifier, detailsLocRib); + log.debug("Local RIB node updated: {}", detailsLocRib.toString()); + } + } else { + if (!isVpnRib) { + if (peer.adjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) { + add(peer.sessionInfo(), nlri, peer.adjacencyRib().nodeTree().get(nodeLsIdentifier)); + } + } else { + if (peer.vpnAdjacencyRib().nodeTree().containsKey(nodeLsIdentifier)) { + add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().nodeTree().get(nodeLsIdentifier)); + } + } + } + } + } + + /** + * Selection process for local RIB link. + * + * @param nlri NLRI to update + * @param isVpnRib true if VPN local RIB, otherwise false + */ + public void selectionProcessLink(BgpLSNlri nlri, boolean isVpnRib) { + BgpPeerImpl peer; + BgpSessionInfo sessionInfo; + int decisionResult; + boolean containsKey; + + BgpLinkLSIdentifier linkLsIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + + if (linkTree.containsKey(linkLsIdentifier)) { + log.debug("Local RIB remove link: {}", linkLsIdentifier.toString()); + linkTree.remove(linkLsIdentifier); + } + + for (BgpId bgpId : bgpController.connectedPeers().keySet()) { + peer = (BgpPeerImpl) (bgpController.getPeer(bgpId)); + + if (linkTree.containsKey(linkLsIdentifier)) { + + containsKey = (!isVpnRib) ? (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) : + (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier)); + + if (!containsKey) { + continue; + } + + sessionInfo = peer.sessionInfo(); + + PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib( + sessionInfo.remoteBgpId().ipAddress(), + sessionInfo.remoteBgpIdentifier(), + sessionInfo.remoteBgpASNum(), + sessionInfo.isIbgpSession(), + ((!isVpnRib) ? + (peer.adjacencyRib().linkTree().get(linkLsIdentifier)) : + (peer.vpnAdjacencyRib().linkTree() + .get(linkLsIdentifier)))); + + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + decisionResult = selectionAlgo.compare(linkTree.get(linkLsIdentifier), detailsLocRib); + if (decisionResult < 0) { + linkTree.replace(linkLsIdentifier, detailsLocRib); + log.debug("Local RIB link updated: {}", detailsLocRib.toString()); + } + } else { + if (!isVpnRib) { + if (peer.adjacencyRib().linkTree().containsKey(linkLsIdentifier)) { + add(peer.sessionInfo(), nlri, peer.adjacencyRib().linkTree().get(linkLsIdentifier)); + } + } else { + if (peer.vpnAdjacencyRib().linkTree().containsKey(linkLsIdentifier)) { + add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().linkTree().get(linkLsIdentifier)); + } + } + } + } + } + + /** + * Selection process for local RIB prefix. + * + * @param nlri NLRI to update + * @param isVpnRib true if VPN local RIB, otherwise false + */ + public void selectionProcessPrefix(BgpLSNlri nlri, boolean isVpnRib) { + BgpPeerImpl peer; + BgpSessionInfo sessionInfo; + int decisionResult; + boolean containsKey; + + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + log.debug("Local RIB remove prefix: {}", prefixIdentifier.toString()); + prefixTree.remove(prefixIdentifier); + } + + for (BgpId bgpId : bgpController.connectedPeers().keySet()) { + peer = (BgpPeerImpl) (bgpController.getPeer(bgpId)); + + if (prefixTree.containsKey(prefixIdentifier)) { + + containsKey = (!isVpnRib) ? (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) : + (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier)); + if (!containsKey) { + continue; + } + sessionInfo = peer.sessionInfo(); + + PathAttrNlriDetailsLocalRib detailsLocRib = new PathAttrNlriDetailsLocalRib( + sessionInfo.remoteBgpId().ipAddress(), + sessionInfo.remoteBgpIdentifier(), + sessionInfo.remoteBgpASNum(), + sessionInfo.isIbgpSession(), + ((!isVpnRib) ? + (peer.adjacencyRib().prefixTree() + .get(prefixIdentifier)) : + (peer.vpnAdjacencyRib().prefixTree() + .get(prefixIdentifier)))); + + BgpSelectionAlgo selectionAlgo = new BgpSelectionAlgo(); + decisionResult = selectionAlgo.compare(prefixTree.get(prefixIdentifier), detailsLocRib); + if (decisionResult < 0) { + prefixTree.replace(prefixIdentifier, detailsLocRib); + log.debug("local RIB prefix updated: {}", detailsLocRib.toString()); + } + } else { + if (!isVpnRib) { + if (peer.adjacencyRib().prefixTree().containsKey(prefixIdentifier)) { + add(peer.sessionInfo(), nlri, peer.adjacencyRib().prefixTree().get(prefixIdentifier)); + } else { + if (peer.vpnAdjacencyRib().prefixTree().containsKey(prefixIdentifier)) { + add(peer.sessionInfo(), nlri, peer.vpnAdjacencyRib().prefixTree().get(prefixIdentifier)); + } + } + } + } + } + } + + @Override + public void add(BgpSessionInfo sessionInfo, BgpLSNlri nlri, PathAttrNlriDetails details, + RouteDistinguisher routeDistinguisher) { + add(sessionInfo, nlri, details); + if (nlri instanceof BgpNodeLSNlriVer4) { + if (!vpnNodeTree.containsKey(routeDistinguisher)) { + vpnNodeTree.put(routeDistinguisher, nodeTree); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (!vpnLinkTree.containsKey(routeDistinguisher)) { + vpnLinkTree.put(routeDistinguisher, linkTree); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (!vpnPrefixTree.containsKey(routeDistinguisher)) { + vpnPrefixTree.put(routeDistinguisher, prefixTree); + } + } + } + + @Override + public void delete(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) { + // Update local RIB + decisionProcess(nlri, routeDistinguisher); + } + + /** + * Update local RIB node based on avaliable peer adjacency RIB. + * + * @param o adjacency-in/VPN adjacency-in + */ + public void localRIBUpdateNode(Object o) { + + if (o instanceof AdjRibIn) { + AdjRibIn adjRib = (AdjRibIn) o; + log.debug("Update local RIB node."); + + Set nodeKeys = adjRib.nodeTree().keySet(); + for (BgpNodeLSIdentifier key : nodeKeys) { + PathAttrNlriDetails pathAttrNlri = adjRib.nodeTree().get(key); + + BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(), pathAttrNlri + .protocolID().getType(), key, false, null); + decisionProcess(nodeNlri); + } + } + + if (o instanceof VpnAdjRibIn) { + VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o; + log.debug("Update local RIB VPN node."); + Set nodeKeysVpn = vpnAdjRib.vpnNodeTree().keySet(); + Map node; + for (RouteDistinguisher keyVpnNode : nodeKeysVpn) { + node = vpnAdjRib.vpnNodeTree().get(keyVpnNode); + + Set vpnNodeKeys = node.keySet(); + for (BgpNodeLSIdentifier key : vpnNodeKeys) { + PathAttrNlriDetails pathAttrNlri = vpnAdjRib.nodeTree().get(key); + BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(pathAttrNlri.identifier(), + pathAttrNlri.protocolID().getType(), + key, true, keyVpnNode); + decisionProcess(nodeNlri, keyVpnNode); + } + } + } + } + + /** + * Update localRIB link based on avaliable peer adjacency RIB. + * + * @param o adjacency-in/VPN adjacency-in + */ + public void localRIBUpdateLink(Object o) { + + if (o instanceof AdjRibIn) { + AdjRibIn adjRib = (AdjRibIn) o; + log.debug("Update local RIB link."); + + Set linkKeys = adjRib.linkTree().keySet(); + for (BgpLinkLSIdentifier key : linkKeys) { + PathAttrNlriDetails pathAttrNlri = adjRib.linkTree().get(key); + BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(), + pathAttrNlri.identifier(), key, null, false); + decisionProcess(linkNlri); + } + } + + if (o instanceof VpnAdjRibIn) { + VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o; + log.debug("Update local RIB VPN link"); + + Set linkKeysVpn = vpnAdjRib.vpnLinkTree().keySet(); + Map link; + for (RouteDistinguisher keyVpnLink : linkKeysVpn) { + link = vpnAdjRib.vpnLinkTree().get(keyVpnLink); + + Set vpnLinkKeys = link.keySet(); + for (BgpLinkLSIdentifier key : vpnLinkKeys) { + PathAttrNlriDetails pathAttrNlri = vpnAdjRib.linkTree().get(key); + BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4(pathAttrNlri.protocolID().getType(), + pathAttrNlri.identifier(), key, keyVpnLink, + true); + decisionProcess(linkNlri, keyVpnLink); + } + } + } + } + + /** + * Update localRIB prefix based on avaliable peer adjacency RIB. + * + * @param o instance of adjacency-in/VPN adjacency-in + */ + public void localRIBUpdatePrefix(Object o) { + + if (o instanceof AdjRibIn) { + AdjRibIn adjRib = (AdjRibIn) o; + log.debug("Update local RIB prefix."); + + Set prefixKeys = adjRib.prefixTree().keySet(); + for (BgpPrefixLSIdentifier key : prefixKeys) { + PathAttrNlriDetails pathAttrNlri = adjRib.prefixTree().get(key); + BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4( + pathAttrNlri.identifier(), + pathAttrNlri.protocolID().getType(), + key, null, false); + decisionProcess(prefixNlri); + } + } + + if (o instanceof VpnAdjRibIn) { + VpnAdjRibIn vpnAdjRib = (VpnAdjRibIn) o; + log.debug("Update local RIB VPN prefix."); + + Set prefixKeysVpn = vpnAdjRib.vpnPrefixTree().keySet(); + Map prefix; + for (RouteDistinguisher keyVpnPrefix : prefixKeysVpn) { + prefix = vpnAdjRib.vpnPrefixTree().get(keyVpnPrefix); + + Set vpnPrefixKeys = prefix.keySet(); + for (BgpPrefixLSIdentifier key : vpnPrefixKeys) { + PathAttrNlriDetails pathAttrNlri = vpnAdjRib.prefixTree().get(key); + BgpPrefixIPv4LSNlriVer4 prefixNlri = new BgpPrefixIPv4LSNlriVer4(pathAttrNlri.identifier(), + pathAttrNlri.protocolID() + .getType(), key, + keyVpnPrefix, true); + decisionProcess(prefixNlri, keyVpnPrefix); + } + } + } + } + + /** + * Update localRIB. + * + * @param adjRibIn adjacency RIB-in + */ + public void localRIBUpdate(AdjRibIn adjRibIn) { + log.debug("Update local RIB."); + + localRIBUpdateNode(adjRibIn); + localRIBUpdateLink(adjRibIn); + localRIBUpdatePrefix(adjRibIn); + } + + /** + * Update localRIB. + * + * @param vpnAdjRibIn VPN adjacency RIB-in + */ + public void localRIBUpdate(VpnAdjRibIn vpnAdjRibIn) { + log.debug("Update VPN local RIB."); + + localRIBUpdateNode(vpnAdjRibIn); + localRIBUpdateLink(vpnAdjRibIn); + localRIBUpdatePrefix(vpnAdjRibIn); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues().add("nodeTree", nodeTree) + .add("linkTree", linkTree).add("prefixTree", prefixTree).add("vpnNodeTree", vpnNodeTree) + .add("vpnLinkTree", vpnLinkTree).add("vpnPrefixTree", vpnPrefixTree).toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java new file mode 100755 index 00000000..431c6210 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageDecoder.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.util.LinkedList; +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onlab.util.HexDump; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpMessageReader; +import org.onosproject.bgpio.types.BgpHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Decode an bgp message from a Channel, for use in a netty pipeline. + */ +public class BgpMessageDecoder extends FrameDecoder { + + protected static final Logger log = LoggerFactory.getLogger(BgpMessageDecoder.class); + + @Override + protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { + log.debug("MESSAGE IS RECEIVED."); + if (!channel.isConnected()) { + log.info("Channel is not connected."); + return null; + } + + HexDump.dump(buffer); + + BgpMessageReader reader = BgpFactories.getGenericReader(); + List msgList = new LinkedList(); + + while (buffer.readableBytes() > 0) { + BgpHeader bgpHeader = new BgpHeader(); + BgpMessage message = reader.readFrom(buffer, bgpHeader); + msgList.add(message); + } + return msgList; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java new file mode 100755 index 00000000..3e56d6ff --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpMessageEncoder.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onlab.util.HexDump; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Encode an bgp message for output into a ChannelBuffer, for use in a + * netty pipeline. + */ +public class BgpMessageEncoder extends OneToOneEncoder { + protected static final Logger log = LoggerFactory.getLogger(BgpMessageEncoder.class); + + @Override + protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { + log.debug("BGPMessageEncoder::encode"); + if (!(msg instanceof List)) { + log.debug("Invalid msg."); + return msg; + } + + @SuppressWarnings("unchecked") + List msglist = (List) msg; + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + + log.debug("SENDING MESSAGE"); + for (BgpMessage pm : msglist) { + pm.writeTo(buf); + } + + HexDump.dump(buf); + + return buf; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java new file mode 100755 index 00000000..7494c814 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPacketStatsImpl.java @@ -0,0 +1,124 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import org.onosproject.bgp.controller.BgpPacketStats; + +/** + * A representation of a packet context which allows any provider + * to view a packet in event, but may block the response to the + * event if blocked has been called. This packet context can be used + * to react to the packet in event with a packet out. + */ +public class BgpPacketStatsImpl implements BgpPacketStats { + + private int inPacketCount; + private int outPacketCount; + private int wrongPacketCount; + private long time; + + /** + * Resets parameter. + */ + public BgpPacketStatsImpl() { + this.inPacketCount = 0; + this.outPacketCount = 0; + this.wrongPacketCount = 0; + this.time = 0; + } + + /** + * Get the outgoing packet count number. + * + * @return packet count + */ + public int outPacketCount() { + return outPacketCount; + } + + /** + * Get the incoming packet count number. + * + * @return packet count + */ + public int inPacketCount() { + return inPacketCount; + } + + /** + * Get the wrong packet count number. + * + * @return packet count + */ + public int wrongPacketCount() { + return wrongPacketCount; + } + + /** + * Increments the received packet counter. + */ + public void addInPacket() { + this.inPacketCount++; + } + + /** + * Increments the sent packet counter. + */ + public void addOutPacket() { + this.outPacketCount++; + } + + /** + * Increments the sent packet counter by specified value. + * + * @param value of no of packets sent + */ + public void addOutPacket(int value) { + this.outPacketCount = this.outPacketCount + value; + } + + /** + * Increments the wrong packet counter. + */ + public void addWrongPacket() { + this.wrongPacketCount++; + } + + /** + * Resets wrong packet count. + */ + public void resetWrongPacket() { + this.wrongPacketCount = 0; + } + + /** + * Get the time. + * + * @return time + */ + public long getTime() { + return this.time; + } + + /** + * Sets the time. + * + * @param time value to set + */ + public void setTime(long time) { + this.time = time; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java new file mode 100755 index 00000000..a8eaee3c --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import org.onlab.packet.Ip4Address; +import org.onosproject.bgp.controller.BgpConnectPeer; +import org.onosproject.bgp.controller.BgpPeerCfg; + +/** + * BGP Peer configuration information. + */ +public class BgpPeerConfig implements BgpPeerCfg { + private int asNumber; + private short holdTime; + private boolean isIBgp; + private Ip4Address peerId = null; + private State state; + private boolean selfInitiated; + private BgpConnectPeer connectPeer; + + /** + * Constructor to initialize the values. + */ + BgpPeerConfig() { + state = State.IDLE; + selfInitiated = false; + } + + @Override + public int getAsNumber() { + return this.asNumber; + } + + @Override + public void setAsNumber(int asNumber) { + this.asNumber = asNumber; + } + + @Override + public short getHoldtime() { + return this.holdTime; + } + + @Override + public void setHoldtime(short holdTime) { + this.holdTime = holdTime; + } + + @Override + public boolean getIsIBgp() { + return this.isIBgp; + } + + @Override + public void setIsIBgp(boolean isIBgp) { + this.isIBgp = isIBgp; + } + + @Override + public String getPeerRouterId() { + if (this.peerId != null) { + return this.peerId.toString(); + } else { + return null; + } + } + + @Override + public void setPeerRouterId(String peerId) { + this.peerId = Ip4Address.valueOf(peerId); + } + + @Override + public void setPeerRouterId(String peerId, int asNumber) { + this.peerId = Ip4Address.valueOf(peerId); + this.asNumber = asNumber; + } + + @Override + public State getState() { + return this.state; + } + + @Override + public void setState(State state) { + this.state = state; + } + + @Override + public boolean getSelfInnitConnection() { + return this.selfInitiated; + } + + @Override + public void setSelfInnitConnection(boolean selfInit) { + this.selfInitiated = selfInit; + } + + @Override + public BgpConnectPeer connectPeer() { + return this.connectPeer; + } + + @Override + public void setConnectPeer(BgpConnectPeer connectPeer) { + this.connectPeer = connectPeer; + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java new file mode 100644 index 00000000..e3f09f30 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java @@ -0,0 +1,346 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; +import java.util.concurrent.RejectedExecutionException; + +import org.jboss.netty.channel.Channel; +import org.onlab.packet.IpAddress; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpSessionInfo; +import org.onosproject.bgp.controller.BgpLocalRib; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.BgpMessage; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.MpReachNlri; +import org.onosproject.bgpio.types.MpUnReachNlri; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * BGPPeerImpl implements BGPPeer, maintains peer information and store updates in RIB . + */ +public class BgpPeerImpl implements BgpPeer { + + protected final Logger log = LoggerFactory.getLogger(BgpPeerImpl.class); + + private static final String SHUTDOWN_MSG = "Worker has already been shutdown"; + + private BgpController bgpController; + private Channel channel; + protected String channelId; + private boolean connected; + protected boolean isHandShakeComplete = false; + private BgpSessionInfo sessionInfo; + private BgpPacketStatsImpl pktStats; + private BgpLocalRib bgplocalRIB; + private BgpLocalRib bgplocalRIBVpn; + private AdjRibIn adjRib; + private VpnAdjRibIn vpnAdjRib; + + /** + * Return the adjacency RIB-IN. + * + * @return adjRib the adjacency RIB-IN + */ + public AdjRibIn adjacencyRib() { + return adjRib; + } + + /** + * Return the adjacency RIB-IN with VPN. + * + * @return vpnAdjRib the adjacency RIB-IN with VPN + */ + public VpnAdjRibIn vpnAdjacencyRib() { + return vpnAdjRib; + } + + @Override + public BgpSessionInfo sessionInfo() { + return sessionInfo; + } + + /** + * Initialize peer. + * + *@param bgpController controller instance + *@param sessionInfo bgp session info + *@param pktStats packet statistics + */ + public BgpPeerImpl(BgpController bgpController, BgpSessionInfo sessionInfo, BgpPacketStatsImpl pktStats) { + this.bgpController = bgpController; + this.sessionInfo = sessionInfo; + this.pktStats = pktStats; + this.bgplocalRIB = bgpController.bgpLocalRib(); + this.bgplocalRIBVpn = bgpController.bgpLocalRibVpn(); + this.adjRib = new AdjRibIn(); + this.vpnAdjRib = new VpnAdjRibIn(); + } + + + @Override + public void buildAdjRibIn(List pathAttr) throws BgpParseException { + ListIterator iterator = pathAttr.listIterator(); + while (iterator.hasNext()) { + BgpValueType attr = iterator.next(); + if (attr instanceof MpReachNlri) { + List nlri = ((MpReachNlri) attr).mpReachNlri(); + callAdd(this, nlri, pathAttr); + } + if (attr instanceof MpUnReachNlri) { + List nlri = ((MpUnReachNlri) attr).mpUnReachNlri(); + callRemove(this, nlri); + } + } + } + + /** + * Updates NLRI identifier node in a tree separately based on afi and safi. + * + * @param peerImpl BGP peer instance + * @param nlri MpReachNlri path attribute + * @param pathAttr list of BGP path attributes + * @throws BgpParseException throws exception + */ + public void callAdd(BgpPeerImpl peerImpl, List nlri, List pathAttr) + throws BgpParseException { + ListIterator listIterator = nlri.listIterator(); + while (listIterator.hasNext()) { + BgpLSNlri nlriInfo = listIterator.next(); + if (nlriInfo instanceof BgpNodeLSNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + bgplocalRIB.add(sessionInfo(), nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details, + ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + bgplocalRIB.add(sessionInfo(), nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details, + ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { + PathAttrNlriDetails details = setPathAttrDetails(nlriInfo, pathAttr); + if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.add(nlriInfo, details); + bgplocalRIB.add(sessionInfo(), nlriInfo, details); + } else { + vpnAdjRib.addVpn(nlriInfo, details, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.add(sessionInfo(), nlriInfo, details, + ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } + } + } + + /** + * Sets BGP path attribute and NLRI details. + * + * @param nlriInfo MpReachNlri path attribute + * @param pathAttr list of BGP path attributes + * @return details object of PathAttrNlriDetails + * @throws BgpParseException throw exception + */ + public PathAttrNlriDetails setPathAttrDetails(BgpLSNlri nlriInfo, List pathAttr) + throws BgpParseException { + PathAttrNlriDetails details = new PathAttrNlriDetails(); + details.setProtocolID(nlriInfo.getProtocolId()); + details.setIdentifier(nlriInfo.getIdentifier()); + details.setPathAttribute(pathAttr); + return details; + } + + /** + * Removes NLRI identifier node in a tree separately based on afi and safi. + * + * @param peerImpl BGP peer instance + * @param nlri NLRI information + */ + public void callRemove(BgpPeerImpl peerImpl, List nlri) { + ListIterator listIterator = nlri.listIterator(); + while (listIterator.hasNext()) { + BgpLSNlri nlriInfo = listIterator.next(); + if (nlriInfo instanceof BgpNodeLSNlriVer4) { + if (!((BgpNodeLSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + bgplocalRIB.delete(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.delete(nlriInfo, ((BgpNodeLSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpLinkLsNlriVer4) { + if (!((BgpLinkLsNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + bgplocalRIB.delete(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.delete(nlriInfo, ((BgpLinkLsNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } else if (nlriInfo instanceof BgpPrefixIPv4LSNlriVer4) { + if (!((BgpPrefixIPv4LSNlriVer4) nlriInfo).isVpnPresent()) { + adjRib.remove(nlriInfo); + bgplocalRIB.delete(nlriInfo); + } else { + vpnAdjRib.removeVpn(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + bgplocalRIBVpn.delete(nlriInfo, ((BgpPrefixIPv4LSNlriVer4) nlriInfo).getRouteDistinguisher()); + } + } + } + } + + /** + * Return the adjacency RIB-IN. + * + * @return adjRib the adjacency RIB-IN + */ + public AdjRibIn adjRib() { + return adjRib; + } + + /** + * Return the adjacency RIB-IN with VPN. + * + * @return vpnAdjRib the adjacency RIB-IN with VPN + */ + public VpnAdjRibIn vpnAdjRib() { + return vpnAdjRib; + } + + /** + * Update localRIB on peer disconnect. + * + */ + public void updateLocalRIBOnPeerDisconnect() { + BgpLocalRibImpl localRib = (BgpLocalRibImpl) bgplocalRIB; + BgpLocalRibImpl localRibVpn = (BgpLocalRibImpl) bgplocalRIBVpn; + + localRib.localRIBUpdate(adjacencyRib()); + localRibVpn.localRIBUpdate(vpnAdjacencyRib()); + } + + // ************************ + // Channel related + // ************************ + + @Override + public final void disconnectPeer() { + this.channel.close(); + } + + @Override + public final void sendMessage(BgpMessage m) { + log.debug("Sending message to {}", channel.getRemoteAddress()); + try { + channel.write(Collections.singletonList(m)); + this.pktStats.addOutPacket(); + } catch (RejectedExecutionException e) { + log.warn(e.getMessage()); + if (!e.getMessage().contains(SHUTDOWN_MSG)) { + throw e; + } + } + } + + @Override + public final void sendMessage(List msgs) { + try { + channel.write(msgs); + this.pktStats.addOutPacket(msgs.size()); + } catch (RejectedExecutionException e) { + log.warn(e.getMessage()); + if (!e.getMessage().contains(SHUTDOWN_MSG)) { + throw e; + } + } + } + + @Override + public final boolean isConnected() { + return this.connected; + } + + @Override + public final void setConnected(boolean connected) { + this.connected = connected; + }; + + @Override + public final void setChannel(Channel channel) { + this.channel = channel; + final SocketAddress address = channel.getRemoteAddress(); + if (address instanceof InetSocketAddress) { + final InetSocketAddress inetAddress = (InetSocketAddress) address; + final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress()); + if (ipAddress.isIp4()) { + channelId = ipAddress.toString() + ':' + inetAddress.getPort(); + } else { + channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort(); + } + } + }; + + @Override + public final Channel getChannel() { + return this.channel; + }; + + @Override + public String channelId() { + return channelId; + } + + @Override + public BgpFactory factory() { + return BgpFactories.getFactory(sessionInfo.remoteBgpVersion()); + } + + @Override + public boolean isHandshakeComplete() { + return isHandShakeComplete; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).omitNullValues() + .add("channel", channelId()) + .add("BgpId", sessionInfo().remoteBgpId()).toString(); + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java new file mode 100755 index 00000000..28e1041c --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPipelineFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.handler.timeout.ReadTimeoutHandler; +import org.jboss.netty.util.ExternalResourceReleasable; +import org.jboss.netty.util.HashedWheelTimer; +import org.jboss.netty.util.Timer; +import org.onosproject.bgp.controller.BgpController; + +/** + * Creates a ChannelPipeline for a server-side bgp channel. + */ +public class BgpPipelineFactory + implements ChannelPipelineFactory, ExternalResourceReleasable { + + static final Timer TIMER = new HashedWheelTimer(); + protected ReadTimeoutHandler readTimeoutHandler; + private boolean isBgpServ; + private BgpController bgpController; + + /** + * Constructor to initialize the values. + * + * @param bgpController parent controller + * @param isBgpServ if it is a server or remote peer + */ + public BgpPipelineFactory(BgpController bgpController, boolean isBgpServ) { + super(); + this.isBgpServ = isBgpServ; + this.bgpController = bgpController; + /* hold time */ + this.readTimeoutHandler = new ReadTimeoutHandler(TIMER, bgpController.getConfig().getHoldTime()); + } + + @Override + public ChannelPipeline getPipeline() throws Exception { + BgpChannelHandler handler = new BgpChannelHandler(bgpController); + + ChannelPipeline pipeline = Channels.pipeline(); + pipeline.addLast("bgpmessagedecoder", new BgpMessageDecoder()); + pipeline.addLast("bgpmessageencoder", new BgpMessageEncoder()); + pipeline.addLast("holdTime", readTimeoutHandler); + if (isBgpServ) { + pipeline.addLast("PassiveHandler", handler); + } else { + pipeline.addLast("ActiveHandler", handler); + } + + return pipeline; + } + + @Override + public void releaseExternalResources() { + TIMER.stop(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java new file mode 100644 index 00000000..d3065f43 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSelectionAlgo.java @@ -0,0 +1,242 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; + +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgpio.types.Origin.ORIGINTYPE; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of BGP best path Selection process. + */ +public final class BgpSelectionAlgo implements Comparator { + private static final Logger log = LoggerFactory.getLogger(BgpSelectionAlgo.class); + LocalPref obj1LocPref = null; + AsPath obj1Aspath = null; + Origin obj1Origin = null; + Med obj1Med = null; + LocalPref obj2LocPref = null; + AsPath obj2Aspath = null; + Origin obj2Origin = null; + Med obj2Med = null; + + @Override + public int compare(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { + if (pathNlriDetails1 == null) { + return -1; + } + if (pathNlriDetails2 == null) { + return 1; + } + if (pathNlriDetails1.equals(pathNlriDetails2)) { + return 0; + } + + List o1 = pathNlriDetails1.localRibNlridetails().pathAttributes(); + List o2 = pathNlriDetails2.localRibNlridetails().pathAttributes(); + ListIterator listIteratorObj1 = o1.listIterator(); + ListIterator listIteratorObj2 = o2.listIterator(); + storeAttr(listIteratorObj1, listIteratorObj2); + + // prefer attribute with higher local preference + if (obj1LocPref != null || obj2LocPref != null && (obj1LocPref != null && !obj1LocPref.equals(obj2LocPref))) { + return compareLocalPref(obj1LocPref, obj2LocPref); + } + + // prefer attribute with shortest Aspath + if (!obj1Aspath.equals(obj2Aspath)) { + Integer obj1Size = countASSize(obj1Aspath); + Integer obj2Size = countASSize(obj2Aspath); + if (obj1Size != obj2Size) { + return compareAsPath(obj1Size, obj2Size); + } + } + + // prefer attribute with lowest origin type + if (!obj1Origin.equals(obj2Origin)) { + return compareOrigin(obj1Origin, obj2Origin); + } + + // prefer attribute with lowest MED + if (obj1Med != null || obj2Med != null && (obj1Med != null && !obj1Med.equals(obj2Med))) { + return compareMed(obj1Med, obj2Med); + } + + if ((pathNlriDetails1 != null || pathNlriDetails2 != null) && (pathNlriDetails1 != null && !pathNlriDetails1 + .equals(pathNlriDetails2))) { + return comparePeerDetails(pathNlriDetails1, pathNlriDetails2); + } + return 0; + } + + /** + * Compares local preference of two objects and returns object with higher preference. + * + * @param obj1LocPref local preference object1 + * @param obj2LocPref local preference object2 + * @return object with higher preference + */ + int compareLocalPref(LocalPref obj1LocPref, LocalPref obj2LocPref) { + return ((Integer) (obj1LocPref.localPref())).compareTo((Integer) (obj2LocPref.localPref())); + } + + /** + * Compares AsPath of two objects and returns object with shortest AsPath. + * + * @param obj1Size object1 AS count + * @param obj2Size object2 AS count + * @return + */ + int compareAsPath(Integer obj1Size, Integer obj2Size) { + return obj1Size.compareTo(obj2Size); + } + + /** + * Compare Origin of two objects and returns object with lowest origin value. + * + * @param obj1Origin Origin object1 + * @param obj2Origin Origin object1 + * @return object with lowest origin value + */ + int compareOrigin(Origin obj1Origin, Origin obj2Origin) { + if (obj1Origin.origin() == ORIGINTYPE.IGP) { + return 1; + } + if (obj2Origin.origin() == ORIGINTYPE.IGP) { + return -1; + } + if (obj1Origin.origin() == ORIGINTYPE.EGP) { + return 1; + } else { + return -1; + } + } + + /** + * Compare Med of two objects and returns object with lowestMed value. + * + * @param obj1Med Med object1 + * @param obj2Med Med object2 + * @return returns object with lowestMed value + */ + int compareMed(Med obj1Med, Med obj2Med) { + return ((Integer) (obj2Med.med())).compareTo((Integer) (obj1Med.med())); + } + + /** + * Compares EBGP over IBGP, BGP identifier value and peer address. + * + * @param pathNlriDetails1 PathAttrNlriDetailsLocalRib object1 + * @param pathNlriDetails2 PathAttrNlriDetailsLocalRib object2 + * @return object which as EBGP over IBGP, lowest BGP identifier value and lowest peer address + */ + int comparePeerDetails(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { + // consider EBGP over IBGP + if (pathNlriDetails1.isLocalRibIbgpSession() != pathNlriDetails2.isLocalRibIbgpSession()) { + if (pathNlriDetails1 == null || pathNlriDetails1.isLocalRibIbgpSession()) { + return -1; + } + if (pathNlriDetails2 == null || pathNlriDetails2.isLocalRibIbgpSession()) { + return 1; + } + } + // prefer lowest BGP identifier value. + if (pathNlriDetails1.localRibIdentifier() != pathNlriDetails2.localRibIdentifier()) { + return ((Integer) pathNlriDetails2.localRibIdentifier()) + .compareTo(pathNlriDetails1.localRibIdentifier()); + } + //prefer lowest peer address + if (pathNlriDetails1.localRibIpAddress() != pathNlriDetails2.localRibIpAddress()) { + return pathNlriDetails2.localRibIpAddress().compareTo(pathNlriDetails1.localRibIpAddress()); + } + return 0; + } + + /** + * Returns ASes count of AsPath attribute , if AS_SET is present then count as 1. + * + * @param aspath object of AsPath + * @return count of ASes + */ + Integer countASSize(AsPath aspath) { + boolean isASSet = false; + int count = 0; + if (!aspath.asPathSet().isEmpty()) { + isASSet = true; + } + if (!aspath.asPathSeq().isEmpty()) { + count = aspath.asPathSeq().size(); + } + return isASSet ? ++count : count; + } + + /** + * Stores BGP basic attributes of two objects. + * + * @param listIteratorObj1 list iterator of object1 + * @param listIteratorObj2 list iterator of object2 + */ + void storeAttr(ListIterator listIteratorObj1, ListIterator listIteratorObj2) { + while (listIteratorObj1.hasNext()) { + BgpValueType pathAttributeObj1 = listIteratorObj1.next(); + switch (pathAttributeObj1.getType()) { + case LocalPref.LOCAL_PREF_TYPE: + obj1LocPref = (LocalPref) pathAttributeObj1; + break; + case AsPath.ASPATH_TYPE: + obj1Aspath = (AsPath) pathAttributeObj1; + break; + case Origin.ORIGIN_TYPE: + obj1Origin = (Origin) pathAttributeObj1; + break; + case Med.MED_TYPE: + obj1Med = (Med) pathAttributeObj1; + break; + default: + log.debug("Got other type, Not required: " + pathAttributeObj1.getType()); + } + } + while (listIteratorObj2.hasNext()) { + BgpValueType pathAttributeObj2 = listIteratorObj2.next(); + switch (pathAttributeObj2.getType()) { + case LocalPref.LOCAL_PREF_TYPE: + obj2LocPref = (LocalPref) pathAttributeObj2; + break; + case AsPath.ASPATH_TYPE: + obj2Aspath = (AsPath) pathAttributeObj2; + break; + case Origin.ORIGIN_TYPE: + obj2Origin = (Origin) pathAttributeObj2; + break; + case Med.MED_TYPE: + obj2Med = (Med) pathAttributeObj2; + break; + default: + log.debug("Got other type, Not required: " + pathAttributeObj2.getType()); + } + } + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java new file mode 100755 index 00000000..33623dc2 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpSessionInfoImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import org.onosproject.bgp.controller.BgpId; +import org.onosproject.bgp.controller.BgpSessionInfo; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class maintains BGP peer session info. + */ +public class BgpSessionInfoImpl implements BgpSessionInfo { + + protected final Logger log = LoggerFactory.getLogger(BgpSessionInfoImpl.class); + private BgpId remoteBgpId; + private BgpVersion remoteBgpVersion; + private long remoteBgpASNum; + private short remoteBgpholdTime; + private int remoteBgpIdentifier; + private short negotiatedholdTime; + private boolean isIbgpSession; + + /** + * Initialize session info. + * + *@param remoteBgpId remote peer id + *@param remoteBgpVersion remote peer version + *@param remoteBgpASNum remote peer AS number + *@param remoteBgpholdTime remote peer hold time + *@param remoteBgpIdentifier remote peer identifier + *@param negotiatedholdTime negotiated hold time + *@param isIbgpSession session type ibgp/ebgp + */ + public BgpSessionInfoImpl(BgpId remoteBgpId, BgpVersion remoteBgpVersion, long remoteBgpASNum, + short remoteBgpholdTime, int remoteBgpIdentifier, short negotiatedholdTime, + boolean isIbgpSession) { + this.remoteBgpId = remoteBgpId; + this.remoteBgpVersion = remoteBgpVersion; + this.remoteBgpASNum = remoteBgpASNum; + this.remoteBgpholdTime = remoteBgpholdTime; + this.remoteBgpIdentifier = remoteBgpIdentifier; + this.negotiatedholdTime = negotiatedholdTime; + this.isIbgpSession = isIbgpSession; + } + + @Override + public boolean isIbgpSession() { + return isIbgpSession; + } + + @Override + public short negotiatedholdTime() { + return negotiatedholdTime; + } + + @Override + public BgpId remoteBgpId() { + return remoteBgpId; + } + + @Override + public BgpVersion remoteBgpVersion() { + return remoteBgpVersion; + } + + @Override + public long remoteBgpASNum() { + return remoteBgpASNum; + } + + @Override + public short remoteBgpHoldTime() { + return remoteBgpholdTime; + } + + @Override + public int remoteBgpIdentifier() { + return remoteBgpIdentifier; + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java new file mode 100755 index 00000000..f02cee8a --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/Controller.java @@ -0,0 +1,254 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp.controller.impl; + +import static org.onlab.util.Tools.groupedThreads; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.group.ChannelGroup; +import org.jboss.netty.channel.group.DefaultChannelGroup; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; +import org.onosproject.bgp.controller.BgpController; +import org.onosproject.bgpio.protocol.BgpFactories; +import org.onosproject.bgpio.protocol.BgpFactory; +import org.onosproject.bgpio.protocol.BgpVersion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The main controller class. Handles all setup and network listeners - Distributed ownership control of bgp peer + * through IControllerRegistryService + */ +public class Controller { + + private static final Logger log = LoggerFactory.getLogger(Controller.class); + + private static final BgpFactory FACTORY4 = BgpFactories.getFactory(BgpVersion.BGP_4); + + private ChannelGroup cg; + public Channel serverChannel; + + // Configuration options + private static final short BGP_PORT_NUM = 179; + private static final short PORT_NUM_ZERO = 0; + private static boolean isPortNumSet = false; + private final int workerThreads = 16; + private final int peerWorkerThreads = 16; + + // Start time of the controller + private long systemStartTime; + + private NioServerSocketChannelFactory serverExecFactory; + private NioClientSocketChannelFactory peerExecFactory; + private static ClientBootstrap peerBootstrap; + private BgpController bgpController; + + // Perf. related configuration + private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; + + /** + * Constructor to initialize the values. + * + * @param bgpController bgp controller instance + */ + public Controller(BgpController bgpController) { + this.bgpController = bgpController; + } + + /** + * Returns factory version for processing BGP messages. + * + * @return instance of factory version + */ + static BgpFactory getBgpMessageFactory4() { + return FACTORY4; + } + + /** + * To get system start time. + * + * @return system start time in milliseconds + */ + public long getSystemStartTime() { + return (this.systemStartTime); + } + + /** + * Tell controller that we're ready to accept bgp peer connections. + */ + public void run() { + + try { + + peerBootstrap = createPeerBootStrap(); + + peerBootstrap.setOption("reuseAddr", true); + peerBootstrap.setOption("child.keepAlive", true); + peerBootstrap.setOption("child.tcpNoDelay", true); + peerBootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); + + final ServerBootstrap bootstrap = createServerBootStrap(); + + bootstrap.setOption("reuseAddr", true); + bootstrap.setOption("child.keepAlive", true); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); + + ChannelPipelineFactory pfact = new BgpPipelineFactory(bgpController, true); + + bootstrap.setPipelineFactory(pfact); + InetSocketAddress sa = new InetSocketAddress(getBgpPortNum()); + cg = new DefaultChannelGroup(); + serverChannel = bootstrap.bind(sa); + cg.add(serverChannel); + log.info("Listening for Peer connection on {}", sa); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Creates server boot strap. + * + * @return ServerBootStrap + */ + private ServerBootstrap createServerBootStrap() { + + if (workerThreads == 0) { + serverExecFactory = new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d"))); + return new ServerBootstrap(serverExecFactory); + } else { + serverExecFactory = new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")), + workerThreads); + return new ServerBootstrap(serverExecFactory); + } + } + + /** + * Creates peer boot strap. + * + * @return ClientBootstrap + */ + private ClientBootstrap createPeerBootStrap() { + + if (peerWorkerThreads == 0) { + peerExecFactory = new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d"))); + return new ClientBootstrap(peerExecFactory); + } else { + peerExecFactory = new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "boss-%d")), + Executors.newCachedThreadPool(groupedThreads("onos/bgp", "worker-%d")), + peerWorkerThreads); + return new ClientBootstrap(peerExecFactory); + } + } + + /** + * Gets peer bootstrap. + * + * @return peer bootstrap + */ + public static ClientBootstrap peerBootstrap() { + return peerBootstrap; + } + + /** + * Initialize internal data structures. + */ + public void init() { + // These data structures are initialized here because other + // module's startUp() might be called before ours + this.systemStartTime = System.currentTimeMillis(); + } + + /** + * Gets run time memory. + * + * @return m run time memory + */ + public Map getMemory() { + Map m = new HashMap<>(); + Runtime runtime = Runtime.getRuntime(); + m.put("total", runtime.totalMemory()); + m.put("free", runtime.freeMemory()); + return m; + } + + /** + * Gets UP time. + * + * @return UP time + */ + public Long getUptime() { + RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); + return rb.getUptime(); + } + + /** + * Starts the BGP controller. + */ + public void start() { + log.info("Started"); + this.init(); + this.run(); + } + + /** + * Stops the BGP controller. + */ + public void stop() { + log.info("Stopped"); + serverExecFactory.shutdown(); + peerExecFactory.shutdown(); + cg.close(); + } + + /** + * Returns port number. + * + * @return port number + */ + public static short getBgpPortNum() { + if (isPortNumSet) { + return PORT_NUM_ZERO; + } + return BGP_PORT_NUM; + } + + /** + * sets the isPortNumSet as true. + */ + public void setBgpPortNum() { + isPortNumSet = true; + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java new file mode 100644 index 00000000..8a9ea91c --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/VpnAdjRibIn.java @@ -0,0 +1,209 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.bgp.controller.impl; + +import java.util.Map; +import java.util.TreeMap; + +import org.onosproject.bgpio.protocol.BgpLSNlri; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; +import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.types.RouteDistinguisher; + +import com.google.common.base.MoreObjects; + +/** + * Implementation of Adj-RIB-In with VPN for each peer. + */ +public class VpnAdjRibIn { + private Map nodeTree = new TreeMap<>(); + private Map linkTree = new TreeMap<>(); + private Map prefixTree = new TreeMap<>(); + + private Map> vpnNodeTree + = new TreeMap<>(); + private Map> vpnLinkTree + = new TreeMap<>(); + private Map> vpnPrefixTree + = new TreeMap<>(); + /** + * Returns the adjacency node. + * + * @return node adjacency RIB node + */ + public Map nodeTree() { + return nodeTree; + } + + /** + * Returns the adjacency link. + * + * @return link adjacency RIB node + */ + public Map linkTree() { + return linkTree; + } + + /** + * Returns the adjacency prefix. + * + * @return prefix adjacency RIB node + */ + public Map prefixTree() { + return prefixTree; + } + + /** + * Returns the adjacency vpnNode. + * + * @return vpnNode adjacency RIB node + */ + public Map> vpnNodeTree() { + return vpnNodeTree; + } + + /** + * Returns the adjacency vpnLink. + * + * @return vpnLink adjacency RIB node + */ + public Map> vpnLinkTree() { + return vpnLinkTree; + } + + /** + * Returns the adjacency vpnPrefix. + * + * @return vpnPrefix adjacency RIB node + */ + public Map> vpnPrefixTree() { + return vpnPrefixTree; + } + + /** + * Update vpn nlri identifier into the tree if nlri identifier exists in tree otherwise add this to the tree. + * + * @param nlri NLRI info + * @param details has pathattribute , protocolID and identifier + */ + public void add(BgpLSNlri nlri, PathAttrNlriDetails details) { + if (nlri instanceof BgpNodeLSNlriVer4) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.replace(nodeLSIdentifier, details); + } else { + nodeTree.put(nodeLSIdentifier, details); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.replace(linkLSIdentifier, details); + } else { + linkTree.put(linkLSIdentifier, details); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.replace(prefixIdentifier, details); + } else { + prefixTree.put(prefixIdentifier, details); + } + } + } + + /** + * Update nlri identifier mapped with route distinguisher if it exists in tree otherwise add nlri infomation mapped + * to respective route distinguisher in tree. + * + * @param nlri NLRI info + * @param details has pathattribute , protocolID and identifier + * @param routeDistinguisher unique for for each vpn + */ + public void addVpn(BgpLSNlri nlri, PathAttrNlriDetails details, RouteDistinguisher routeDistinguisher) { + add(nlri, details); + if (nlri instanceof BgpNodeLSNlriVer4) { + if (!vpnNodeTree.containsKey(routeDistinguisher)) { + vpnNodeTree.put(routeDistinguisher, nodeTree); + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (!vpnLinkTree.containsKey(routeDistinguisher)) { + vpnLinkTree.put(routeDistinguisher, linkTree); + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (!vpnPrefixTree.containsKey(routeDistinguisher)) { + vpnPrefixTree.put(routeDistinguisher, prefixTree); + } + } + } + + /** + * Removes vpn nlri identifier mapped to route distinguisher if it exists in tree. + * + * @param nlri NLRI Info + * @param routeDistinguisher unique for for each vpn + */ + public void removeVpn(BgpLSNlri nlri, RouteDistinguisher routeDistinguisher) { + if (nlri instanceof BgpNodeLSNlriVer4) { + if (vpnNodeTree.containsKey(routeDistinguisher)) { + BgpNodeLSIdentifier nodeLSIdentifier = ((BgpNodeLSNlriVer4) nlri).getLocalNodeDescriptors(); + if (nodeTree.containsKey(nodeLSIdentifier)) { + nodeTree.remove(nodeLSIdentifier); + } + if ((vpnNodeTree.get(routeDistinguisher)).isEmpty()) { + vpnNodeTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpLinkLsNlriVer4) { + if (vpnLinkTree.containsKey(routeDistinguisher)) { + BgpLinkLSIdentifier linkLSIdentifier = ((BgpLinkLsNlriVer4) nlri).getLinkIdentifier(); + if (linkTree.containsKey(linkLSIdentifier)) { + linkTree.remove(linkLSIdentifier); + } + if ((vpnLinkTree.get(routeDistinguisher)).isEmpty()) { + vpnLinkTree.remove(routeDistinguisher); + } + } + } else if (nlri instanceof BgpPrefixIPv4LSNlriVer4) { + if (vpnPrefixTree.containsKey(routeDistinguisher)) { + BgpPrefixLSIdentifier prefixIdentifier = ((BgpPrefixIPv4LSNlriVer4) nlri).getPrefixIdentifier(); + if (prefixTree.containsKey(prefixIdentifier)) { + prefixTree.remove(prefixIdentifier); + } + if ((vpnPrefixTree.get(routeDistinguisher)).isEmpty()) { + vpnPrefixTree.remove(routeDistinguisher); + } + } + } + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues().add("nodeTree", nodeTree) + .add("linkTree", linkTree) + .add("prefixTree", prefixTree) + .add("vpnNodeTree", vpnNodeTree) + .add("vpnLinkTree", vpnLinkTree) + .add("vpnPrefixTree", vpnPrefixTree) + .toString(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java new file mode 100755 index 00000000..fd4e9506 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of the BGP controller IO subsystem. + */ +package org.onosproject.bgp.controller.impl; diff --git a/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java new file mode 100755 index 00000000..7549b922 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpControllerImplTest.java @@ -0,0 +1,322 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import com.google.common.net.InetAddresses; +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import org.onlab.junit.TestUtils; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.LinkedList; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.onosproject.bgp.controller.BgpCfg; +import org.onosproject.bgp.controller.impl.BgpControllerImpl; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv; +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv; + +/** + * Test case for BGPControllerImpl. + */ +public class BgpControllerImplTest { + + protected static final Logger log = LoggerFactory + .getLogger(BgpControllerImplTest.class); + + private static final String IP_LOOPBACK_ID1 = "127.0.0.1"; + + private static final int MESSAGE_TIMEOUT_MS = 3000; + public byte version; + public short asNumber; + public short holdTime; + public int bgpId = InetAddresses.coerceToInteger(InetAddresses.forString(IP_LOOPBACK_ID1)); + public boolean isLargeAsCapabilitySet = false; + public LinkedList capabilityTlv = new LinkedList<>(); + + @Before + public void setUp() throws Exception { + peer1 = new BgpPeerTest(version, asNumber, + holdTime, bgpId, isLargeAsCapabilitySet, + capabilityTlv); + + bgpControllerImpl = new BgpControllerImpl(); + + // NOTE: We use port 0 to bind on any available port + bgpControllerImpl.controller().setBgpPortNum(); + bgpControllerImpl.activate(); + + Channel serverChannel = TestUtils.getField(bgpControllerImpl.controller(), + "serverChannel"); + SocketAddress socketAddress = serverChannel.getLocalAddress(); + InetSocketAddress inetSocketAddress = + (InetSocketAddress) socketAddress; + InetAddress connectToAddress = InetAddresses.forString("127.0.0.1"); + connectToSocket = new InetSocketAddress(connectToAddress, + inetSocketAddress.getPort()); + + bgpControllerImpl.getConfig().setRouterId("1.1.1.1"); + bgpControllerImpl.getConfig().setAsNumber(200); + bgpControllerImpl.getConfig().setHoldTime((short) 120); + bgpControllerImpl.getConfig().setState(BgpCfg.State.IP_AS_CONFIGURED); + + bgpControllerImpl.getConfig().addPeer("127.0.0.1", 200); + } + + @After + public void tearDown() throws Exception { + bgpControllerImpl.deactivate(); + bgpControllerImpl = null; + } + + private BgpControllerImpl bgpControllerImpl; + + BgpPeerTest peer1; + + // The socket that the remote peers should connect to + private InetSocketAddress connectToSocket; + + @Test + public void bgpOpenMessageTest1() throws InterruptedException { + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest2() throws InterruptedException { + // Open message with as number which is not configured at peer + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 500; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await(MESSAGE_TIMEOUT_MS, TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await(MESSAGE_TIMEOUT_MS, TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(false)); + } + + @Test + public void bgpOpenMessageTest3() throws InterruptedException { + // Open message with invalid hold time value + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 1; + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest4() throws InterruptedException { + // Open message with invalid as number + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(766545); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest5() throws InterruptedException { + // Open message with LS capability + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest6() throws InterruptedException { + // Open message with as4 capability + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + bgpControllerImpl.getConfig().setLargeASCapability(true); + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + + result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + @Test + public void bgpOpenMessageTest7() throws InterruptedException { + // Open message with both LS capability and as4 capability + short afi = 16388; + byte res = 0; + byte safi = 71; + peer1.peerChannelHandler.asNumber = 200; + peer1.peerChannelHandler.version = 4; + peer1.peerChannelHandler.holdTime = 120; + + peer1.peerChannelHandler.isLargeAsCapabilitySet = true; + bgpControllerImpl.getConfig().setLargeASCapability(true); + BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv); + + bgpControllerImpl.getConfig().setLsCapability(true); + BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi); + peer1.peerChannelHandler.capabilityTlv.add(tempTlv1); + peer1.connect(connectToSocket); + + boolean result; + result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await( + MESSAGE_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + assertThat(result, is(true)); + } + + /** + * A class to capture the state for a BGP peer. + */ + private final class BgpPeerTest { + private ClientBootstrap peerBootstrap; + private BgpPeerFrameDecoderTest peerFrameDecoder = + new BgpPeerFrameDecoderTest(); + private BgpPeerChannelHandlerTest peerChannelHandler; + + private BgpPeerTest(byte version, short asNumber, + short holdTime, int bgpId, boolean isLargeAsCapabilitySet, + LinkedList capabilityTlv) { + peerChannelHandler = new BgpPeerChannelHandlerTest(version, + asNumber, holdTime, bgpId, isLargeAsCapabilitySet, capabilityTlv); + } + + /** + * Starts the BGP peer. + * + * @param connectToSocket the socket to connect to + */ + private void connect(InetSocketAddress connectToSocket) + throws InterruptedException { + + ChannelFactory channelFactory = + new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + ChannelPipelineFactory pipelineFactory = () -> { + ChannelPipeline pipeline = Channels.pipeline(); + pipeline.addLast("BgpPeerFrameDecoderTest", + peerFrameDecoder); + pipeline.addLast("BgpPeerChannelHandlerTest", + peerChannelHandler); + return pipeline; + }; + + peerBootstrap = new ClientBootstrap(channelFactory); + peerBootstrap.setOption("child.keepAlive", true); + peerBootstrap.setOption("child.tcpNoDelay", true); + peerBootstrap.setPipelineFactory(pipelineFactory); + peerBootstrap.connect(connectToSocket); + } + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java new file mode 100755 index 00000000..26ed36d8 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerChannelHandlerTest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import java.util.LinkedList; +import java.util.concurrent.TimeUnit; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.onosproject.bgpio.protocol.ver4.BgpKeepaliveMsgVer4; +import org.onosproject.bgpio.protocol.ver4.BgpOpenMsgVer4; +import org.onosproject.bgpio.types.BgpHeader; +import org.onosproject.bgpio.types.BgpValueType; + +public class BgpPeerChannelHandlerTest extends SimpleChannelHandler { + public static final int OPEN_MSG_MINIMUM_LENGTH = 29; + public static final byte[] MARKER = new byte[] {(byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff}; + public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER, + (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01); + LinkedList capabilityTlv = new LinkedList<>(); + public byte version; + public short asNumber; + public short holdTime; + public int bgpId; + public boolean isLargeAsCapabilitySet; + + final BgpOpenMsgVer4 openMessage = new BgpOpenMsgVer4(); + ChannelHandlerContext savedCtx; + + /** + * Constructor to initialize all variables of BGP Open message. + * + * @param version BGP version in open message + * @param asNumber AS number in open message + * @param holdTime hold time in open message + * @param bgpId BGP identifier in open message + * @param capabilityTlv capabilities in open message + */ + public BgpPeerChannelHandlerTest(byte version, + short asNumber, + short holdTime, + int bgpId, + boolean isLargeAsCapabilitySet, + LinkedList capabilityTlv) { + this.version = version; + this.asNumber = asNumber; + this.holdTime = holdTime; + this.bgpId = bgpId; + this.isLargeAsCapabilitySet = isLargeAsCapabilitySet; + this.capabilityTlv = capabilityTlv; + } + + /** + * closes the channel. + */ + void closeChannel() { + savedCtx.getChannel().close(); + } + + @Override + public void channelConnected(ChannelHandlerContext ctx, + ChannelStateEvent channelEvent) throws InterruptedException { + this.savedCtx = ctx; + + BgpOpenMsgVer4 openMsg = new BgpOpenMsgVer4(DEFAULT_OPEN_HEADER, + this.version, + this.asNumber, + this.holdTime, + this.bgpId, + this.capabilityTlv); + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + openMsg.writeTo(buffer); + ctx.getChannel().write(buffer); + + TimeUnit.MILLISECONDS.sleep(100); + + BgpKeepaliveMsgVer4 keepaliveMsg = new BgpKeepaliveMsgVer4(); + ChannelBuffer buffer1 = ChannelBuffers.dynamicBuffer(); + keepaliveMsg.writeTo(buffer1); + ctx.getChannel().write(buffer1); + } + + @Override + public void channelDisconnected(ChannelHandlerContext ctx, + ChannelStateEvent channelEvent) { + //Do Nothing + } +} diff --git a/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java new file mode 100755 index 00000000..7767053f --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java @@ -0,0 +1,168 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.bgp; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.frame.FrameDecoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.concurrent.CountDownLatch; + +/** + * Class to decode the message received. + */ +public class BgpPeerFrameDecoderTest extends FrameDecoder { + static final byte OPEN_MSG_TYPE = 0x1; + static final byte KEEPALIVE_MSG_TYPE = 0x4; + static final byte UPDATE_MSG_TYPE = 0x2; + static final byte NOTIFICATION_MSG_TYPE = 0x3; + static final int MINIMUM_COMMON_HEADER_LENGTH = 19; + static final int MINIMUM_OPEN_MSG_LENGTH = 29; + static final int MINIMUM_HEADER_MARKER_LENGTH = 16; + static final int HEADER_AND_MSG_LEN = 18; + + protected static final Logger log = LoggerFactory + .getLogger(BgpPeerFrameDecoderTest.class); + final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1); + final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1); + final CountDownLatch receivedNotificationMessageLatch = new CountDownLatch(1); + + @Override + protected Object decode(ChannelHandlerContext ctx, + Channel channel, + ChannelBuffer cb) throws Exception { + + if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { + log.debug("Error: Packet length is less then minimum length"); + return null; + } + + byte[] marker = new byte[MINIMUM_HEADER_MARKER_LENGTH]; + cb.readBytes(marker); + for (int i = 0; i < marker.length; i++) { + if (marker[i] != (byte) 0xff) { + log.debug("Error: Marker must be set all ones"); + ctx.getChannel().close(); + return null; + } + } + + short length = cb.readShort(); + if (length < MINIMUM_COMMON_HEADER_LENGTH) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return null; + } + + if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return null; + } + + byte type = cb.readByte(); + int len = length - MINIMUM_COMMON_HEADER_LENGTH; + + ChannelBuffer message = cb.readBytes(len); + + switch (type) { + case OPEN_MSG_TYPE: + processBgpOpen(ctx, message); + break; + case UPDATE_MSG_TYPE: + break; + case NOTIFICATION_MSG_TYPE: + processBgpNotification(ctx, message); + break; + case KEEPALIVE_MSG_TYPE: + processBgpKeepalive(ctx, message); + break; + default: + ctx.getChannel().close(); + return null; + } + + return null; + } + + /** + * Processes BGP open message. + * + * @param ctx Channel handler context + * @param message open message + */ + private void processBgpOpen(ChannelHandlerContext ctx, + ChannelBuffer message) { + int minLength = + MINIMUM_OPEN_MSG_LENGTH - MINIMUM_COMMON_HEADER_LENGTH; + if (message.readableBytes() < minLength) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return; + } + + message.readByte(); // read version + message.readShort(); // read AS number + message.readShort(); // read Hold timer + message.readInt(); // read BGP Identifier + // Optional Parameters + int optParamLen = message.readUnsignedByte(); + if (message.readableBytes() < optParamLen) { + log.debug("Error: Bad message length"); + ctx.getChannel().close(); + return; + } + message.readBytes(optParamLen); + + // Open message received + receivedOpenMessageLatch.countDown(); + } + + /** + * Processes BGP keepalive message. + * + * @param ctx Channel handler context + * @param message keepalive message + */ + private void processBgpKeepalive(ChannelHandlerContext ctx, + ChannelBuffer message) { + + // Keepalive message received + receivedKeepaliveMessageLatch.countDown(); + } + + /** + * Processes BGP notification message. + * + * @param ctx Channel handler context + * @param message notification message + */ + private void processBgpNotification(ChannelHandlerContext ctx, + ChannelBuffer message) { + byte[] data; + message.readByte(); //read error code + message.readByte(); // read error sub code + if (message.readableBytes() > 0) { + data = new byte[message.readableBytes()]; + message.readBytes(data, 0, message.readableBytes()); + } + + // Notification message received + receivedNotificationMessageLatch.countDown(); + } +} \ No newline at end of file diff --git a/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java new file mode 100644 index 00000000..7c0fa417 --- /dev/null +++ b/framework/src/onos/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpSelectionAlgoTest.java @@ -0,0 +1,595 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.controller.impl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.util.LinkedList; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpAddress.Version; +import org.onosproject.bgpio.exceptions.BgpParseException; +import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; +import org.onosproject.bgpio.types.AsPath; +import org.onosproject.bgpio.types.BgpValueType; +import org.onosproject.bgpio.types.LocalPref; +import org.onosproject.bgpio.types.Med; +import org.onosproject.bgpio.types.Origin; +import org.onosproject.bgp.controller.impl.BgpSelectionAlgo; + +/** + * Test cases for BGP Selection Algorithm. + */ +public class BgpSelectionAlgoTest { + + /** + * firstPathAttribute and secondPathAttribute has same AS count and firstPathAttribute + * has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest1() throws BgpParseException { + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + //origin with IGP + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + //AsPath with AS_SEQ with one AS + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xea }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + //origin with INCOMPLETE + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + //AsPath with AS_SEQ with one AS + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * firstPathAttribute has 1 AS count and secondPathAttribute has 2 AS count + * and firstPathAttribute has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest2() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x08, 0x02, 0x01, (byte) 0xfd, + (byte) 0xea, 0x02, 0x01, (byte) 0xfd, (byte) 0xea }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute and secondPathAttribute has same AS value + * and firstPathAttribute has shortest Origin value than secondPathAttribute. + */ + @Test + public void selectionAlgoTest3() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * firstPathAttribute has lowest med than secondPathAttribute. + */ + @Test + public void selectionAlgoTest4() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, + 0x00 }; + buffer.writeBytes(med); + pathAttribute1 = Med.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x02 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + med = new byte[] {(byte) 0x80, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01 }; + buffer.writeBytes(med); + pathAttribute2 = Med.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * secondPathAttribute has higher local preference than firstPathAttribute. + */ + @Test + public void selectionAlgoTest5() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, + 0x00, 0x01 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(locPref); + pathAttribute1 = LocalPref.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + locPref = new byte[] {(byte) 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x0a }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(locPref); + pathAttribute2 = LocalPref.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = true; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * secondPathAttribute is EBGP than firstPathAttribute is IBGP. + */ + @Test + public void selectionAlgoTest6() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + int bgpId = 168427777; + short locRIBASNum = 100; + boolean isIbgp = true; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + bgpId = 536936448; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, false, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute has lower BGPID than secondPathAttribute. + */ + @Test + public void selectionAlgoTest7() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //B0A0A00 + bgpId = 185207296; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(1)); + } + + /** + * secondPathAttribute has lowest peer address than firstPathAttribute. + */ + @Test + public void selectionAlgoTest8() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0b, 0x0b, 0x0b, 0x0b }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + bgpId = 168430080; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(-1)); + } + + /** + * firstPathAttribute and secondPathAttribute are same. + */ + @Test + public void selectionAlgoTest9() throws BgpParseException { + + byte[] peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes1 = new LinkedList<>(); + BgpValueType pathAttribute1; + byte[] origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute1 = Origin.read(buffer); + pathAttributes1.add(pathAttribute1); + byte[] asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute1 = AsPath.read(buffer); + pathAttributes1.add(pathAttribute1); + + IpAddress ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + Integer bgpId = 168430080; + short locRIBASNum = 100; + boolean isIbgp = false; + PathAttrNlriDetails attrList1 = new PathAttrNlriDetails(); + attrList1.setIdentifier(0); + attrList1.setPathAttribute(pathAttributes1); + attrList1.setProtocolID(ProtocolType.ISIS_LEVEL_ONE); + PathAttrNlriDetailsLocalRib list1 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList1); + + peerIp = new byte[] {0x0a, 0x0a, 0x0a, 0x0a }; + LinkedList pathAttributes2 = new LinkedList<>(); + BgpValueType pathAttribute2; + origin = new byte[] {0x40, 0x01, 0x01, 0x00 }; + buffer = ChannelBuffers.dynamicBuffer(); + buffer.writeBytes(origin); + pathAttribute2 = Origin.read(buffer); + pathAttributes2.add(pathAttribute2); + asPath = new byte[] {0x40, 0x02, 0x04, 0x02, 0x01, (byte) 0xfd, + (byte) 0xe9 }; + buffer.writeBytes(asPath); + pathAttribute2 = AsPath.read(buffer); + pathAttributes2.add(pathAttribute2); + + ipAddress = IpAddress.valueOf(Version.INET, peerIp); + //A0A0A00 + bgpId = 168430080; + locRIBASNum = 200; + isIbgp = false; + PathAttrNlriDetails attrList2 = new PathAttrNlriDetails(); + attrList2.setIdentifier(0); + attrList2.setPathAttribute(pathAttributes2); + attrList2.setProtocolID(ProtocolType.OSPF_V2); + PathAttrNlriDetailsLocalRib list2 = new PathAttrNlriDetailsLocalRib( + ipAddress, bgpId, locRIBASNum, isIbgp, attrList2); + BgpSelectionAlgo algo = new BgpSelectionAlgo(); + int result = algo.compare(list1, list2); + assertThat(result, is(0)); + } +} diff --git a/framework/src/onos/protocols/bgp/pom.xml b/framework/src/onos/protocols/bgp/pom.xml new file mode 100755 index 00000000..3b28181e --- /dev/null +++ b/framework/src/onos/protocols/bgp/pom.xml @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + org.onosproject + onos-protocols + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-bgp + pom + + ONOS BGP Protocol subsystem + + + api + ctl + bgpio + + + diff --git a/framework/src/onos/protocols/netconf/api/pom.xml b/framework/src/onos/protocols/netconf/api/pom.xml index ed8a5302..062ec932 100644 --- a/framework/src/onos/protocols/netconf/api/pom.xml +++ b/framework/src/onos/protocols/netconf/api/pom.xml @@ -14,18 +14,23 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + 4.0.0 org.onosproject onos-netconf 1.4.0-SNAPSHOT + ../pom.xml + onos-netconf-api bundle ONOS NETCONF plugin API + commons-pool diff --git a/framework/src/onos/protocols/netconf/ctl/pom.xml b/framework/src/onos/protocols/netconf/ctl/pom.xml index e022acba..bae59f07 100644 --- a/framework/src/onos/protocols/netconf/ctl/pom.xml +++ b/framework/src/onos/protocols/netconf/ctl/pom.xml @@ -28,6 +28,8 @@ onos-netconf-ctl bundle + ONOS NETCONF plugin controller + org.osgi @@ -86,6 +88,10 @@ + + org.apache.felix + maven-scr-plugin + diff --git a/framework/src/onos/protocols/netconf/pom.xml b/framework/src/onos/protocols/netconf/pom.xml index d2f5c432..f0d6ca70 100644 --- a/framework/src/onos/protocols/netconf/pom.xml +++ b/framework/src/onos/protocols/netconf/pom.xml @@ -34,21 +34,9 @@ ctl - ONOS NETCONF southbound libraries + ONOS NETCONF southbound plugin + - - junit - junit - test - - - org.onosproject - onlab-misc - - - org.onosproject - onlab-junit - io.netty netty-buffer @@ -63,21 +51,9 @@ org.onosproject - onos-core-net + onos-api ${project.version} - - - - org.apache.felix - maven-bundle-plugin - - - org.apache.felix - maven-scr-plugin - - - diff --git a/framework/src/onos/protocols/netconf/rfc/pom.xml b/framework/src/onos/protocols/netconf/rfc/pom.xml index 832937bc..fa1e06e2 100644 --- a/framework/src/onos/protocols/netconf/rfc/pom.xml +++ b/framework/src/onos/protocols/netconf/rfc/pom.xml @@ -27,4 +27,5 @@ onos-netconf-rfc bundle + diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java new file mode 100644 index 00000000..7336c3c6 --- /dev/null +++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.openflow.controller; + +import com.google.common.annotations.Beta; +import org.onosproject.net.driver.HandlerBehaviour; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.oxm.OFOxm; + +/** + * Interprets extension selectors and converts them to/from OpenFlow objects. + */ +@Beta +public interface ExtensionSelectorInterpreter extends HandlerBehaviour { + + /** + * Returns true if the given extension selector is supported by this + * driver. + * + * @param extensionSelectorType extension selector type + * @return true if the instruction is supported, otherwise false + */ + boolean supported(ExtensionSelectorType extensionSelectorType); + + /** + * Maps an extension selector to an OpenFlow OXM. + * + * @param factory OpenFlow factory + * @param extensionSelector extension selector + * @return OpenFlow action + */ + OFOxm mapSelector(OFFactory factory, ExtensionSelector extensionSelector); + + /** + * Maps an OpenFlow OXM to an extension selector. + * + * @param oxm OpenFlow OXM + * @return extension selector + */ + ExtensionSelector mapOxm(OFOxm oxm); +} diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java index dc57977f..88a5353d 100644 --- a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java +++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java @@ -24,34 +24,34 @@ import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.action.OFAction; /** - * Interprets extension instructions and converts them to/from OpenFlow objects. + * Interprets extension treatments and converts them to/from OpenFlow objects. */ @Beta public interface ExtensionTreatmentInterpreter extends HandlerBehaviour { /** - * Returns true if the given extension instruction is supported by this + * Returns true if the given extension treatment is supported by this * driver. * - * @param extensionTreatmentType extension instruction type - * @return true if the instruction is supported, otherwise false + * @param extensionTreatmentType extension treatment type + * @return true if the extension is supported, otherwise false */ boolean supported(ExtensionTreatmentType extensionTreatmentType); /** - * Maps an extension instruction to an OpenFlow action. + * Maps an extension treatment to an OpenFlow action. * * @param factory OpenFlow factory - * @param extensionTreatment extension instruction + * @param extensionTreatment extension treatment * @return OpenFlow action */ OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment); /** - * Maps an OpenFlow action to an extension instruction. + * Maps an OpenFlow action to an extension treatment. * * @param action OpenFlow action - * @return extension instruction + * @return extension treatment */ ExtensionTreatment mapAction(OFAction action); diff --git a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java index c7174192..08444b17 100644 --- a/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java +++ b/framework/src/onos/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java @@ -98,6 +98,7 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour @Override public final void disconnectSwitch() { + setConnected(false); this.channel.close(); } diff --git a/framework/src/onos/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java b/framework/src/onos/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java index b97c3362..b410158e 100644 --- a/framework/src/onos/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java +++ b/framework/src/onos/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java @@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onosproject.cfg.ComponentConfigService; +import org.onosproject.core.CoreService; import org.onosproject.net.driver.DefaultDriverProviderService; import org.onosproject.net.driver.DriverService; import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext; @@ -83,12 +84,16 @@ import static org.onlab.util.Tools.groupedThreads; @Component(immediate = true) @Service public class OpenFlowControllerImpl implements OpenFlowController { + private static final String APP_ID = "org.onosproject.openflow-base"; private static final String DEFAULT_OFPORT = "6633,6653"; private static final int DEFAULT_WORKER_THREADS = 16; private static final Logger log = LoggerFactory.getLogger(OpenFlowControllerImpl.class); + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DriverService driverService; @@ -147,15 +152,24 @@ public class OpenFlowControllerImpl implements OpenFlowController { @Activate public void activate(ComponentContext context) { + coreService.registerApplication(APP_ID, this::preDeactivate); cfgService.registerProperties(getClass()); ctrl.setConfigParams(context.getProperties()); ctrl.start(agent, driverService); } + private void preDeactivate() { + // Close listening channel and all OF channels before deactivating + ctrl.stop(); + connectedSwitches.values().forEach(OpenFlowSwitch::disconnectSwitch); + } + @Deactivate public void deactivate() { cfgService.unregisterProperties(getClass(), false); - ctrl.stop(); + connectedSwitches.clear(); + activeMasterSwitches.clear(); + activeEqualSwitches.clear(); } @Modified diff --git a/framework/src/onos/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java b/framework/src/onos/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java index e079c590..56d422a9 100644 --- a/framework/src/onos/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java +++ b/framework/src/onos/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java @@ -32,6 +32,7 @@ import org.junit.Before; import org.junit.Test; import org.onlab.junit.TestTools; import org.onosproject.cfg.ComponentConfigService; +import org.onosproject.core.CoreService; import org.onosproject.openflow.OpenflowSwitchDriverAdapter; import org.onosproject.openflow.controller.Dpid; import org.onosproject.openflow.controller.OpenFlowSwitch; @@ -127,6 +128,10 @@ public class OpenFlowControllerImplTest { switchListener = new TestSwitchListener(); controller.addListener(switchListener); + CoreService mockCoreService = + EasyMock.createMock(CoreService.class); + controller.coreService = mockCoreService; + ComponentConfigService mockConfigService = EasyMock.createMock(ComponentConfigService.class); expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of()); diff --git a/framework/src/onos/protocols/openflow/pom.xml b/framework/src/onos/protocols/openflow/pom.xml index 5a136a19..3bf976b5 100644 --- a/framework/src/onos/protocols/openflow/pom.xml +++ b/framework/src/onos/protocols/openflow/pom.xml @@ -37,20 +37,6 @@ - - org.onosproject - onlab-misc - - - org.onosproject - onlab-junit - - - junit - junit - 4.11 - test - org.hamcrest hamcrest-core @@ -74,13 +60,4 @@ - - - - org.apache.felix - maven-bundle-plugin - - - - diff --git a/framework/src/onos/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/framework/src/onos/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java index 8a661ab9..5f72606d 100644 --- a/framework/src/onos/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java +++ b/framework/src/onos/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java @@ -578,16 +578,7 @@ public class DefaultOvsdbClient return false; } - String bridgeUuid = getBridgeUuid(bridgeName); - if (bridgeUuid != null) { - log.warn("Bridge {} is already exist", bridgeName); - // remove existing one and re-create? - return false; - } - Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE); - bridge.setName(bridgeName); - Set failMode = new HashSet<>(Arrays.asList("secure")); bridge.setFailMode(failMode); @@ -598,9 +589,15 @@ public class DefaultOvsdbClient options.put("datapath-id", dpid); bridge.setOtherConfig(options); - bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid", - OvsdbConstant.DATABASENAME, "bridges", - ovsUuid, bridge.getRow()); + String bridgeUuid = getBridgeUuid(bridgeName); + if (bridgeUuid == null) { + bridge.setName(bridgeName); + bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid", + OvsdbConstant.DATABASENAME, "bridges", + ovsUuid, bridge.getRow()); + } else { + updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow()); + } if (bridgeUuid != null) { createPort(bridgeName, bridgeName); diff --git a/framework/src/onos/protocols/ovsdb/pom.xml b/framework/src/onos/protocols/ovsdb/pom.xml index 930978a4..03e9d98c 100644 --- a/framework/src/onos/protocols/ovsdb/pom.xml +++ b/framework/src/onos/protocols/ovsdb/pom.xml @@ -20,28 +20,23 @@ 4.0.0 org.onosproject - onos + onos-protocols 1.4.0-SNAPSHOT + ../pom.xml + onos-ovsdb - onos-ovsdb pom ONOS OVSDB southbound plugin + + + api + rfc + ctl + + - - junit - junit - test - - - org.onosproject - onlab-misc - - - org.onosproject - onlab-junit - io.netty netty-buffer @@ -52,18 +47,4 @@ - - - - org.apache.felix - maven-bundle-plugin - - - - - - api - rfc - ctl - \ No newline at end of file diff --git a/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/ISISAreaIdentifierTlv.java b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/ISISAreaIdentifierTlv.java index 648dbb66..f9fb4f89 100644 --- a/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/ISISAreaIdentifierTlv.java +++ b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/ISISAreaIdentifierTlv.java @@ -15,6 +15,7 @@ */ package org.onosproject.pcepio.types; +import java.util.Arrays; import java.util.Objects; import org.jboss.netty.buffer.ChannelBuffer; @@ -100,7 +101,7 @@ public class ISISAreaIdentifierTlv implements PcepValueType { @Override public int hashCode() { - return Objects.hash(rawValue); + return Objects.hash(Arrays.hashCode(rawValue), rawValue.length); } @Override @@ -110,7 +111,7 @@ public class ISISAreaIdentifierTlv implements PcepValueType { } if (obj instanceof ISISAreaIdentifierTlv) { ISISAreaIdentifierTlv other = (ISISAreaIdentifierTlv) obj; - return Objects.equals(hLength, other.hLength) && Objects.equals(rawValue, other.rawValue); + return Objects.equals(hLength, other.hLength) && Arrays.equals(rawValue, other.rawValue); } return false; } diff --git a/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/LinkNameTlv.java b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/LinkNameTlv.java index aa0f11a7..34dea5ba 100644 --- a/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/LinkNameTlv.java +++ b/framework/src/onos/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/LinkNameTlv.java @@ -15,8 +15,7 @@ */ package org.onosproject.pcepio.types; -import java.util.Objects; - +import java.util.Arrays; import org.jboss.netty.buffer.ChannelBuffer; import org.onosproject.pcepio.protocol.PcepVersion; import org.slf4j.Logger; @@ -100,7 +99,7 @@ public class LinkNameTlv implements PcepValueType { @Override public int hashCode() { - return Objects.hash(rawValue); + return Arrays.hashCode(rawValue); } @Override @@ -110,7 +109,7 @@ public class LinkNameTlv implements PcepValueType { } if (obj instanceof LinkNameTlv) { LinkNameTlv other = (LinkNameTlv) obj; - return Objects.equals(rawValue, other.rawValue); + return Arrays.equals(this.rawValue, other.rawValue); } return false; } diff --git a/framework/src/onos/protocols/pcep/pom.xml b/framework/src/onos/protocols/pcep/pom.xml index c8e4222d..466b0c3c 100755 --- a/framework/src/onos/protocols/pcep/pom.xml +++ b/framework/src/onos/protocols/pcep/pom.xml @@ -37,24 +37,4 @@ pcepio - - - org.onosproject - onlab-misc - - - org.onosproject - onlab-junit - - - - - - - org.apache.felix - maven-bundle-plugin - - - - diff --git a/framework/src/onos/protocols/pom.xml b/framework/src/onos/protocols/pom.xml index bcdc58b8..25219fa0 100644 --- a/framework/src/onos/protocols/pom.xml +++ b/framework/src/onos/protocols/pom.xml @@ -29,19 +29,30 @@ onos-protocols pom - ONOS south-bound protocols + ONOS southbound protocols openflow netconf pcep ovsdb - + + org.onosproject + onlab-misc + + + org.onosproject + onlab-junit + + + junit + junit + test + diff --git a/framework/src/onos/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java b/framework/src/onos/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java index 30bb4470..37576e44 100755 --- a/framework/src/onos/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java +++ b/framework/src/onos/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpTopologyProviderTest.java @@ -31,6 +31,7 @@ import org.onosproject.bgp.controller.BgpCfg; import org.onosproject.bgp.controller.BgpController; import org.onosproject.bgp.controller.BgpId; import org.onosproject.bgp.controller.BgpPeer; +import org.onosproject.bgp.controller.BgpLocalRib; import org.onosproject.bgp.controller.BgpNodeListener; import org.onosproject.bgp.controller.BgpPeerManager; import org.onosproject.bgpio.exceptions.BgpParseException; @@ -208,6 +209,17 @@ public class BgpTopologyProviderTest { return 0; } + @Override + public BgpLocalRib bgpLocalRibVpn() { + // TODO Auto-generated method stub + return null; + } + + @Override + public BgpLocalRib bgpLocalRib() { + // TODO Auto-generated method stub + return null; + } @Override public BgpPeerManager peerManager() { diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java index 94abebaa..668d59c0 100644 --- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java +++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java @@ -570,7 +570,7 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { case DEVICE_AVAILABILITY_CHANGED: if (deviceService.isAvailable(deviceId)) { log.debug("Device up {}", deviceId); - updateDevice(device); + updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId)); } else { log.debug("Device down {}", deviceId); removeDevice(deviceId); diff --git a/framework/src/onos/providers/netcfghost/pom.xml b/framework/src/onos/providers/netcfghost/pom.xml new file mode 100644 index 00000000..15363c8d --- /dev/null +++ b/framework/src/onos/providers/netcfghost/pom.xml @@ -0,0 +1,65 @@ + + + + + onos-providers + org.onosproject + 1.4.0-SNAPSHOT + + 4.0.0 + + onos-netcfg-host-provider + bundle + + + Host provider that uses network config service to discover hosts. + + http://onosproject.org + + + org.onosproject.netcfghostprovider + ON.Lab + + + + + org.onosproject + onos-api + + + + org.onosproject + onlab-osgi + + + + junit + junit + 4.11 + test + + + + org.easymock + easymock + test + + + + diff --git a/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java b/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java new file mode 100644 index 00000000..767cfb7f --- /dev/null +++ b/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java @@ -0,0 +1,196 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.provider.netcfghost; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.Host; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigRegistry; +import org.onosproject.net.config.basics.BasicHostConfig; +import org.onosproject.net.host.DefaultHostDescription; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.host.HostProvider; +import org.onosproject.net.host.HostProviderRegistry; +import org.onosproject.net.host.HostProviderService; +import org.onosproject.net.provider.AbstractProvider; +import org.onosproject.net.provider.ProviderId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.Set; + +/** + * Host provider that uses network config service to discover hosts. + */ +@Component(immediate = true) +public class NetworkConfigHostProvider extends AbstractProvider implements HostProvider { + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected HostProviderRegistry providerRegistry; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected NetworkConfigRegistry networkConfigRegistry; + + private static final String APP_NAME = "org.onosproject.provider.netcfghost"; + private ApplicationId appId; + protected HostProviderService providerService; + + private final Logger log = LoggerFactory.getLogger(getClass()); + private final InternalNetworkConfigListener networkConfigListener = + new InternalNetworkConfigListener(); + + /** + * Creates an network config host location provider. + */ + public NetworkConfigHostProvider() { + super(new ProviderId("host", APP_NAME)); + } + + @Activate + protected void activate() { + appId = coreService.registerApplication(APP_NAME); + providerService = providerRegistry.register(this); + networkConfigRegistry.addListener(networkConfigListener); + readInitialConfig(); + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + networkConfigRegistry.removeListener(networkConfigListener); + providerRegistry.unregister(this); + providerService = null; + log.info("Stopped"); + } + + @Override + public void triggerProbe(Host host) { + /* + * Note: In CORD deployment, we assume that all hosts are configured. + * Therefore no probe is required. + */ + } + + /** + * Adds host information. + * IP information will be appended if host exists. + * + * @param mac MAC address of the host + * @param vlan VLAN ID of the host + * @param hloc Location of the host + * @param ips Set of IP addresses of the host + */ + protected void addHost(MacAddress mac, VlanId vlan, HostLocation hloc, Set ips) { + HostId hid = HostId.hostId(mac, vlan); + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ips); + providerService.hostDetected(hid, desc, false); + } + + /** + * Updates host information. + * IP information will be replaced if host exists. + * + * @param mac MAC address of the host + * @param vlan VLAN ID of the host + * @param hloc Location of the host + * @param ips Set of IP addresses of the host + */ + protected void updateHost(MacAddress mac, VlanId vlan, HostLocation hloc, Set ips) { + HostId hid = HostId.hostId(mac, vlan); + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ips); + providerService.hostDetected(hid, desc, true); + } + + /** + * Removes host information. + * + * @param mac MAC address of the host + * @param vlan VLAN ID of the host + */ + protected void removeHost(MacAddress mac, VlanId vlan) { + HostId hid = HostId.hostId(mac, vlan); + providerService.hostVanished(hid); + } + + private void readInitialConfig() { + networkConfigRegistry.getSubjects(HostId.class).forEach(hostId -> { + MacAddress mac = hostId.mac(); + VlanId vlan = hostId.vlanId(); + BasicHostConfig hostConfig = + networkConfigRegistry.getConfig(hostId, BasicHostConfig.class); + Set ipAddresses = hostConfig.ipAddresses(); + ConnectPoint location = hostConfig.location(); + HostLocation hloc = new HostLocation(location, System.currentTimeMillis()); + addHost(mac, vlan, hloc, ipAddresses); + }); + } + + private class InternalNetworkConfigListener implements NetworkConfigListener { + @Override + public void event(NetworkConfigEvent event) { + // Do not process non-host, register and unregister events + if (!event.configClass().equals(BasicHostConfig.class) || + event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED || + event.type() == NetworkConfigEvent.Type.CONFIG_UNREGISTERED) { + return; + } + + HostId hostId = (HostId) event.subject(); + MacAddress mac = hostId.mac(); + VlanId vlan = hostId.vlanId(); + BasicHostConfig hostConfig = + networkConfigRegistry.getConfig(hostId, BasicHostConfig.class); + Set ipAddresses = null; + HostLocation hloc = null; + + // Note: There will be no config presented in the CONFIG_REMOVE case + if (hostConfig != null) { + ipAddresses = hostConfig.ipAddresses(); + ConnectPoint location = hostConfig.location(); + hloc = new HostLocation(location, System.currentTimeMillis()); + } + + switch (event.type()) { + case CONFIG_ADDED: + addHost(mac, vlan, hloc, ipAddresses); + break; + case CONFIG_UPDATED: + updateHost(mac, vlan, hloc, ipAddresses); + break; + case CONFIG_REMOVED: + removeHost(mac, vlan); + break; + default: + break; + } + } + } +} diff --git a/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/package-info.java b/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/package-info.java new file mode 100644 index 00000000..a56b9a80 --- /dev/null +++ b/framework/src/onos/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Host provider that uses network config service to discover hosts. + */ +package org.onosproject.provider.netcfghost; diff --git a/framework/src/onos/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java b/framework/src/onos/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java new file mode 100644 index 00000000..a4f057cf --- /dev/null +++ b/framework/src/onos/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.provider.netcfghost; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onosproject.net.DeviceId; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.PortNumber; +import org.onosproject.net.host.DefaultHostDescription; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.host.HostProvider; +import org.onosproject.net.host.HostProviderService; +import org.onosproject.net.provider.AbstractProviderService; + +import java.util.HashSet; +import java.util.Set; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +/** + * Set of tests of the host location provider for CORD. + */ +public class NetworkConfigHostProviderTest { + private NetworkConfigHostProvider provider = new NetworkConfigHostProvider(); + private MockHostProviderService providerService = new MockHostProviderService(provider); + + private MacAddress mac = MacAddress.valueOf("c0:ff:ee:c0:ff:ee"); + private VlanId vlan = VlanId.vlanId(VlanId.UNTAGGED); + private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); + private PortNumber port = PortNumber.portNumber(5); + private HostLocation hloc = new HostLocation(deviceId, port, 100); + private Set ips = new HashSet<>(); + private HostId hostId = HostId.hostId(mac, vlan); + private HostDescription hostDescription; + + @Before + public void setUp() { + provider.providerService = providerService; + + // Initialize test variables + ips.add(IpAddress.valueOf("10.0.0.1")); + ips.add(IpAddress.valueOf("192.168.0.1")); + hostDescription = new DefaultHostDescription(mac, vlan, hloc, ips); + } + + @Test + public void testAddHost() throws Exception { + provider.addHost(mac, vlan, hloc, ips); + assertThat(providerService.hostId, is(hostId)); + assertThat(providerService.hostDescription, is(hostDescription)); + assertThat(providerService.event, is("hostDetected")); + providerService.clear(); + } + + @Test + public void testUpdateHost() throws Exception { + provider.updateHost(mac, vlan, hloc, ips); + assertThat(providerService.hostId, is(hostId)); + assertThat(providerService.hostDescription, is(hostDescription)); + assertThat(providerService.event, is("hostDetected")); + providerService.clear(); + } + + @Test + public void testRemoveHost() throws Exception { + provider.removeHost(mac, vlan); + assertThat(providerService.hostId, is(hostId)); + assertNull(providerService.hostDescription); + assertThat(providerService.event, is("hostVanished")); + providerService.clear(); + } + + /** + * Mock HostProviderService. + */ + private class MockHostProviderService + extends AbstractProviderService + implements HostProviderService { + private HostId hostId = null; + private HostDescription hostDescription = null; + private String event = null; + + public MockHostProviderService(HostProvider provider) { + super(provider); + } + + @Override + public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) { + this.hostId = hostId; + this.hostDescription = hostDescription; + this.event = "hostDetected"; + } + + @Override + public void hostVanished(HostId hostId) { + this.hostId = hostId; + this.event = "hostVanished"; + } + + @Override + public void removeIpFromHost(HostId hostId, IpAddress ipAddress) { + // Note: This method is never used. + } + + public void clear() { + this.hostId = null; + this.hostDescription = null; + this.event = null; + } + } +} diff --git a/framework/src/onos/providers/netconf/app/pom.xml b/framework/src/onos/providers/netconf/app/pom.xml index 4a19ae8e..0aa55ff5 100644 --- a/framework/src/onos/providers/netconf/app/pom.xml +++ b/framework/src/onos/providers/netconf/app/pom.xml @@ -37,12 +37,7 @@ onos-netconf-provider-device ${project.version} - - org.onosproject - onos-netconf-provider-flow - ${project.version} - - + diff --git a/framework/src/onos/providers/netconf/flow/pom.xml b/framework/src/onos/providers/netconf/flow/pom.xml deleted file mode 100644 index 7ccd552f..00000000 --- a/framework/src/onos/providers/netconf/flow/pom.xml +++ /dev/null @@ -1,259 +0,0 @@ - - - - 4.0.0 - - - org.onosproject - onos-netconf-providers - 1.4.0-SNAPSHOT - ../pom.xml - - - onos-netconf-provider-flow - bundle - - - - org.osgi - org.osgi.compendium - - - ch.ethz.ganymed - ganymed-ssh2 - 262 - - - - org.onosproject - jnc - 1.0 - - - org.jdom - jdom2 - 2.0.5 - - - jaxen - jaxen - 1.1.4 - true - - - org.osgi - org.osgi.core - - - org.onosproject - onlab-junit - test - - - org.easymock - easymock - test - - - org.onosproject - onos-yang-tool - 1.3 - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.3 - - - - com.tailf:JNC - - com/tailf/jnc/** - - - - ch.ethz.ganymed:ganymed-ssh2 - - ch/ethz/ssh2/** - - - - org.jdom:jdom2 - - org/jdom2/** - - - - org.onosproject:onos-yang-tool - - org/opendaylight/yang/gen/** - - - - - - - package - - shade - - - - - - org.apache.felix - maven-scr-plugin - - - org.apache.felix - maven-bundle-plugin - - - - com.tailf.jnc, - ch.ethz.ssh2, - ch.ethz.ssh2.auth, - ch.ethz.ssh2.channel, - ch.ethz.ssh2.crypto, - ch.ethz.ssh2.crypto.cipher, - ch.ethz.ssh2.crypto.dh, - ch.ethz.ssh2.crypto.digest, - ch.ethz.ssh2.log, - ch.ethz.ssh2.packets, - ch.ethz.ssh2.server, - ch.ethz.ssh2.sftp, - ch.ethz.ssh2.signature, - ch.ethz.ssh2.transport, - ch.ethz.ssh2.util, - org.jdom2, - org.jdom2.input, - org.jdom2.output, - org.jdom2.adapters, - org.jdom2.filter, - org.jdom2.internal, - org.jdom2.located, - org.jdom2.transform, - org.jdom2.util, - org.jdom2.xpath, - org.jdom2.input.sax, - org.jdom2.input.stax, - org.jdom2.output.support, - org.jdom2.xpath.jaxen, - org.jdom2.xpath.util, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520, - org.opendaylight.yangtools.yang.data.impl.schema.tree, - org.opendaylight.yangtools.yang.data.impl.codec, - org.opendaylight.yangtools.yang.model.parser.api, - org.opendaylight.yangtools.yang.data.impl.schema.nodes, - org.opendaylight.yangtools.yang.binding.util, - org.opendaylight.yangtools.yang.data.impl, - org.opendaylight.yangtools.sal.binding.generator.impl, - org.opendaylight.yangtools.yang.parser.impl.util, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625, - org.opendaylight.yangtools.yang.data.api, - org.opendaylight.yangtools.objcache.spi, - org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser, - org.opendaylight.yangtools.maven.sal.api.gen.plugin, - org.opendaylight.yangtools.yang.data.impl.schema.builder.impl, - org.opendaylight.yangtools.yang.data.api.schema.tree, - org.opendaylight.yangtools.binding.generator.util, - org.opendaylight.yangtools.sal.binding.generator.spi, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715, - org.opendaylight.yangtools.yang2sources.spi, - org.opendaylight.yangtools.yang.model.repo.api, - org.opendaylight.yangtools.util, - org.opendaylight.yangtools.yang.parser.util, - org.opendaylight.yangtools.yang.data.api.schema.stream, - org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer, - org.opendaylight.yangtools.concepts, - org.opendaylight.yangtools.yang.binding, - org.opendaylight.yangtools.yang.model.util.repo, - org.opendaylight.yangtools.yang.wadl.generator.maven, - org.opendaylight.yangtools.yang.data.api.schema, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type, - org.opendaylight.yangtools.concepts.util, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version, - org.opendaylight.yangtools.sal.binding.model.api, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip, - org.opendaylight.yangtools.yang.data.impl.schema.builder.api, - org.opendaylight.yangtools.util.concurrent, - org.opendaylight.yangtools.yang.parser.builder.impl, - org.opendaylight.yangtools.yang.data.impl.schema.transform.base, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling, - org.opendaylight.yangtools.sal.binding.model.api.type.builder, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields, - org.opendaylight.yangtools.yang2sources.plugin, - org.opendaylight.yangtools.yang.data.impl.codec.xml, - org.opendaylight.yangtools.antlrv4.code.gen, - org.opendaylight.yangtools.yang.parser.builder.util, - org.opendaylight.yangtools.yang.data.impl.schema.transform, - org.opendaylight.yangtools.yang.model.api.type, - org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer, - org.opendaylight.yangtools.yang.data.api.schema.tree.spi, - org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser, - org.opendaylight.yangtools.sal.binding.yang.types, - org.opendaylight.yangtools.yang.data.impl.schema.transform.dom, - org.opendaylight.yangtools.yang.data.impl.util, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.timerange, - org.opendaylight.yangtools.sal.binding.generator.api, - org.opendaylight.yangtools.sal.java.api.generator, - org.opendaylight.yangtools.yang.binding.annotations, - org.opendaylight.yangtools.sal.binding.generator.util, - org.opendaylight.yangtools.yang.model.repo.util, - org.opendaylight.yangtools.yang.model.api, - org.opendaylight.yangtools.yang.common, - org.opendaylight.yangtools.yang.wadl.generator, - org.opendaylight.yangtools.yang.parser.builder.api, - org.opendaylight.yangtools.yang.model.util, - org.opendaylight.yangtools.yang.parser.impl, - org.opendaylight.yangtools.yang.data.impl.schema, - org.opendaylight.yangtools.yang.data.api.codec, - org.opendaylight.yangtools.yang.unified.doc.generator, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list, - org.opendaylight.yangtools.objcache, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions, - org.opendaylight.yangtools.yang.data.util, - org.opendaylight.yangtools.yang.unified.doc.generator.maven, - org.opendaylight.yangtools.binding.generator.util.generated.type.builder, - org.opendaylight.yangtools.yang.model.repo.spi, - org.opendaylight.yangtools.yang.parser.repo, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715, - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches, - org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid, - com.romix.scala, - com.romix.scala.collection, - com.romix.scala.collection.concurrent, - org.opendaylight.yangtools.objcache.impl - - - - - - org.onosproject - onos-maven-plugin - - - - - diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java deleted file mode 100644 index b29d687e..00000000 --- a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.flow.impl; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static org.onlab.util.Tools.get; -import static org.slf4j.LoggerFactory.getLogger; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Dictionary; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timeout; -import org.jboss.netty.util.TimerTask; -import org.onlab.util.Timer; -import org.onosproject.core.ApplicationId; -import org.onosproject.net.DeviceId; -import org.onosproject.net.flow.FlowEntry; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleBatchOperation; -import org.onosproject.net.flow.FlowRuleProvider; -import org.onosproject.net.flow.FlowRuleProviderRegistry; -import org.onosproject.net.flow.FlowRuleProviderService; -import org.onosproject.net.provider.AbstractProvider; -import org.onosproject.net.provider.ProviderId; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.AccessList; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.AccessListBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.AccessListEntries; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.AccessListEntriesBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.ActionsBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.Matches; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.MatchesBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling.DenyBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling.PermitBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceIp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceIpBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.DestinationPortRange; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.DestinationPortRangeBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.SourcePortRange; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.SourcePortRangeBuilder; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -/** - * Netconf provider to accept any flow and report them. - */ -@Component(immediate = true) -public class NetconfFlowRuleProvider extends AbstractProvider - implements FlowRuleProvider { - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected FlowRuleProviderRegistry providerRegistry; - - private ConcurrentMap> flowTable = new ConcurrentHashMap<>(); - - private FlowRuleProviderService providerService; - - private XmlBuilder xmlBuilder; - - private AceIp aceIp; - private SourcePortRange srcPortRange; - private DestinationPortRange destPortRange; - private Matches matches; - private HashedWheelTimer timer = Timer.getTimer(); - private Timeout timeout; - private static final String ACL_NAME_KEY = "acl-name"; - private static final String ACL_LIST_ENTRIES_RULE_NAME_KEY = "access-list-entries.rule-name"; - private static final String ACL_LIST_SP_LOWER_KEY = "source-port-range.lower-port"; - private static final String ACL_LIST_SP_UPPER_KEY = "source-port-range.upper-port"; - private static final String ACL_LIST_DP_LOWER_KEY = "destination-port-range.lower-port"; - private static final String ACL_LIST_DP_UPPER_KEY = "destination-port-range.upper-port"; - private static final String ACL_LIST_DEST_IPV4_KEY = "matches.destination-ipv4-address"; - private static final String ACL_LIST_SRC_IPV4_KEY = "matches.source-ipv4-address"; - private static final String ACL_LIST_ACTIONS_KEY = "actions"; - - public NetconfFlowRuleProvider() { - super(new ProviderId("netconf", "org.onosproject.provider.netconf")); - } - - @Activate - public void activate(ComponentContext context) { - providerService = providerRegistry.register(this); - timeout = timer.newTimeout(new StatisticTask(), 5, TimeUnit.SECONDS); - applyRule(); - modified(context); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - providerRegistry.unregister(this); - providerService = null; - timeout.cancel(); - log.info("Stopped"); - } - - @Modified - public void modified(ComponentContext context) { - if (xmlBuilder == null) { - xmlBuilder = new XmlBuilder(); - } - if (context == null) { - log.info("No configuration file"); - return; - } - Dictionary properties = context.getProperties(); - String deviceEntry = get(properties, "devConfigs"); - log.info("Settings: devConfigs={}", deviceEntry); - Enumeration elements = properties.keys(); - Object nextElement = elements.nextElement(); - while (elements.hasMoreElements()) { - if (nextElement instanceof String) { - log.info("key::" + nextElement + ", value::" - + get(properties, (String) nextElement)); - } - nextElement = elements.nextElement(); - } - if (!isNullOrEmpty(deviceEntry)) { - Map deviceMap = processDeviceEntry(deviceEntry); - AccessList accessList = buildAccessList(properties); - String xmlMsg = xmlBuilder.buildAclRequestXml(accessList); - log.info("The resultant xml from the builder\n" + xmlMsg); - NetconfOperation netconfOperation = new NetconfOperation(); - netconfOperation.sendXmlMessage(xmlMsg, deviceMap.get("username"), - deviceMap.get("password"), - deviceMap.get("hostIp"), Integer - .parseInt(deviceMap - .get("hostPort"))); - } - } - - /** - * @param properties - * @return accessList - */ - private AccessList buildAccessList(Dictionary properties) { - /** - * Populating Access List. - */ - AccessListBuilder abuilder = new AccessListBuilder(); - String aclName = get(properties, ACL_NAME_KEY); - if (aclName != null) { - abuilder.setAclName(aclName); - } - AccessList accessList = abuilder.build(); - abuilder.setAccessListEntries(getAccessListEntries(properties, matches)); - srcPortRange = getSourcePortRange(properties); - destPortRange = getDestinationPortRange(properties); - aceIp = getAceIp(properties, srcPortRange, destPortRange); - matches = getMatches(properties); - return accessList; - } - - /** - * @param properties - * @return matches - */ - private Matches getMatches(Dictionary properties) { - /** - * Building Matches for given ACL model. - */ - MatchesBuilder matchesBuilder = new MatchesBuilder(); - if (aceIp != null) { - matchesBuilder.setAceType(aceIp); - } - matches = matchesBuilder.build(); - return matches; - } - - /** - * @param properties - * @return srcPortRange - */ - private SourcePortRange getSourcePortRange(Dictionary properties) { - /** - * Building Source Port Range for given ACL model. - */ - String spRangeLowerStr = get(properties, ACL_LIST_SP_LOWER_KEY); - String spRangeUpperStr = get(properties, ACL_LIST_SP_UPPER_KEY); - SourcePortRangeBuilder srcPortRangeBuilder = new SourcePortRangeBuilder(); - if (spRangeLowerStr != null) { - int spRangeLower = Integer.parseInt(spRangeLowerStr); - srcPortRangeBuilder.setLowerPort(new PortNumber(spRangeLower)); - } - if (spRangeUpperStr != null) { - int spRangeUpper = Integer.parseInt(spRangeUpperStr); - srcPortRangeBuilder.setUpperPort(new PortNumber(spRangeUpper)); - } - srcPortRange = srcPortRangeBuilder.build(); - return srcPortRange; - } - - /** - * @param properties - * @return destPortRange - */ - private DestinationPortRange getDestinationPortRange(Dictionary properties) { - /** - * Building Destination Port Range for given ACL model. - */ - String dpRangeLowerStr = get(properties, ACL_LIST_DP_LOWER_KEY); - String dpRangeUpperStr = get(properties, ACL_LIST_DP_UPPER_KEY); - DestinationPortRangeBuilder destPortRangeBuilder = new DestinationPortRangeBuilder(); - if (dpRangeLowerStr != null) { - int dpRangeLower = Integer.parseInt(dpRangeLowerStr); - destPortRangeBuilder.setLowerPort(new PortNumber(dpRangeLower)); - } - if (dpRangeUpperStr != null) { - int dpRangeUpper = Integer.parseInt(dpRangeUpperStr); - destPortRangeBuilder.setUpperPort(new PortNumber(dpRangeUpper)); - } - destPortRange = destPortRangeBuilder.build(); - return destPortRange; - } - - /** - * @param properties - * @return accessListEntries - */ - private List getAccessListEntries(Dictionary properties, - Matches matches) { - /** - * Build and Populate Access List Entries. - */ - AccessListEntriesBuilder acLListEntriesBuilder = new AccessListEntriesBuilder(); - String aclListEntriesRuleName = get(properties, - ACL_LIST_ENTRIES_RULE_NAME_KEY); - if (aclListEntriesRuleName != null) { - acLListEntriesBuilder.setRuleName(aclListEntriesRuleName); - } - acLListEntriesBuilder.setMatches(matches); - String aclActions = get(properties, ACL_LIST_ACTIONS_KEY); - if (aclActions != null) { - ActionsBuilder actionBuilder = new ActionsBuilder(); - if (aclActions.equalsIgnoreCase("deny")) { - DenyBuilder denyBuilder = new DenyBuilder(); - actionBuilder.setPacketHandling(denyBuilder.build()); - } else if (aclActions.equalsIgnoreCase("permit")) { - PermitBuilder permitBuilder = new PermitBuilder(); - actionBuilder.setPacketHandling(permitBuilder.build()); - } - acLListEntriesBuilder.setActions(actionBuilder.build()); - } - AccessListEntries aclListEntries = acLListEntriesBuilder.build(); - List accessListEntries = new ArrayList(); - accessListEntries.add(aclListEntries); - return accessListEntries; - } - - /** - * @param properties - * @return aceIp - */ - private AceIp getAceIp(Dictionary properties, - SourcePortRange srcPortRange, - DestinationPortRange destPortRange) { - /** - * Building Ace IPV4 Type - */ - String destIpv4 = get(properties, ACL_LIST_DEST_IPV4_KEY); - String srcIpv4 = get(properties, ACL_LIST_SRC_IPV4_KEY); - AceIpv4Builder aceIpv4Builder = new AceIpv4Builder(); - aceIp = null; - if (destIpv4 != null) { - Ipv4Prefix destinationIp = new Ipv4Prefix(destIpv4); - aceIpv4Builder.setDestinationIpv4Address(destinationIp); - } - if (srcIpv4 != null) { - Ipv4Prefix sourceIp = new Ipv4Prefix(srcIpv4); - aceIpv4Builder.setSourceIpv4Address(sourceIp); - } - if (destIpv4 != null || srcIpv4 != null) { - AceIpv4 aceIpv4 = aceIpv4Builder.build(); - AceIpBuilder aceIpBuilder = new AceIpBuilder(); - aceIpBuilder.setAceIpVersion(aceIpv4); - aceIpBuilder.setSourcePortRange(srcPortRange); - aceIpBuilder.setDestinationPortRange(destPortRange); - aceIp = aceIpBuilder.build(); - } - return aceIp; - } - - /** - * @param deviceEntry - * @return deviceMap - */ - private Map processDeviceEntry(String deviceEntry) { - if (deviceEntry == null) { - log.info("No content for Device Entry, so cannot proceed further."); - return null; - } - - Map deviceMap = new HashMap(); - log.info("Trying to convert Device Entry String: " + deviceEntry - + " to a Netconf Device Object"); - try { - URI uri = new URI(deviceEntry); - String path = uri.getPath(); - String userInfo = path.substring(path.lastIndexOf('@')); - String hostInfo = path.substring(path.lastIndexOf('@') + 1); - String[] infoSplit = userInfo.split(":"); - String username = infoSplit[0]; - String password = infoSplit[1]; - infoSplit = hostInfo.split(":"); - String hostIp = infoSplit[0]; - String hostPort = infoSplit[1]; - if (isNullOrEmpty(username) || isNullOrEmpty(password) - || isNullOrEmpty(hostIp) || isNullOrEmpty(hostPort)) { - log.warn("Bad Configuration Data: both user and device" - + " information parts of Configuration " + deviceEntry - + " should be non-nullable"); - } else { - deviceMap.put("hostIp", hostIp); - deviceMap.put("hostPort", hostPort); - deviceMap.put("username", username); - deviceMap.put("password", password); - } - } catch (ArrayIndexOutOfBoundsException aie) { - log.error("Error while reading config infromation from the config file: " - + "The user, host and device state infomation should be " - + "in the order 'userInfo@hostInfo:deviceState'" - + deviceEntry, aie); - } catch (URISyntaxException urie) { - log.error("Error while parsing config information for the device entry: " - + "Illegal character in path " + deviceEntry, - urie); - } catch (Exception e) { - log.error("Error while parsing config information for the device entry: " - + deviceEntry, e); - } - return deviceMap; - } - - @Override - public void applyFlowRule(FlowRule... flowRules) { - } - - @Override - public void removeFlowRule(FlowRule... flowRules) { - } - - private void applyRule() { - // applyFlowRule(flowRules);//currentl - } - - @Override - public void removeRulesById(ApplicationId id, FlowRule... flowRules) { - log.info("removal by app id not supported in null provider"); - } - - @Override - public void executeBatch(FlowRuleBatchOperation batch) { - - } - - private class StatisticTask implements TimerTask { - - @Override - public void run(Timeout to) throws Exception { - for (DeviceId devId : flowTable.keySet()) { - providerService.pushFlowMetrics(devId, flowTable - .getOrDefault(devId, Collections.emptySet())); - } - timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS); - - } - } -} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java deleted file mode 100644 index 4e5a2752..00000000 --- a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.flow.impl; - -import static org.onlab.util.Tools.delay; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; - -import org.slf4j.Logger; - -import com.tailf.jnc.Capabilities; -import com.tailf.jnc.JNCException; -import com.tailf.jnc.SSHConnection; -import com.tailf.jnc.SSHSession; - -/** - * This is to carry necessary information to connect and execute NETCONF - * operations. - */ -public class NetconfOperation { - private final Logger log = getLogger(NetconfOperation.class); - private static final int EVENTINTERVAL = 2000; - private static final int CONNECTION_CHECK_INTERVAL = 3; - private static final String INPUT_HELLO_XML_MSG = new StringBuilder( - "") - .append("") - .append("urn:ietf:params:netconf:base:1.0") - .append("").toString(); - - /** - * This will send a Xml message to the device. - * @param xmlMsg XML to send - * @param username user name - * @param password pass word - * @param deviceIp ip address of the device - * @param devicePort port on the device - */ - protected void sendXmlMessage(String xmlMsg, String username, - String password, String deviceIp, - Integer devicePort) { - SSHSession ssh = null; - try { - SSHConnection sshConnection = getConnection(username, password, - deviceIp, devicePort); - ssh = new SSHSession(sshConnection); - executeMessage(ssh, INPUT_HELLO_XML_MSG); - /* - * execute acl message - */ - executeMessage(ssh, xmlMsg); - - } catch (IOException e) { - log.error("Unable to send Hello Message to the device: ", e); - } catch (JNCException e) { - log.error("Authentication fail while sending Hello Message to the device: ", - e); - } catch (Exception e) { - log.error("Unable to send Hello Message to the device: ", e); - } finally { - log.debug("Closing the session after successful execution"); - if (ssh != null) { - ssh.close(); - } - } - } - - private void executeMessage(SSHSession ssh, String xmlMsg) - throws IOException, JNCException { - String helloRequestXML = xmlMsg.trim(); - - log.debug("Sending Hello"); - ssh.print(helloRequestXML); - ssh.flush(); - String xmlResponse = null; - int i = CONNECTION_CHECK_INTERVAL; - while (!ssh.ready() && i > 0) { - delay(EVENTINTERVAL); - i--; - } - - if (ssh.ready()) { - StringBuffer readOne = ssh.readOne(); - if (readOne == null) { - log.error("The Hello Contains No Capabilites"); - throw new JNCException( - JNCException.SESSION_ERROR, - "server does not support NETCONF base capability: " - + Capabilities.NETCONF_BASE_CAPABILITY); - } else { - xmlResponse = readOne.toString().trim(); - - log.debug("Reading Capabilities: " - + ssh.getSSHConnection().getGanymedConnection() - .getHostname()); - } - } - } - - /** - * To establish SSH Connection. - * - * @param username user name - * @param password pass word - * @param sshHost host - * @param sshPort port - * @return new SSH connection - * @throws IOException if connection fails - * @throws JNCException if connection causes an error - */ - public SSHConnection getConnection(String username, String password, - String sshHost, Integer sshPort) - throws IOException, JNCException { - SSHConnection sshConnection; - try { - sshConnection = new SSHConnection(sshHost, sshPort); - sshConnection.authenticateWithPassword(username, password); - } catch (IOException e) { - log.error("Unable to create a connection to the device: "); - throw e; - } catch (JNCException e) { - log.error("Failed to connect to the device: "); - throw e; - } - return sshConnection; - } - -} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java deleted file mode 100644 index 389f1669..00000000 --- a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.flow.impl; - -import static org.slf4j.LoggerFactory.getLogger; - -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.Namespace; -import org.jdom2.output.Format; -import org.jdom2.output.XMLOutputter; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.AccessList; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.AceType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceEth; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceIp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.AceIpVersion; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv6; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.DestinationPortRange; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.SourcePortRange; -import org.slf4j.Logger; - -/** - * Xml Builder to generate the xml according to given ACL model. - */ -public class XmlBuilder { - private final Logger log = getLogger(XmlBuilder.class); - - public String buildAclRequestXml(AccessList accessList) { - Document doc = new Document(); - Namespace namespaceRpc = Namespace - .getNamespace("urn:ietf:params:xml:ns:netconf:base:1.0"); - Namespace accessNamespaceRpc = Namespace - .getNamespace("urn:ietf:params:xml:ns:yang:ietf-acl"); - doc.setRootElement(new Element("rpc", namespaceRpc) - .setAttribute("message-id", "101")); - - /** - * Access list elements of given ACL model. - */ - Element access = new Element("access-list", accessNamespaceRpc); - access.addContent(new Element("acl-name", accessNamespaceRpc) - .setText(accessList.getAclName())); - // access.addContent(accessEntries); - - if (!accessList.getAccessListEntries().isEmpty() - && accessList.getAccessListEntries() != null) { - for (int accessEntryIntVlu = 0; accessEntryIntVlu < accessList - .getAccessListEntries().size(); accessEntryIntVlu++) { - access.addContent(getAccessEntries(accessEntryIntVlu, - accessList, - accessNamespaceRpc)); - } - } - - /** - * edit-config operation for given ACL model. - */ - Element editConfig = new Element("edit-config", namespaceRpc); - editConfig.addContent(new Element("target", namespaceRpc) - .addContent(new Element("running", namespaceRpc))); - editConfig.addContent(new Element("config", Namespace - .getNamespace("urn:ietf:params:xml:ns:netconf:base:1.0")) - .addContent(access)); - - doc.getRootElement().addContent(editConfig); - XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat()); - String outputString = xmlOutputter.outputString(doc); - - return outputString; - } - - /** - * access entries operation for given ACL model. - */ - private Element getAccessEntries(int accessEntryIntVlu, - AccessList accessList, - Namespace accessNamespaceRpc) { - - /** - * Port Number - */ - - int srcPortRangeLower = 0; - int srcPortRangeUpper = 0; - int destPortRangeLower = 0; - int destPortRangeUpper = 0; - - String sourceIpAdd = ""; - String destinationIpAdd = ""; - - /* - * checking accessList is null or not - */ - if (accessList != null) { - /* - * checking list entries are empty or null - */ - if (!accessList.getAccessListEntries().isEmpty() - && accessList.getAccessListEntries() != null) { - AceType aceType = accessList.getAccessListEntries() - .get(accessEntryIntVlu).getMatches().getAceType(); - - if (aceType instanceof AceIp) { - AceIp aceIp = (AceIp) aceType; - SourcePortRange sourcePortRange = aceIp - .getSourcePortRange(); - if (sourcePortRange != null) { - PortNumber lowerPort = sourcePortRange.getLowerPort(); - PortNumber upperPort = sourcePortRange.getUpperPort(); - - if (lowerPort != null) { - srcPortRangeLower = lowerPort.getValue(); - } - if (upperPort != null) { - srcPortRangeUpper = upperPort.getValue(); - } - } - DestinationPortRange destinationPortRange = aceIp - .getDestinationPortRange(); - - if (destinationPortRange != null) { - PortNumber lowerPort = destinationPortRange - .getLowerPort(); - if (lowerPort != null) { - destPortRangeLower = lowerPort.getValue(); - } - - PortNumber upperPort = destinationPortRange - .getUpperPort(); - if (upperPort != null) { - destPortRangeUpper = upperPort.getValue(); - } - - } - - AceIpVersion aceIpVersion = aceIp.getAceIpVersion(); - if (aceIpVersion instanceof AceIpv4) { - AceIpv4 obj = (AceIpv4) aceIpVersion; - destinationIpAdd = obj.getDestinationIpv4Address() - .getValue(); - sourceIpAdd = obj.getSourceIpv4Address().getValue(); - } else if (aceIpVersion instanceof AceIpv6) { - AceIpv6 obj = (AceIpv6) aceIpVersion; - destinationIpAdd = obj.getDestinationIpv6Address() - .getValue(); - sourceIpAdd = obj.getSourceIpv6Address().getValue(); - } - } else if (aceType instanceof AceEth) { - log.debug("Need to add execution loging for Ace Type Ethernet"); - } - } - } - - /** - * Matches elements to define IP address & Port range for given ACL - * model. - */ - Element matchesElement = new Element("matches", accessNamespaceRpc); - if (String.valueOf(srcPortRangeLower) != null - && !String.valueOf(srcPortRangeLower).isEmpty()) { - - matchesElement.addContent(new Element("source-port-range", - accessNamespaceRpc) - .addContent(new Element("lower-port", accessNamespaceRpc) - .setText(String.valueOf(srcPortRangeLower)))); - - matchesElement.addContent(new Element("source-port-range", - accessNamespaceRpc) - .addContent(new Element("upper-port", accessNamespaceRpc) - .setText(String.valueOf(srcPortRangeUpper)))); - - matchesElement.addContent(new Element("destination-port-range", - accessNamespaceRpc) - .addContent(new Element("lower-port", accessNamespaceRpc) - .setText(String.valueOf(destPortRangeLower)))); - - matchesElement.addContent(new Element("destination-port-range", - accessNamespaceRpc) - .addContent(new Element("upper-port", accessNamespaceRpc) - .setText(String.valueOf(destPortRangeUpper)))); - } - - if (destinationIpAdd != null && !destinationIpAdd.isEmpty()) { - matchesElement.addContent(new Element("destination-ipv4-address", - accessNamespaceRpc) - .setText(destinationIpAdd)); - } - if (sourceIpAdd != null && !sourceIpAdd.isEmpty()) { - matchesElement.addContent(new Element("source-ipv4-address", - accessNamespaceRpc) - .setText(sourceIpAdd)); - } - - /** - * Access entries elements for given ACL model. - */ - Element accessEntries = new Element("access-list-entries", - accessNamespaceRpc); - accessEntries.addContent(new Element("rule-name", accessNamespaceRpc) - .setText(accessList.getAccessListEntries() - .get(accessEntryIntVlu).getRuleName())); - accessEntries.addContent(matchesElement); - accessEntries.addContent(new Element("actions", accessNamespaceRpc) - .addContent(new Element("deny", accessNamespaceRpc))); - - return accessEntries; - } -} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java deleted file mode 100644 index b095fc9a..00000000 --- a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Provider that will accept any flow rules. - */ -package org.onosproject.provider.netconf.flow.impl; - diff --git a/framework/src/onos/providers/netconf/pom.xml b/framework/src/onos/providers/netconf/pom.xml index f73940fe..8c4681df 100644 --- a/framework/src/onos/providers/netconf/pom.xml +++ b/framework/src/onos/providers/netconf/pom.xml @@ -34,7 +34,6 @@ device app - flow diff --git a/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java b/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java index c5688419..68c536b9 100644 --- a/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java +++ b/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java @@ -168,7 +168,7 @@ public class NullProviders { @Activate - public void activate(ComponentContext context) { + public void activate() { cfgService.registerProperties(getClass()); deviceProviderService = deviceProviderRegistry.register(deviceProvider); @@ -180,7 +180,7 @@ public class NullProviders { } @Deactivate - public void deactivate(ComponentContext context) { + public void deactivate() { cfgService.unregisterProperties(getClass(), false); tearDown(); diff --git a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java index a7e334f4..4ceb425c 100644 --- a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java +++ b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java @@ -516,7 +516,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); - SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); OFExpPortDescPropOpticalTransport firstProp = port.getProperties().get(0); OFPortOpticalTransportSignalType sigType = firstProp.getPortSignalType(); @@ -560,16 +560,19 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr /** * Creates an annotation for the port name if one is available. * - * @param port description of the port + * @param portName the port name + * @param portMac the port mac * @return annotation containing the port name if one is found, * null otherwise */ - private SparseAnnotations makePortNameAnnotation(String port) { + private SparseAnnotations makePortAnnotation(String portName, String portMac) { SparseAnnotations annotations = null; - String portName = Strings.emptyToNull(port); + String pName = Strings.emptyToNull(portName); + String pMac = Strings.emptyToNull(portMac); if (portName != null) { annotations = DefaultAnnotations.builder() - .set(AnnotationKeys.PORT_NAME, portName).build(); + .set(AnnotationKeys.PORT_NAME, pName) + .set(AnnotationKeys.PORT_MAC, pMac).build(); } return annotations; } @@ -586,7 +589,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER; - SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); return new DefaultPortDescription(portNo, enabled, type, portSpeed(port), annotations); } @@ -607,7 +610,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); - SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); if (port.getVersion() == OFVersion.OF_13 && ptype == PortDescPropertyType.OPTICAL_TRANSPORT) { @@ -649,7 +652,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr // FIXME when Calient OF agent reports port status boolean enabled = true; - SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); // S160 data sheet // Wavelength range: 1260 - 1630 nm, grid is irrelevant for this type of switch @@ -664,7 +667,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr } else { PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER; - SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); return new DefaultPortDescription(portNo, false, type, portSpeed(port), annotations); } diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java index d4494f18..b12d8a60 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java @@ -27,6 +27,7 @@ import org.onlab.packet.VlanId; import org.onosproject.core.DefaultGroupId; import org.onosproject.net.DeviceId; import org.onosproject.net.Lambda; +import org.onosproject.net.OduSignalId; import org.onosproject.net.PortNumber; import org.onosproject.net.driver.DefaultDriverData; import org.onosproject.net.driver.DefaultDriverHandler; @@ -83,15 +84,21 @@ import org.projectfloodlight.openflow.types.U32; import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U8; import org.projectfloodlight.openflow.types.VlanPcp; +import org.projectfloodlight.openflow.types.OduSignalID; import org.slf4j.Logger; import java.util.List; import static org.onosproject.net.flow.criteria.Criteria.matchLambda; import static org.onosproject.net.flow.criteria.Criteria.matchOchSignalType; +import static org.onosproject.net.flow.criteria.Criteria.matchOduSignalType; +import static org.onosproject.net.flow.criteria.Criteria.matchOduSignalId; +import static org.onosproject.net.flow.instructions.Instructions.modL0Lambda; +import static org.onosproject.net.flow.instructions.Instructions.modL1OduSignalId; import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupChannelSpacing; import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupGridType; import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOchSignalType; +import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOduSignalType; import static org.slf4j.LoggerFactory.getLogger; public class FlowEntryBuilder { @@ -454,6 +461,29 @@ public class FlowEntryBuilder { builder.extension(interpreter.mapAction(action), DeviceId.deviceId(Dpid.uri(dpid))); } break; + case EXP_ODU_SIG_ID: + @SuppressWarnings("unchecked") + OFOxm oduID = (OFOxm) oxm; + OduSignalID oduSignalID = oduID.getValue(); + OduSignalId oduSignalId = OduSignalId.oduSignalId(oduSignalID.getTpn(), + oduSignalID.getTslen(), + oduSignalID.getTsmap()); + builder.add(modL1OduSignalId(oduSignalId)); + break; + case EXP_OCH_SIG_ID: + try { + @SuppressWarnings("unchecked") + OFOxm ochId = (OFOxm) oxm; + CircuitSignalID circuitSignalID = ochId.getValue(); + builder.add(modL0Lambda(Lambda.ochSignal( + lookupGridType(circuitSignalID.getGridType()), + lookupChannelSpacing(circuitSignalID.getChannelSpacing()), + circuitSignalID.getChannelNumber(), circuitSignalID.getSpectralWidth()))); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + break; + } + break; case ARP_OP: case ARP_SHA: case ARP_SPA: @@ -501,6 +531,8 @@ public class FlowEntryBuilder { case OCH_SIGTYPE_BASIC: case SCTP_DST: case SCTP_SRC: + case EXP_ODU_SIGTYPE: + case EXP_OCH_SIGTYPE: default: log.warn("Set field type {} not yet implemented.", oxm.getMatchField().id); break; @@ -704,6 +736,41 @@ public class FlowEntryBuilder { U8 sigType = match.get(MatchField.OCH_SIGTYPE); builder.add(matchOchSignalType(lookupOchSignalType((byte) sigType.getValue()))); break; + case EXP_OCH_SIG_ID: + try { + CircuitSignalID expSigId = match.get(MatchField.EXP_OCH_SIG_ID); + builder.add(matchLambda(Lambda.ochSignal( + lookupGridType(expSigId.getGridType()), lookupChannelSpacing(expSigId.getChannelSpacing()), + expSigId.getChannelNumber(), expSigId.getSpectralWidth()))); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + break; + } + break; + case EXP_OCH_SIGTYPE: + try { + U8 expOchSigType = match.get(MatchField.EXP_OCH_SIGTYPE); + builder.add(matchOchSignalType(lookupOchSignalType((byte) expOchSigType.getValue()))); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + break; + } + break; + case EXP_ODU_SIG_ID: + OduSignalId oduSignalId = OduSignalId.oduSignalId(match.get(MatchField.EXP_ODU_SIG_ID).getTpn(), + match.get(MatchField.EXP_ODU_SIG_ID).getTslen(), + match.get(MatchField.EXP_ODU_SIG_ID).getTsmap()); + builder.add(matchOduSignalId(oduSignalId)); + break; + case EXP_ODU_SIGTYPE: + try { + U8 oduSigType = match.get(MatchField.EXP_ODU_SIGTYPE); + builder.add(matchOduSignalType(lookupOduSignalType((byte) oduSigType.getValue()))); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + break; + } + break; case TUNNEL_ID: long tunnelId = match.get(MatchField.TUNNEL_ID).getValue(); builder.matchTunnelId(tunnelId); diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java index 2a8d2010..dcd7b0fc 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java @@ -20,8 +20,13 @@ import org.onlab.packet.Ip4Prefix; import org.onlab.packet.Ip6Address; import org.onlab.packet.Ip6Prefix; import org.onlab.packet.VlanId; +import org.onosproject.net.DeviceId; import org.onosproject.net.OchSignal; +import org.onosproject.net.driver.DefaultDriverData; +import org.onosproject.net.driver.DefaultDriverHandler; +import org.onosproject.net.driver.Driver; import org.onosproject.net.driver.DriverService; +import org.onosproject.net.OduSignalId; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.criteria.ArpHaCriterion; @@ -30,6 +35,8 @@ import org.onosproject.net.flow.criteria.ArpPaCriterion; import org.onosproject.net.flow.criteria.Criterion; import org.onosproject.net.flow.criteria.EthCriterion; import org.onosproject.net.flow.criteria.EthTypeCriterion; +import org.onosproject.net.flow.criteria.ExtensionCriterion; +import org.onosproject.net.flow.criteria.ExtensionSelector; import org.onosproject.net.flow.criteria.IPCriterion; import org.onosproject.net.flow.criteria.IPDscpCriterion; import org.onosproject.net.flow.criteria.IPEcnCriterion; @@ -47,6 +54,8 @@ import org.onosproject.net.flow.criteria.MplsBosCriterion; import org.onosproject.net.flow.criteria.MplsCriterion; import org.onosproject.net.flow.criteria.OchSignalCriterion; import org.onosproject.net.flow.criteria.OchSignalTypeCriterion; +import org.onosproject.net.flow.criteria.OduSignalIdCriterion; +import org.onosproject.net.flow.criteria.OduSignalTypeCriterion; import org.onosproject.net.flow.criteria.PortCriterion; import org.onosproject.net.flow.criteria.SctpPortCriterion; import org.onosproject.net.flow.criteria.TcpPortCriterion; @@ -54,12 +63,14 @@ import org.onosproject.net.flow.criteria.TunnelIdCriterion; import org.onosproject.net.flow.criteria.UdpPortCriterion; import org.onosproject.net.flow.criteria.VlanIdCriterion; import org.onosproject.net.flow.criteria.VlanPcpCriterion; +import org.onosproject.openflow.controller.ExtensionSelectorInterpreter; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFFlowAdd; import org.projectfloodlight.openflow.protocol.OFFlowDelete; import org.projectfloodlight.openflow.protocol.OFFlowMod; import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.protocol.oxm.OFOxm; import org.projectfloodlight.openflow.types.ArpOpcode; import org.projectfloodlight.openflow.types.CircuitSignalID; import org.projectfloodlight.openflow.types.EthType; @@ -84,6 +95,7 @@ import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U8; import org.projectfloodlight.openflow.types.VlanPcp; import org.projectfloodlight.openflow.types.VlanVid; +import org.projectfloodlight.openflow.types.OduSignalID; import org.slf4j.Logger; import java.util.Optional; @@ -102,6 +114,7 @@ public abstract class FlowModBuilder { private final TrafficSelector selector; protected final Long xid; protected final Optional driverService; + protected final DeviceId deviceId; /** * Creates a new flow mod builder. @@ -142,6 +155,7 @@ public abstract class FlowModBuilder { this.selector = flowRule.selector(); this.xid = xid.orElse(0L); this.driverService = driverService; + this.deviceId = flowRule.deviceId(); } /** @@ -398,7 +412,7 @@ public abstract class FlowModBuilder { OchSignal signal = ochSignalCriterion.lambda(); byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType()); byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing()); - mBuilder.setExact(MatchField.OCH_SIGID, + mBuilder.setExact(MatchField.EXP_OCH_SIG_ID, new CircuitSignalID(gridType, channelSpacing, (short) signal.spacingMultiplier(), (short) signal.slotGranularity())); } catch (NoMappingFoundException e) { @@ -406,9 +420,30 @@ public abstract class FlowModBuilder { } break; case OCH_SIGTYPE: - OchSignalTypeCriterion sc = (OchSignalTypeCriterion) c; - byte signalType = OpenFlowValueMapper.lookupOchSignalType(sc.signalType()); - mBuilder.setExact(MatchField.OCH_SIGTYPE, U8.of(signalType)); + try { + OchSignalTypeCriterion sc = (OchSignalTypeCriterion) c; + byte signalType = OpenFlowValueMapper.lookupOchSignalType(sc.signalType()); + mBuilder.setExact(MatchField.EXP_OCH_SIGTYPE, U8.of(signalType)); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + } + break; + case ODU_SIGID: + OduSignalIdCriterion oduSignalIdCriterion = (OduSignalIdCriterion) c; + OduSignalId oduSignalId = oduSignalIdCriterion.oduSignalId(); + mBuilder.setExact(MatchField.EXP_ODU_SIG_ID, + new OduSignalID((short) oduSignalId.tributaryPortNumber(), + (short) oduSignalId.tributarySlotLength(), + oduSignalId.tributarySlotBitmap())); + break; + case ODU_SIGTYPE: + try { + OduSignalTypeCriterion oduSignalTypeCriterion = (OduSignalTypeCriterion) c; + byte oduSigType = OpenFlowValueMapper.lookupOduSignalType(oduSignalTypeCriterion.signalType()); + mBuilder.setExact(MatchField.EXP_ODU_SIGTYPE, U8.of(oduSigType)); + } catch (NoMappingFoundException e) { + log.warn(e.getMessage()); + } break; case TUNNEL_ID: TunnelIdCriterion tunnelId = (TunnelIdCriterion) c; @@ -446,8 +481,24 @@ public abstract class FlowModBuilder { mBuilder.setExact(MatchField.ARP_TPA, IPv4Address.of(arpPaCriterion.ip().toInt())); break; + case EXTENSION: + ExtensionCriterion extensionCriterion = (ExtensionCriterion) c; + OFOxm oxm = buildExtensionOxm(extensionCriterion.extensionSelector()); + if (oxm == null) { + log.warn("Unable to build extension selector"); + break; + } + + if (oxm.isMasked()) { + mBuilder.setMasked(oxm.getMatchField(), oxm.getValue(), oxm.getMask()); + } else { + mBuilder.setExact(oxm.getMatchField(), oxm.getValue()); + } + + break; case MPLS_TC: case PBB_ISID: + // TODO: need to implement PBB-ISID case when OpenFlowJ is ready default: log.warn("Match type {} not yet implemented.", c.type()); } @@ -473,4 +524,21 @@ public abstract class FlowModBuilder { return factory; } + private OFOxm buildExtensionOxm(ExtensionSelector extension) { + if (!driverService.isPresent()) { + log.error("No driver service present"); + return null; + } + Driver driver = driverService.get().getDriver(deviceId); + if (driver.hasBehaviour(ExtensionSelectorInterpreter.class)) { + DefaultDriverHandler handler = + new DefaultDriverHandler(new DefaultDriverData(driver, deviceId)); + ExtensionSelectorInterpreter interpreter = handler.behaviour(ExtensionSelectorInterpreter.class); + + return interpreter.mapSelector(factory(), extension); + } + + return null; + } + } diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java index bdea09da..d4ebb4fd 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java @@ -181,6 +181,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { acts.add(queueBuilder.build()); break; case L0MODIFICATION: + case L1MODIFICATION: case GROUP: case TABLE: case METADATA: diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java index 90def432..a3182e72 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java @@ -18,8 +18,8 @@ package org.onosproject.provider.of.flow.impl; import com.google.common.collect.Lists; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; -import org.onosproject.net.DeviceId; import org.onosproject.net.OchSignal; +import org.onosproject.net.OduSignalId; import org.onosproject.net.PortNumber; import org.onosproject.net.driver.DefaultDriverData; import org.onosproject.net.driver.DefaultDriverHandler; @@ -36,6 +36,8 @@ import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction; import org.onosproject.net.flow.instructions.L0ModificationInstruction; import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction; import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction; +import org.onosproject.net.flow.instructions.L1ModificationInstruction; +import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction; @@ -46,6 +48,9 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPc import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions; import org.onosproject.net.flow.instructions.L3ModificationInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction; import org.onosproject.net.flow.instructions.L4ModificationInstruction; import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction; @@ -62,6 +67,7 @@ import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue; import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.oxm.OFOxm; +import org.projectfloodlight.openflow.types.ArpOpcode; import org.projectfloodlight.openflow.types.CircuitSignalID; import org.projectfloodlight.openflow.types.EthType; import org.projectfloodlight.openflow.types.IPv4Address; @@ -73,6 +79,7 @@ import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFGroup; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFVlanVidMatch; +import org.projectfloodlight.openflow.types.OduSignalID; import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U32; @@ -95,7 +102,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder { private static final int OFPCML_NO_BUFFER = 0xffff; private final TrafficTreatment treatment; - private final DeviceId deviceId; /** * Constructor for a flow mod builder for OpenFlow 1.3. @@ -110,7 +116,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder { super(flowRule, factory, xid, driverService); this.treatment = flowRule.treatment(); - this.deviceId = flowRule.deviceId(); } @Override @@ -233,6 +238,9 @@ public class FlowModBuilderVer13 extends FlowModBuilder { case L0MODIFICATION: actions.add(buildL0Modification(i)); break; + case L1MODIFICATION: + actions.add(buildL1Modification(i)); + break; case L2MODIFICATION: actions.add(buildL2Modification(i)); break; @@ -302,20 +310,31 @@ public class FlowModBuilderVer13 extends FlowModBuilder { private OFAction buildL0Modification(Instruction i) { L0ModificationInstruction l0m = (L0ModificationInstruction) i; + OFOxm oxm = null; switch (l0m.subtype()) { case LAMBDA: return buildModLambdaInstruction((ModLambdaInstruction) i); case OCH: try { - return buildModOchSignalInstruction((ModOchSignalInstruction) i); + ModOchSignalInstruction modOchSignalInstruction = (ModOchSignalInstruction) l0m; + OchSignal signal = modOchSignalInstruction.lambda(); + byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType()); + byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing()); + oxm = factory().oxms().expOchSigId( + new CircuitSignalID(gridType, channelSpacing, + (short) signal.spacingMultiplier(), (short) signal.slotGranularity())); } catch (NoMappingFoundException e) { log.warn(e.getMessage()); break; } + break; default: log.warn("Unimplemented action type {}.", l0m.subtype()); break; } + if (oxm != null) { + return factory().actions().buildSetField().setField(oxm).build(); + } return null; } @@ -335,6 +354,31 @@ public class FlowModBuilderVer13 extends FlowModBuilder { )); } + private OFAction buildL1Modification(Instruction i) { + L1ModificationInstruction l1m = (L1ModificationInstruction) i; + OFOxm oxm = null; + switch (l1m.subtype()) { + case ODU_SIGID: + ModOduSignalIdInstruction modOduSignalIdInstruction = (ModOduSignalIdInstruction) l1m; + OduSignalId oduSignalId = modOduSignalIdInstruction.oduSignalId(); + + OduSignalID oduSignalID = new OduSignalID((short) oduSignalId.tributaryPortNumber(), + (short) oduSignalId.tributarySlotLength(), + oduSignalId.tributarySlotBitmap()); + + oxm = factory().oxms().expOduSigId(oduSignalID); + break; + default: + log.warn("Unimplemented action type {}.", l1m.subtype()); + break; + } + + if (oxm != null) { + return factory().actions().buildSetField().setField(oxm).build(); + } + return null; + } + private OFAction buildL2Modification(Instruction i) { L2ModificationInstruction l2m = (L2ModificationInstruction) i; ModEtherInstruction eth; @@ -433,6 +477,19 @@ public class FlowModBuilderVer13 extends FlowModBuilder { int flowLabel = flowLabelInstruction.flowLabel(); oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel)); break; + case ARP_SPA: + ModArpIPInstruction aip = (ModArpIPInstruction) i; + ip4 = aip.ip().getIp4Address(); + oxm = factory().oxms().arpSpa(IPv4Address.of(ip4.toInt())); + break; + case ARP_SHA: + ModArpEthInstruction ei = (ModArpEthInstruction) i; + oxm = factory().oxms().arpSha(MacAddress.of(ei.mac().toLong())); + break; + case ARP_OP: + ModArpOpInstruction oi = (ModArpOpInstruction) i; + oxm = factory().oxms().arpOp(ArpOpcode.of((int) oi.op())); + break; case DEC_TTL: return factory().actions().decNwTtl(); case TTL_IN: diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java index d5186fa9..aa8df947 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java @@ -1,882 +1,882 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.provider.of.flow.impl; - -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.onosproject.net.flow.DefaultTypedFlowEntry; -import org.onosproject.net.flow.FlowEntry; -import org.onosproject.net.flow.FlowId; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.StoredFlowEntry; -import org.onosproject.net.flow.TypedStoredFlowEntry; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.openflow.controller.OpenFlowSwitch; -import org.onosproject.openflow.controller.RoleState; -import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; -import org.projectfloodlight.openflow.protocol.match.Match; -import org.projectfloodlight.openflow.types.OFPort; -import org.projectfloodlight.openflow.types.TableId; -import org.slf4j.Logger; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.net.flow.TypedStoredFlowEntry.FlowLiveType; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Efficiently and adaptively collects flow statistics for the specified switch. - */ -public class NewAdaptiveFlowStatsCollector { - - private final Logger log = getLogger(getClass()); - - private final OpenFlowSwitch sw; - - private ScheduledExecutorService adaptiveFlowStatsScheduler = - Executors.newScheduledThreadPool(4, groupedThreads("onos/flow", "device-stats-collector-%d")); - private ScheduledFuture calAndShortFlowsThread; - private ScheduledFuture midFlowsThread; - private ScheduledFuture longFlowsThread; - - // Task that calculates all flowEntries' FlowLiveType and collects stats IMMEDIATE flows every calAndPollInterval - private CalAndShortFlowsTask calAndShortFlowsTask; - // Task that collects stats MID flows every 2*calAndPollInterval - private MidFlowsTask midFlowsTask; - // Task that collects stats LONG flows every 3*calAndPollInterval - private LongFlowsTask longFlowsTask; - - private static final int CAL_AND_POLL_TIMES = 1; // must be always 0 - private static final int MID_POLL_TIMES = 2; // variable greater or equal than 1 - private static final int LONG_POLL_TIMES = 3; // variable greater or equal than MID_POLL_TIMES - //TODO: make ENTIRE_POLL_TIMES configurable with enable or disable - // must be variable greater or equal than common multiple of MID_POLL_TIMES and LONG_POLL_TIMES - private static final int ENTIRE_POLL_TIMES = 6; - - private static final int DEFAULT_CAL_AND_POLL_FREQUENCY = 5; - private static final int MIN_CAL_AND_POLL_FREQUENCY = 2; - private static final int MAX_CAL_AND_POLL_FREQUENCY = 60; - - private int calAndPollInterval; // CAL_AND_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; - private int midPollInterval; // MID_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; - private int longPollInterval; // LONG_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; - // only used for checking condition at each task if it collects entire flows from a given switch or not - private int entirePollInterval; // ENTIRE_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; - - // Number of call count of each Task, - // for undoing collection except only entire flows collecting task in CalAndShortFlowsTask - private int callCountCalAndShortFlowsTask = 0; // increased CAL_AND_POLL_TIMES whenever Task is called - private int callCountMidFlowsTask = 0; // increased MID_POLL_TIMES whenever Task is called - private int callCountLongFlowsTask = 0; // increased LONG_POLL_TIMES whenever Task is called - - private InternalDeviceFlowTable deviceFlowTable = new InternalDeviceFlowTable(); - - private boolean isFirstTimeStart = true; - - public static final long NO_FLOW_MISSING_XID = (-1); - private long flowMissingXid = NO_FLOW_MISSING_XID; - - /** - * Creates a new adaptive collector for the given switch and default cal_and_poll frequency. - * - * @param sw switch to pull - * @param pollInterval cal and immediate poll frequency in seconds - */ - NewAdaptiveFlowStatsCollector(OpenFlowSwitch sw, int pollInterval) { - this.sw = sw; - - initMemberVars(pollInterval); - } - - // check calAndPollInterval validity and set all pollInterval values and finally initialize each task call count - private void initMemberVars(int pollInterval) { - if (pollInterval < MIN_CAL_AND_POLL_FREQUENCY) { - this.calAndPollInterval = MIN_CAL_AND_POLL_FREQUENCY; - } else if (pollInterval >= MAX_CAL_AND_POLL_FREQUENCY) { - this.calAndPollInterval = MAX_CAL_AND_POLL_FREQUENCY; - } else { - this.calAndPollInterval = pollInterval; - } - - calAndPollInterval = CAL_AND_POLL_TIMES * calAndPollInterval; - midPollInterval = MID_POLL_TIMES * calAndPollInterval; - longPollInterval = LONG_POLL_TIMES * calAndPollInterval; - entirePollInterval = ENTIRE_POLL_TIMES * calAndPollInterval; - - callCountCalAndShortFlowsTask = 0; - callCountMidFlowsTask = 0; - callCountLongFlowsTask = 0; - - flowMissingXid = NO_FLOW_MISSING_XID; - } - - /** - * Adjusts adaptive poll frequency. - * - * @param pollInterval poll frequency in seconds - */ - synchronized void adjustCalAndPollInterval(int pollInterval) { - initMemberVars(pollInterval); - - if (calAndShortFlowsThread != null) { - calAndShortFlowsThread.cancel(false); - } - if (midFlowsThread != null) { - midFlowsThread.cancel(false); - } - if (longFlowsThread != null) { - longFlowsThread.cancel(false); - } - - calAndShortFlowsTask = new CalAndShortFlowsTask(); - calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - calAndShortFlowsTask, - 0, - calAndPollInterval, - TimeUnit.SECONDS); - - midFlowsTask = new MidFlowsTask(); - midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - midFlowsTask, - 0, - midPollInterval, - TimeUnit.SECONDS); - - longFlowsTask = new LongFlowsTask(); - longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - longFlowsTask, - 0, - longPollInterval, - TimeUnit.SECONDS); - - log.debug("calAndPollInterval=" + calAndPollInterval + "is adjusted"); - } - - private class CalAndShortFlowsTask implements Runnable { - @Override - public void run() { - if (sw.getRole() == RoleState.MASTER) { - log.trace("CalAndShortFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); - - if (isFirstTimeStart) { - // isFirstTimeStart, get entire flow stats from a given switch sw - log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats at first time start for {}", - sw.getStringId()); - ofFlowStatsRequestAllSend(); - - callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; - isFirstTimeStart = false; - } else if (callCountCalAndShortFlowsTask == ENTIRE_POLL_TIMES) { - // entire_poll_times, get entire flow stats from a given switch sw - log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats for {}", sw.getStringId()); - ofFlowStatsRequestAllSend(); - - callCountCalAndShortFlowsTask = CAL_AND_POLL_TIMES; - //TODO: check flows deleted in switch, but exist in controller flow table, then remove them - // - } else { - calAndShortFlowsTaskInternal(); - callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; - } - } - } - } - - // send openflow flow stats request message with getting all flow entries to a given switch sw - private void ofFlowStatsRequestAllSend() { - OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() - .setMatch(sw.factory().matchWildcardAll()) - .setTableId(TableId.ALL) - .setOutPort(OFPort.NO_MASK) - .build(); - - synchronized (this) { - // set the request xid to check the reply in OpenFlowRuleProvider - // After processing the reply of this request message, - // this must be set to NO_FLOW_MISSING_XID(-1) by provider - setFlowMissingXid(request.getXid()); - log.debug("ofFlowStatsRequestAllSend,Request={},for {}", request.toString(), sw.getStringId()); - - sw.sendMsg(request); - } - } - - // send openflow flow stats request message with getting the specific flow entry(fe) to a given switch sw - private void ofFlowStatsRequestFlowSend(FlowEntry fe) { - // set find match - Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(), - Optional.empty()).buildMatch(); - // set find tableId - TableId tableId = TableId.of(fe.tableId()); - // set output port - Instruction ins = fe.treatment().allInstructions().stream() - .filter(i -> (i.type() == Instruction.Type.OUTPUT)) - .findFirst() - .orElse(null); - OFPort ofPort = OFPort.NO_MASK; - if (ins != null) { - Instructions.OutputInstruction out = (Instructions.OutputInstruction) ins; - ofPort = OFPort.of((int) ((out.port().toLong()))); - } - - OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() - .setMatch(match) - .setTableId(tableId) - .setOutPort(ofPort) - .build(); - - synchronized (this) { - if (getFlowMissingXid() != NO_FLOW_MISSING_XID) { - log.debug("ofFlowStatsRequestFlowSend: previous FlowStatsRequestAll does not be processed yet," - + " set no flow missing xid anyway, for {}", - sw.getStringId()); - setFlowMissingXid(NO_FLOW_MISSING_XID); - } - - sw.sendMsg(request); - } - } - - private void calAndShortFlowsTaskInternal() { - deviceFlowTable.checkAndMoveLiveFlowAll(); - - deviceFlowTable.getShortFlows().forEach(fe -> { - ofFlowStatsRequestFlowSend(fe); - }); - } - - private class MidFlowsTask implements Runnable { - @Override - public void run() { - if (sw.getRole() == RoleState.MASTER) { - log.trace("MidFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); - - // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw - if (callCountMidFlowsTask == ENTIRE_POLL_TIMES) { - callCountMidFlowsTask = MID_POLL_TIMES; - } else { - midFlowsTaskInternal(); - callCountMidFlowsTask += MID_POLL_TIMES; - } - } - } - } - - private void midFlowsTaskInternal() { - deviceFlowTable.getMidFlows().forEach(fe -> { - ofFlowStatsRequestFlowSend(fe); - }); - } - - private class LongFlowsTask implements Runnable { - @Override - public void run() { - if (sw.getRole() == RoleState.MASTER) { - log.trace("LongFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); - - // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw - if (callCountLongFlowsTask == ENTIRE_POLL_TIMES) { - callCountLongFlowsTask = LONG_POLL_TIMES; - } else { - longFlowsTaskInternal(); - callCountLongFlowsTask += LONG_POLL_TIMES; - } - } - } - } - - private void longFlowsTaskInternal() { - deviceFlowTable.getLongFlows().forEach(fe -> { - ofFlowStatsRequestFlowSend(fe); - }); - } - - /** - * start adaptive flow statistic collection. - * - */ - public synchronized void start() { - log.debug("Starting AdaptiveStats collection thread for {}", sw.getStringId()); - callCountCalAndShortFlowsTask = 0; - callCountMidFlowsTask = 0; - callCountLongFlowsTask = 0; - - isFirstTimeStart = true; - - // Initially start polling quickly. Then drop down to configured value - calAndShortFlowsTask = new CalAndShortFlowsTask(); - calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - calAndShortFlowsTask, - 1, - calAndPollInterval, - TimeUnit.SECONDS); - - midFlowsTask = new MidFlowsTask(); - midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - midFlowsTask, - 1, - midPollInterval, - TimeUnit.SECONDS); - - longFlowsTask = new LongFlowsTask(); - longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( - longFlowsTask, - 1, - longPollInterval, - TimeUnit.SECONDS); - - log.info("Started"); - } - - /** - * stop adaptive flow statistic collection. - * - */ - public synchronized void stop() { - log.debug("Stopping AdaptiveStats collection thread for {}", sw.getStringId()); - if (calAndShortFlowsThread != null) { - calAndShortFlowsThread.cancel(true); - } - if (midFlowsThread != null) { - midFlowsThread.cancel(true); - } - if (longFlowsThread != null) { - longFlowsThread.cancel(true); - } - - adaptiveFlowStatsScheduler.shutdownNow(); - - isFirstTimeStart = false; - - log.info("Stopped"); - } - - /** - * add typed flow entry from flow rule into the internal flow table. - * - * @param flowRules the flow rules - * - */ - public synchronized void addWithFlowRule(FlowRule... flowRules) { - for (FlowRule fr : flowRules) { - // First remove old entry unconditionally, if exist - deviceFlowTable.remove(fr); - - // add new flow entry, we suppose IMMEDIATE_FLOW - TypedStoredFlowEntry newFlowEntry = new DefaultTypedFlowEntry(fr, - FlowLiveType.IMMEDIATE_FLOW); - deviceFlowTable.addWithCalAndSetFlowLiveType(newFlowEntry); - } - } - - /** - * add or update typed flow entry from flow entry into the internal flow table. - * - * @param flowEntries the flow entries - * - */ - public synchronized void addOrUpdateFlows(FlowEntry... flowEntries) { - for (FlowEntry fe : flowEntries) { - // check if this new rule is an update to an existing entry - TypedStoredFlowEntry stored = deviceFlowTable.getFlowEntry(fe); - - if (stored != null) { - // duplicated flow entry is collected!, just skip - if (fe.bytes() == stored.bytes() && fe.packets() == stored.packets() - && fe.life() == stored.life()) { - log.debug("addOrUpdateFlows:, FlowId=" + Long.toHexString(fe.id().value()) - + ",is DUPLICATED stats collection, just skip." - + " AdaptiveStats collection thread for {}", - sw.getStringId()); - - stored.setLastSeen(); - continue; - } else if (fe.life() < stored.life()) { - // Invalid updates the stats values, i.e., bytes, packets, durations ... - log.debug("addOrUpdateFlows():" + - " Invalid Flow Update! The new life is SMALLER than the previous one, jus skip." + - " new flowId=" + Long.toHexString(fe.id().value()) + - ", old flowId=" + Long.toHexString(stored.id().value()) + - ", new bytes=" + fe.bytes() + ", old bytes=" + stored.bytes() + - ", new life=" + fe.life() + ", old life=" + stored.life() + - ", new lastSeen=" + fe.lastSeen() + ", old lastSeen=" + stored.lastSeen()); - // go next - stored.setLastSeen(); - continue; - } - - // update now - stored.setLife(fe.life()); - stored.setPackets(fe.packets()); - stored.setBytes(fe.bytes()); - stored.setLastSeen(); - if (stored.state() == FlowEntry.FlowEntryState.PENDING_ADD) { - // flow is really RULE_ADDED - stored.setState(FlowEntry.FlowEntryState.ADDED); - } - // flow is RULE_UPDATED, skip adding and just updating flow live table - //deviceFlowTable.calAndSetFlowLiveType(stored); - continue; - } - - // add new flow entry, we suppose IMMEDIATE_FLOW - TypedStoredFlowEntry newFlowEntry = new DefaultTypedFlowEntry(fe, - FlowLiveType.IMMEDIATE_FLOW); - deviceFlowTable.addWithCalAndSetFlowLiveType(newFlowEntry); - } - } - - /** - * remove typed flow entry from the internal flow table. - * - * @param flowRules the flow entries - * - */ - public synchronized void removeFlows(FlowRule... flowRules) { - for (FlowRule rule : flowRules) { - deviceFlowTable.remove(rule); - } - } - - // same as removeFlows() function - /** - * remove typed flow entry from the internal flow table. - * - * @param flowRules the flow entries - * - */ - public void flowRemoved(FlowRule... flowRules) { - removeFlows(flowRules); - } - - // same as addOrUpdateFlows() function - /** - * add or update typed flow entry from flow entry into the internal flow table. - * - * @param flowEntries the flow entry list - * - */ - public void pushFlowMetrics(List flowEntries) { - flowEntries.forEach(fe -> { - addOrUpdateFlows(fe); - }); - } - - /** - * returns flowMissingXid that indicates the execution of flowMissing process or not(NO_FLOW_MISSING_XID(-1)). - * - * @return xid of missing flow - */ - public long getFlowMissingXid() { - return flowMissingXid; - } - - /** - * set flowMissingXid, namely OFFlowStatsRequest match any ALL message Id. - * - * @param flowMissingXid the OFFlowStatsRequest message Id - * - */ - public void setFlowMissingXid(long flowMissingXid) { - this.flowMissingXid = flowMissingXid; - } - - private class InternalDeviceFlowTable { - - private final Map> - flowEntries = Maps.newConcurrentMap(); - - private final Set shortFlows = new HashSet<>(); - private final Set midFlows = new HashSet<>(); - private final Set longFlows = new HashSet<>(); - - // Assumed latency adjustment(default=500 millisecond) between FlowStatsRequest and Reply - private final long latencyFlowStatsRequestAndReplyMillis = 500; - - - // Statistics for table operation - private long addCount = 0, addWithSetFlowLiveTypeCount = 0; - private long removeCount = 0; - - /** - * Resets all count values with zero. - * - */ - public void resetAllCount() { - addCount = 0; - addWithSetFlowLiveTypeCount = 0; - removeCount = 0; - } - - // get set of flow entries for the given flowId - private Set getFlowEntriesInternal(FlowId flowId) { - return flowEntries.computeIfAbsent(flowId, id -> Sets.newCopyOnWriteArraySet()); - } - - // get flow entry for the given flow rule - private TypedStoredFlowEntry getFlowEntryInternal(FlowRule rule) { - Set flowEntries = getFlowEntriesInternal(rule.id()); - return flowEntries.stream() - .filter(entry -> Objects.equal(entry, rule)) - .findAny() - .orElse(null); - } - - // get the flow entries for all flows in flow table - private Set getFlowEntriesInternal() { - Set result = Sets.newHashSet(); - - flowEntries.values().forEach(result::addAll); - return result; - } - - /** - * Gets the number of flow entry in flow table. - * - * @return the number of flow entry. - * - */ - public long getFlowCount() { - return flowEntries.values().stream().mapToLong(Set::size).sum(); - } - - /** - * Gets the number of flow entry in flow table. - * - * @param rule the flow rule - * @return the typed flow entry. - * - */ - public TypedStoredFlowEntry getFlowEntry(FlowRule rule) { - checkNotNull(rule); - - return getFlowEntryInternal(rule); - } - - /** - * Gets the all typed flow entries in flow table. - * - * @return the set of typed flow entry. - * - */ - public Set getFlowEntries() { - return getFlowEntriesInternal(); - } - - /** - * Gets the short typed flow entries in flow table. - * - * @return the set of typed flow entry. - * - */ - public Set getShortFlows() { - return ImmutableSet.copyOf(shortFlows); //Sets.newHashSet(shortFlows); - } - - /** - * Gets the mid typed flow entries in flow table. - * - * @return the set of typed flow entry. - * - */ - public Set getMidFlows() { - return ImmutableSet.copyOf(midFlows); //Sets.newHashSet(midFlows); - } - - /** - * Gets the long typed flow entries in flow table. - * - * @return the set of typed flow entry. - * - */ - public Set getLongFlows() { - return ImmutableSet.copyOf(longFlows); //Sets.newHashSet(longFlows); - } - - /** - * Add typed flow entry into table only. - * - * @param rule the flow rule - * - */ - public synchronized void add(TypedStoredFlowEntry rule) { - checkNotNull(rule); - - //rule have to be new DefaultTypedFlowEntry - boolean result = getFlowEntriesInternal(rule.id()).add(rule); - - if (result) { - addCount++; - } - } - - /** - * Calculates and set the flow live type at the first time, - * and then add it into a corresponding typed flow table. - * - * @param rule the flow rule - * - */ - public void calAndSetFlowLiveType(TypedStoredFlowEntry rule) { - checkNotNull(rule); - - calAndSetFlowLiveTypeInternal(rule); - } - - /** - * Add the typed flow entry into table, and calculates and set the flow live type, - * and then add it into a corresponding typed flow table. - * - * @param rule the flow rule - * - */ - public synchronized void addWithCalAndSetFlowLiveType(TypedStoredFlowEntry rule) { - checkNotNull(rule); - - //rule have to be new DefaultTypedFlowEntry - boolean result = getFlowEntriesInternal(rule.id()).add(rule); - if (result) { - calAndSetFlowLiveTypeInternal(rule); - addWithSetFlowLiveTypeCount++; - } else { - log.debug("addWithCalAndSetFlowLiveType, FlowId=" + Long.toHexString(rule.id().value()) - + " ADD Failed, cause it may already exists in table !!!," - + " AdaptiveStats collection thread for {}", - sw.getStringId()); - } - } - - // In real, calculates and set the flow live type at the first time, - // and then add it into a corresponding typed flow table - private void calAndSetFlowLiveTypeInternal(TypedStoredFlowEntry rule) { - long life = rule.life(); - FlowLiveType prevFlowLiveType = rule.flowLiveType(); - - if (life >= longPollInterval) { - rule.setFlowLiveType(FlowLiveType.LONG_FLOW); - longFlows.add(rule); - } else if (life >= midPollInterval) { - rule.setFlowLiveType(FlowLiveType.MID_FLOW); - midFlows.add(rule); - } else if (life >= calAndPollInterval) { - rule.setFlowLiveType(FlowLiveType.SHORT_FLOW); - shortFlows.add(rule); - } else if (life >= 0) { - rule.setFlowLiveType(FlowLiveType.IMMEDIATE_FLOW); - } else { // life < 0 - rule.setFlowLiveType(FlowLiveType.UNKNOWN_FLOW); - } - - if (rule.flowLiveType() != prevFlowLiveType) { - switch (prevFlowLiveType) { - // delete it from previous flow table - case SHORT_FLOW: - shortFlows.remove(rule); - break; - case MID_FLOW: - midFlows.remove(rule); - break; - case LONG_FLOW: - longFlows.remove(rule); - break; - default: - break; - } - } - } - - - // check the flow live type based on current time, then set and add it into corresponding table - private boolean checkAndMoveLiveFlowInternal(TypedStoredFlowEntry fe, long cTime) { - long curTime = (cTime > 0 ? cTime : System.currentTimeMillis()); - // For latency adjustment(default=500 millisecond) between FlowStatsRequest and Reply - long fromLastSeen = ((curTime - fe.lastSeen() + latencyFlowStatsRequestAndReplyMillis) / 1000); - // fe.life() unit is SECOND! - long liveTime = fe.life() + fromLastSeen; - - - switch (fe.flowLiveType()) { - case IMMEDIATE_FLOW: - if (liveTime >= longPollInterval) { - fe.setFlowLiveType(FlowLiveType.LONG_FLOW); - longFlows.add(fe); - } else if (liveTime >= midPollInterval) { - fe.setFlowLiveType(FlowLiveType.MID_FLOW); - midFlows.add(fe); - } else if (liveTime >= calAndPollInterval) { - fe.setFlowLiveType(FlowLiveType.SHORT_FLOW); - shortFlows.add(fe); - } - break; - case SHORT_FLOW: - if (liveTime >= longPollInterval) { - fe.setFlowLiveType(FlowLiveType.LONG_FLOW); - shortFlows.remove(fe); - longFlows.add(fe); - } else if (liveTime >= midPollInterval) { - fe.setFlowLiveType(FlowLiveType.MID_FLOW); - shortFlows.remove(fe); - midFlows.add(fe); - } - break; - case MID_FLOW: - if (liveTime >= longPollInterval) { - fe.setFlowLiveType(FlowLiveType.LONG_FLOW); - midFlows.remove(fe); - longFlows.add(fe); - } - break; - case LONG_FLOW: - if (fromLastSeen > entirePollInterval) { - log.trace("checkAndMoveLiveFlowInternal, flow is already removed at switch."); - return false; - } - break; - case UNKNOWN_FLOW: // Unknown flow is an internal error flow type, just fall through - default : - // Error Unknown Live Type - log.error("checkAndMoveLiveFlowInternal, Unknown Live Type error!" - + "AdaptiveStats collection thread for {}", - sw.getStringId()); - return false; - } - - log.debug("checkAndMoveLiveFlowInternal, FlowId=" + Long.toHexString(fe.id().value()) - + ", state=" + fe.state() - + ", After liveType=" + fe.flowLiveType() - + ", liveTime=" + liveTime - + ", life=" + fe.life() - + ", bytes=" + fe.bytes() - + ", packets=" + fe.packets() - + ", fromLastSeen=" + fromLastSeen - + ", priority=" + fe.priority() - + ", selector=" + fe.selector().criteria() - + ", treatment=" + fe.treatment() - + " AdaptiveStats collection thread for {}", - sw.getStringId()); - - return true; - } - - /** - * Check and move live type for all type flow entries in table at every calAndPollInterval time. - * - */ - public void checkAndMoveLiveFlowAll() { - Set typedFlowEntries = getFlowEntriesInternal(); - - long calCurTime = System.currentTimeMillis(); - typedFlowEntries.forEach(fe -> { - if (!checkAndMoveLiveFlowInternal(fe, calCurTime)) { - remove(fe); - } - }); - - // print table counts for debug - if (log.isDebugEnabled()) { - synchronized (this) { - long totalFlowCount = getFlowCount(); - long shortFlowCount = shortFlows.size(); - long midFlowCount = midFlows.size(); - long longFlowCount = longFlows.size(); - long immediateFlowCount = totalFlowCount - shortFlowCount - midFlowCount - longFlowCount; - long calTotalCount = addCount + addWithSetFlowLiveTypeCount - removeCount; - - log.debug("--------------------------------------------------------------------------- for {}", - sw.getStringId()); - log.debug("checkAndMoveLiveFlowAll, Total Flow_Count=" + totalFlowCount - + ", add - remove_Count=" + calTotalCount - + ", IMMEDIATE_FLOW_Count=" + immediateFlowCount - + ", SHORT_FLOW_Count=" + shortFlowCount - + ", MID_FLOW_Count=" + midFlowCount - + ", LONG_FLOW_Count=" + longFlowCount - + ", add_Count=" + addCount - + ", addWithSetFlowLiveType_Count=" + addWithSetFlowLiveTypeCount - + ", remove_Count=" + removeCount - + " AdaptiveStats collection thread for {}", sw.getStringId()); - log.debug("--------------------------------------------------------------------------- for {}", - sw.getStringId()); - if (totalFlowCount != calTotalCount) { - log.error("checkAndMoveLiveFlowAll, Real total flow count and " - + "calculated total flow count do NOT match, something is wrong internally " - + "or check counter value bound is over!"); - } - if (immediateFlowCount < 0) { - log.error("checkAndMoveLiveFlowAll, IMMEDIATE_FLOW count is negative, " - + "something is wrong internally " - + "or check counter value bound is over!"); - } - } - } - log.trace("checkAndMoveLiveFlowAll, AdaptiveStats for {}", sw.getStringId()); - } - - /** - * Remove the typed flow entry from table. - * - * @param rule the flow rule - * - */ - public synchronized void remove(FlowRule rule) { - checkNotNull(rule); - - TypedStoredFlowEntry removeStore = getFlowEntryInternal(rule); - if (removeStore != null) { - removeLiveFlowsInternal((TypedStoredFlowEntry) removeStore); - boolean result = getFlowEntriesInternal(rule.id()).remove(removeStore); - - if (result) { - removeCount++; - } - } - } - - // Remove the typed flow entry from corresponding table - private void removeLiveFlowsInternal(TypedStoredFlowEntry fe) { - switch (fe.flowLiveType()) { - case IMMEDIATE_FLOW: - // do nothing - break; - case SHORT_FLOW: - shortFlows.remove(fe); - break; - case MID_FLOW: - midFlows.remove(fe); - break; - case LONG_FLOW: - longFlows.remove(fe); - break; - default: // error in Flow Live Type - log.error("removeLiveFlowsInternal, Unknown Live Type error!"); - break; - } - } - } -} +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.provider.of.flow.impl; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.onosproject.net.flow.DefaultTypedFlowEntry; +import org.onosproject.net.flow.FlowEntry; +import org.onosproject.net.flow.FlowId; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.flow.StoredFlowEntry; +import org.onosproject.net.flow.TypedStoredFlowEntry; +import org.onosproject.net.flow.instructions.Instruction; +import org.onosproject.net.flow.instructions.Instructions; +import org.onosproject.openflow.controller.OpenFlowSwitch; +import org.onosproject.openflow.controller.RoleState; +import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.TableId; +import org.slf4j.Logger; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.groupedThreads; +import static org.onosproject.net.flow.TypedStoredFlowEntry.FlowLiveType; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Efficiently and adaptively collects flow statistics for the specified switch. + */ +public class NewAdaptiveFlowStatsCollector { + + private final Logger log = getLogger(getClass()); + + private final OpenFlowSwitch sw; + + private ScheduledExecutorService adaptiveFlowStatsScheduler = + Executors.newScheduledThreadPool(4, groupedThreads("onos/flow", "device-stats-collector-%d")); + private ScheduledFuture calAndShortFlowsThread; + private ScheduledFuture midFlowsThread; + private ScheduledFuture longFlowsThread; + + // Task that calculates all flowEntries' FlowLiveType and collects stats IMMEDIATE flows every calAndPollInterval + private CalAndShortFlowsTask calAndShortFlowsTask; + // Task that collects stats MID flows every 2*calAndPollInterval + private MidFlowsTask midFlowsTask; + // Task that collects stats LONG flows every 3*calAndPollInterval + private LongFlowsTask longFlowsTask; + + private static final int CAL_AND_POLL_TIMES = 1; // must be always 0 + private static final int MID_POLL_TIMES = 2; // variable greater or equal than 1 + private static final int LONG_POLL_TIMES = 3; // variable greater or equal than MID_POLL_TIMES + //TODO: make ENTIRE_POLL_TIMES configurable with enable or disable + // must be variable greater or equal than common multiple of MID_POLL_TIMES and LONG_POLL_TIMES + private static final int ENTIRE_POLL_TIMES = 6; + + private static final int DEFAULT_CAL_AND_POLL_FREQUENCY = 5; + private static final int MIN_CAL_AND_POLL_FREQUENCY = 2; + private static final int MAX_CAL_AND_POLL_FREQUENCY = 60; + + private int calAndPollInterval; // CAL_AND_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; + private int midPollInterval; // MID_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; + private int longPollInterval; // LONG_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; + // only used for checking condition at each task if it collects entire flows from a given switch or not + private int entirePollInterval; // ENTIRE_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; + + // Number of call count of each Task, + // for undoing collection except only entire flows collecting task in CalAndShortFlowsTask + private int callCountCalAndShortFlowsTask = 0; // increased CAL_AND_POLL_TIMES whenever Task is called + private int callCountMidFlowsTask = 0; // increased MID_POLL_TIMES whenever Task is called + private int callCountLongFlowsTask = 0; // increased LONG_POLL_TIMES whenever Task is called + + private InternalDeviceFlowTable deviceFlowTable = new InternalDeviceFlowTable(); + + private boolean isFirstTimeStart = true; + + public static final long NO_FLOW_MISSING_XID = (-1); + private long flowMissingXid = NO_FLOW_MISSING_XID; + + /** + * Creates a new adaptive collector for the given switch and default cal_and_poll frequency. + * + * @param sw switch to pull + * @param pollInterval cal and immediate poll frequency in seconds + */ + NewAdaptiveFlowStatsCollector(OpenFlowSwitch sw, int pollInterval) { + this.sw = sw; + + initMemberVars(pollInterval); + } + + // check calAndPollInterval validity and set all pollInterval values and finally initialize each task call count + private void initMemberVars(int pollInterval) { + if (pollInterval < MIN_CAL_AND_POLL_FREQUENCY) { + this.calAndPollInterval = MIN_CAL_AND_POLL_FREQUENCY; + } else if (pollInterval >= MAX_CAL_AND_POLL_FREQUENCY) { + this.calAndPollInterval = MAX_CAL_AND_POLL_FREQUENCY; + } else { + this.calAndPollInterval = pollInterval; + } + + calAndPollInterval = CAL_AND_POLL_TIMES * calAndPollInterval; + midPollInterval = MID_POLL_TIMES * calAndPollInterval; + longPollInterval = LONG_POLL_TIMES * calAndPollInterval; + entirePollInterval = ENTIRE_POLL_TIMES * calAndPollInterval; + + callCountCalAndShortFlowsTask = 0; + callCountMidFlowsTask = 0; + callCountLongFlowsTask = 0; + + flowMissingXid = NO_FLOW_MISSING_XID; + } + + /** + * Adjusts adaptive poll frequency. + * + * @param pollInterval poll frequency in seconds + */ + synchronized void adjustCalAndPollInterval(int pollInterval) { + initMemberVars(pollInterval); + + if (calAndShortFlowsThread != null) { + calAndShortFlowsThread.cancel(false); + } + if (midFlowsThread != null) { + midFlowsThread.cancel(false); + } + if (longFlowsThread != null) { + longFlowsThread.cancel(false); + } + + calAndShortFlowsTask = new CalAndShortFlowsTask(); + calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + calAndShortFlowsTask, + 0, + calAndPollInterval, + TimeUnit.SECONDS); + + midFlowsTask = new MidFlowsTask(); + midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + midFlowsTask, + 0, + midPollInterval, + TimeUnit.SECONDS); + + longFlowsTask = new LongFlowsTask(); + longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + longFlowsTask, + 0, + longPollInterval, + TimeUnit.SECONDS); + + log.debug("calAndPollInterval=" + calAndPollInterval + "is adjusted"); + } + + private class CalAndShortFlowsTask implements Runnable { + @Override + public void run() { + if (sw.getRole() == RoleState.MASTER) { + log.trace("CalAndShortFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); + + if (isFirstTimeStart) { + // isFirstTimeStart, get entire flow stats from a given switch sw + log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats at first time start for {}", + sw.getStringId()); + ofFlowStatsRequestAllSend(); + + callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; + isFirstTimeStart = false; + } else if (callCountCalAndShortFlowsTask == ENTIRE_POLL_TIMES) { + // entire_poll_times, get entire flow stats from a given switch sw + log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats for {}", sw.getStringId()); + ofFlowStatsRequestAllSend(); + + callCountCalAndShortFlowsTask = CAL_AND_POLL_TIMES; + //TODO: check flows deleted in switch, but exist in controller flow table, then remove them + // + } else { + calAndShortFlowsTaskInternal(); + callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; + } + } + } + } + + // send openflow flow stats request message with getting all flow entries to a given switch sw + private void ofFlowStatsRequestAllSend() { + OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() + .setMatch(sw.factory().matchWildcardAll()) + .setTableId(TableId.ALL) + .setOutPort(OFPort.NO_MASK) + .build(); + + synchronized (this) { + // set the request xid to check the reply in OpenFlowRuleProvider + // After processing the reply of this request message, + // this must be set to NO_FLOW_MISSING_XID(-1) by provider + setFlowMissingXid(request.getXid()); + log.debug("ofFlowStatsRequestAllSend,Request={},for {}", request.toString(), sw.getStringId()); + + sw.sendMsg(request); + } + } + + // send openflow flow stats request message with getting the specific flow entry(fe) to a given switch sw + private void ofFlowStatsRequestFlowSend(FlowEntry fe) { + // set find match + Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(), + Optional.empty()).buildMatch(); + // set find tableId + TableId tableId = TableId.of(fe.tableId()); + // set output port + Instruction ins = fe.treatment().allInstructions().stream() + .filter(i -> (i.type() == Instruction.Type.OUTPUT)) + .findFirst() + .orElse(null); + OFPort ofPort = OFPort.NO_MASK; + if (ins != null) { + Instructions.OutputInstruction out = (Instructions.OutputInstruction) ins; + ofPort = OFPort.of((int) ((out.port().toLong()))); + } + + OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() + .setMatch(match) + .setTableId(tableId) + .setOutPort(ofPort) + .build(); + + synchronized (this) { + if (getFlowMissingXid() != NO_FLOW_MISSING_XID) { + log.debug("ofFlowStatsRequestFlowSend: previous FlowStatsRequestAll does not be processed yet," + + " set no flow missing xid anyway, for {}", + sw.getStringId()); + setFlowMissingXid(NO_FLOW_MISSING_XID); + } + + sw.sendMsg(request); + } + } + + private void calAndShortFlowsTaskInternal() { + deviceFlowTable.checkAndMoveLiveFlowAll(); + + deviceFlowTable.getShortFlows().forEach(fe -> { + ofFlowStatsRequestFlowSend(fe); + }); + } + + private class MidFlowsTask implements Runnable { + @Override + public void run() { + if (sw.getRole() == RoleState.MASTER) { + log.trace("MidFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); + + // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw + if (callCountMidFlowsTask == ENTIRE_POLL_TIMES) { + callCountMidFlowsTask = MID_POLL_TIMES; + } else { + midFlowsTaskInternal(); + callCountMidFlowsTask += MID_POLL_TIMES; + } + } + } + } + + private void midFlowsTaskInternal() { + deviceFlowTable.getMidFlows().forEach(fe -> { + ofFlowStatsRequestFlowSend(fe); + }); + } + + private class LongFlowsTask implements Runnable { + @Override + public void run() { + if (sw.getRole() == RoleState.MASTER) { + log.trace("LongFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); + + // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw + if (callCountLongFlowsTask == ENTIRE_POLL_TIMES) { + callCountLongFlowsTask = LONG_POLL_TIMES; + } else { + longFlowsTaskInternal(); + callCountLongFlowsTask += LONG_POLL_TIMES; + } + } + } + } + + private void longFlowsTaskInternal() { + deviceFlowTable.getLongFlows().forEach(fe -> { + ofFlowStatsRequestFlowSend(fe); + }); + } + + /** + * start adaptive flow statistic collection. + * + */ + public synchronized void start() { + log.debug("Starting AdaptiveStats collection thread for {}", sw.getStringId()); + callCountCalAndShortFlowsTask = 0; + callCountMidFlowsTask = 0; + callCountLongFlowsTask = 0; + + isFirstTimeStart = true; + + // Initially start polling quickly. Then drop down to configured value + calAndShortFlowsTask = new CalAndShortFlowsTask(); + calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + calAndShortFlowsTask, + 1, + calAndPollInterval, + TimeUnit.SECONDS); + + midFlowsTask = new MidFlowsTask(); + midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + midFlowsTask, + 1, + midPollInterval, + TimeUnit.SECONDS); + + longFlowsTask = new LongFlowsTask(); + longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( + longFlowsTask, + 1, + longPollInterval, + TimeUnit.SECONDS); + + log.info("Started"); + } + + /** + * stop adaptive flow statistic collection. + * + */ + public synchronized void stop() { + log.debug("Stopping AdaptiveStats collection thread for {}", sw.getStringId()); + if (calAndShortFlowsThread != null) { + calAndShortFlowsThread.cancel(true); + } + if (midFlowsThread != null) { + midFlowsThread.cancel(true); + } + if (longFlowsThread != null) { + longFlowsThread.cancel(true); + } + + adaptiveFlowStatsScheduler.shutdownNow(); + + isFirstTimeStart = false; + + log.info("Stopped"); + } + + /** + * add typed flow entry from flow rule into the internal flow table. + * + * @param flowRules the flow rules + * + */ + public synchronized void addWithFlowRule(FlowRule... flowRules) { + for (FlowRule fr : flowRules) { + // First remove old entry unconditionally, if exist + deviceFlowTable.remove(fr); + + // add new flow entry, we suppose IMMEDIATE_FLOW + TypedStoredFlowEntry newFlowEntry = new DefaultTypedFlowEntry(fr, + FlowLiveType.IMMEDIATE_FLOW); + deviceFlowTable.addWithCalAndSetFlowLiveType(newFlowEntry); + } + } + + /** + * add or update typed flow entry from flow entry into the internal flow table. + * + * @param flowEntries the flow entries + * + */ + public synchronized void addOrUpdateFlows(FlowEntry... flowEntries) { + for (FlowEntry fe : flowEntries) { + // check if this new rule is an update to an existing entry + TypedStoredFlowEntry stored = deviceFlowTable.getFlowEntry(fe); + + if (stored != null) { + // duplicated flow entry is collected!, just skip + if (fe.bytes() == stored.bytes() && fe.packets() == stored.packets() + && fe.life() == stored.life()) { + log.debug("addOrUpdateFlows:, FlowId=" + Long.toHexString(fe.id().value()) + + ",is DUPLICATED stats collection, just skip." + + " AdaptiveStats collection thread for {}", + sw.getStringId()); + + stored.setLastSeen(); + continue; + } else if (fe.life() < stored.life()) { + // Invalid updates the stats values, i.e., bytes, packets, durations ... + log.debug("addOrUpdateFlows():" + + " Invalid Flow Update! The new life is SMALLER than the previous one, jus skip." + + " new flowId=" + Long.toHexString(fe.id().value()) + + ", old flowId=" + Long.toHexString(stored.id().value()) + + ", new bytes=" + fe.bytes() + ", old bytes=" + stored.bytes() + + ", new life=" + fe.life() + ", old life=" + stored.life() + + ", new lastSeen=" + fe.lastSeen() + ", old lastSeen=" + stored.lastSeen()); + // go next + stored.setLastSeen(); + continue; + } + + // update now + stored.setLife(fe.life()); + stored.setPackets(fe.packets()); + stored.setBytes(fe.bytes()); + stored.setLastSeen(); + if (stored.state() == FlowEntry.FlowEntryState.PENDING_ADD) { + // flow is really RULE_ADDED + stored.setState(FlowEntry.FlowEntryState.ADDED); + } + // flow is RULE_UPDATED, skip adding and just updating flow live table + //deviceFlowTable.calAndSetFlowLiveType(stored); + continue; + } + + // add new flow entry, we suppose IMMEDIATE_FLOW + TypedStoredFlowEntry newFlowEntry = new DefaultTypedFlowEntry(fe, + FlowLiveType.IMMEDIATE_FLOW); + deviceFlowTable.addWithCalAndSetFlowLiveType(newFlowEntry); + } + } + + /** + * remove typed flow entry from the internal flow table. + * + * @param flowRules the flow entries + * + */ + public synchronized void removeFlows(FlowRule... flowRules) { + for (FlowRule rule : flowRules) { + deviceFlowTable.remove(rule); + } + } + + // same as removeFlows() function + /** + * remove typed flow entry from the internal flow table. + * + * @param flowRules the flow entries + * + */ + public void flowRemoved(FlowRule... flowRules) { + removeFlows(flowRules); + } + + // same as addOrUpdateFlows() function + /** + * add or update typed flow entry from flow entry into the internal flow table. + * + * @param flowEntries the flow entry list + * + */ + public void pushFlowMetrics(List flowEntries) { + flowEntries.forEach(fe -> { + addOrUpdateFlows(fe); + }); + } + + /** + * returns flowMissingXid that indicates the execution of flowMissing process or not(NO_FLOW_MISSING_XID(-1)). + * + * @return xid of missing flow + */ + public long getFlowMissingXid() { + return flowMissingXid; + } + + /** + * set flowMissingXid, namely OFFlowStatsRequest match any ALL message Id. + * + * @param flowMissingXid the OFFlowStatsRequest message Id + * + */ + public void setFlowMissingXid(long flowMissingXid) { + this.flowMissingXid = flowMissingXid; + } + + private class InternalDeviceFlowTable { + + private final Map> + flowEntries = Maps.newConcurrentMap(); + + private final Set shortFlows = new HashSet<>(); + private final Set midFlows = new HashSet<>(); + private final Set longFlows = new HashSet<>(); + + // Assumed latency adjustment(default=500 millisecond) between FlowStatsRequest and Reply + private final long latencyFlowStatsRequestAndReplyMillis = 500; + + + // Statistics for table operation + private long addCount = 0, addWithSetFlowLiveTypeCount = 0; + private long removeCount = 0; + + /** + * Resets all count values with zero. + * + */ + public void resetAllCount() { + addCount = 0; + addWithSetFlowLiveTypeCount = 0; + removeCount = 0; + } + + // get set of flow entries for the given flowId + private Set getFlowEntriesInternal(FlowId flowId) { + return flowEntries.computeIfAbsent(flowId, id -> Sets.newCopyOnWriteArraySet()); + } + + // get flow entry for the given flow rule + private TypedStoredFlowEntry getFlowEntryInternal(FlowRule rule) { + Set flowEntries = getFlowEntriesInternal(rule.id()); + return flowEntries.stream() + .filter(entry -> Objects.equal(entry, rule)) + .findAny() + .orElse(null); + } + + // get the flow entries for all flows in flow table + private Set getFlowEntriesInternal() { + Set result = Sets.newHashSet(); + + flowEntries.values().forEach(result::addAll); + return result; + } + + /** + * Gets the number of flow entry in flow table. + * + * @return the number of flow entry. + * + */ + public long getFlowCount() { + return flowEntries.values().stream().mapToLong(Set::size).sum(); + } + + /** + * Gets the number of flow entry in flow table. + * + * @param rule the flow rule + * @return the typed flow entry. + * + */ + public TypedStoredFlowEntry getFlowEntry(FlowRule rule) { + checkNotNull(rule); + + return getFlowEntryInternal(rule); + } + + /** + * Gets the all typed flow entries in flow table. + * + * @return the set of typed flow entry. + * + */ + public Set getFlowEntries() { + return getFlowEntriesInternal(); + } + + /** + * Gets the short typed flow entries in flow table. + * + * @return the set of typed flow entry. + * + */ + public Set getShortFlows() { + return ImmutableSet.copyOf(shortFlows); //Sets.newHashSet(shortFlows); + } + + /** + * Gets the mid typed flow entries in flow table. + * + * @return the set of typed flow entry. + * + */ + public Set getMidFlows() { + return ImmutableSet.copyOf(midFlows); //Sets.newHashSet(midFlows); + } + + /** + * Gets the long typed flow entries in flow table. + * + * @return the set of typed flow entry. + * + */ + public Set getLongFlows() { + return ImmutableSet.copyOf(longFlows); //Sets.newHashSet(longFlows); + } + + /** + * Add typed flow entry into table only. + * + * @param rule the flow rule + * + */ + public synchronized void add(TypedStoredFlowEntry rule) { + checkNotNull(rule); + + //rule have to be new DefaultTypedFlowEntry + boolean result = getFlowEntriesInternal(rule.id()).add(rule); + + if (result) { + addCount++; + } + } + + /** + * Calculates and set the flow live type at the first time, + * and then add it into a corresponding typed flow table. + * + * @param rule the flow rule + * + */ + public void calAndSetFlowLiveType(TypedStoredFlowEntry rule) { + checkNotNull(rule); + + calAndSetFlowLiveTypeInternal(rule); + } + + /** + * Add the typed flow entry into table, and calculates and set the flow live type, + * and then add it into a corresponding typed flow table. + * + * @param rule the flow rule + * + */ + public synchronized void addWithCalAndSetFlowLiveType(TypedStoredFlowEntry rule) { + checkNotNull(rule); + + //rule have to be new DefaultTypedFlowEntry + boolean result = getFlowEntriesInternal(rule.id()).add(rule); + if (result) { + calAndSetFlowLiveTypeInternal(rule); + addWithSetFlowLiveTypeCount++; + } else { + log.debug("addWithCalAndSetFlowLiveType, FlowId=" + Long.toHexString(rule.id().value()) + + " ADD Failed, cause it may already exists in table !!!," + + " AdaptiveStats collection thread for {}", + sw.getStringId()); + } + } + + // In real, calculates and set the flow live type at the first time, + // and then add it into a corresponding typed flow table + private void calAndSetFlowLiveTypeInternal(TypedStoredFlowEntry rule) { + long life = rule.life(); + FlowLiveType prevFlowLiveType = rule.flowLiveType(); + + if (life >= longPollInterval) { + rule.setFlowLiveType(FlowLiveType.LONG_FLOW); + longFlows.add(rule); + } else if (life >= midPollInterval) { + rule.setFlowLiveType(FlowLiveType.MID_FLOW); + midFlows.add(rule); + } else if (life >= calAndPollInterval) { + rule.setFlowLiveType(FlowLiveType.SHORT_FLOW); + shortFlows.add(rule); + } else if (life >= 0) { + rule.setFlowLiveType(FlowLiveType.IMMEDIATE_FLOW); + } else { // life < 0 + rule.setFlowLiveType(FlowLiveType.UNKNOWN_FLOW); + } + + if (rule.flowLiveType() != prevFlowLiveType) { + switch (prevFlowLiveType) { + // delete it from previous flow table + case SHORT_FLOW: + shortFlows.remove(rule); + break; + case MID_FLOW: + midFlows.remove(rule); + break; + case LONG_FLOW: + longFlows.remove(rule); + break; + default: + break; + } + } + } + + + // check the flow live type based on current time, then set and add it into corresponding table + private boolean checkAndMoveLiveFlowInternal(TypedStoredFlowEntry fe, long cTime) { + long curTime = (cTime > 0 ? cTime : System.currentTimeMillis()); + // For latency adjustment(default=500 millisecond) between FlowStatsRequest and Reply + long fromLastSeen = ((curTime - fe.lastSeen() + latencyFlowStatsRequestAndReplyMillis) / 1000); + // fe.life() unit is SECOND! + long liveTime = fe.life() + fromLastSeen; + + + switch (fe.flowLiveType()) { + case IMMEDIATE_FLOW: + if (liveTime >= longPollInterval) { + fe.setFlowLiveType(FlowLiveType.LONG_FLOW); + longFlows.add(fe); + } else if (liveTime >= midPollInterval) { + fe.setFlowLiveType(FlowLiveType.MID_FLOW); + midFlows.add(fe); + } else if (liveTime >= calAndPollInterval) { + fe.setFlowLiveType(FlowLiveType.SHORT_FLOW); + shortFlows.add(fe); + } + break; + case SHORT_FLOW: + if (liveTime >= longPollInterval) { + fe.setFlowLiveType(FlowLiveType.LONG_FLOW); + shortFlows.remove(fe); + longFlows.add(fe); + } else if (liveTime >= midPollInterval) { + fe.setFlowLiveType(FlowLiveType.MID_FLOW); + shortFlows.remove(fe); + midFlows.add(fe); + } + break; + case MID_FLOW: + if (liveTime >= longPollInterval) { + fe.setFlowLiveType(FlowLiveType.LONG_FLOW); + midFlows.remove(fe); + longFlows.add(fe); + } + break; + case LONG_FLOW: + if (fromLastSeen > entirePollInterval) { + log.trace("checkAndMoveLiveFlowInternal, flow is already removed at switch."); + return false; + } + break; + case UNKNOWN_FLOW: // Unknown flow is an internal error flow type, just fall through + default : + // Error Unknown Live Type + log.error("checkAndMoveLiveFlowInternal, Unknown Live Type error!" + + "AdaptiveStats collection thread for {}", + sw.getStringId()); + return false; + } + + log.debug("checkAndMoveLiveFlowInternal, FlowId=" + Long.toHexString(fe.id().value()) + + ", state=" + fe.state() + + ", After liveType=" + fe.flowLiveType() + + ", liveTime=" + liveTime + + ", life=" + fe.life() + + ", bytes=" + fe.bytes() + + ", packets=" + fe.packets() + + ", fromLastSeen=" + fromLastSeen + + ", priority=" + fe.priority() + + ", selector=" + fe.selector().criteria() + + ", treatment=" + fe.treatment() + + " AdaptiveStats collection thread for {}", + sw.getStringId()); + + return true; + } + + /** + * Check and move live type for all type flow entries in table at every calAndPollInterval time. + * + */ + public void checkAndMoveLiveFlowAll() { + Set typedFlowEntries = getFlowEntriesInternal(); + + long calCurTime = System.currentTimeMillis(); + typedFlowEntries.forEach(fe -> { + if (!checkAndMoveLiveFlowInternal(fe, calCurTime)) { + remove(fe); + } + }); + + // print table counts for debug + if (log.isDebugEnabled()) { + synchronized (this) { + long totalFlowCount = getFlowCount(); + long shortFlowCount = shortFlows.size(); + long midFlowCount = midFlows.size(); + long longFlowCount = longFlows.size(); + long immediateFlowCount = totalFlowCount - shortFlowCount - midFlowCount - longFlowCount; + long calTotalCount = addCount + addWithSetFlowLiveTypeCount - removeCount; + + log.debug("--------------------------------------------------------------------------- for {}", + sw.getStringId()); + log.debug("checkAndMoveLiveFlowAll, Total Flow_Count=" + totalFlowCount + + ", add - remove_Count=" + calTotalCount + + ", IMMEDIATE_FLOW_Count=" + immediateFlowCount + + ", SHORT_FLOW_Count=" + shortFlowCount + + ", MID_FLOW_Count=" + midFlowCount + + ", LONG_FLOW_Count=" + longFlowCount + + ", add_Count=" + addCount + + ", addWithSetFlowLiveType_Count=" + addWithSetFlowLiveTypeCount + + ", remove_Count=" + removeCount + + " AdaptiveStats collection thread for {}", sw.getStringId()); + log.debug("--------------------------------------------------------------------------- for {}", + sw.getStringId()); + if (totalFlowCount != calTotalCount) { + log.error("checkAndMoveLiveFlowAll, Real total flow count and " + + "calculated total flow count do NOT match, something is wrong internally " + + "or check counter value bound is over!"); + } + if (immediateFlowCount < 0) { + log.error("checkAndMoveLiveFlowAll, IMMEDIATE_FLOW count is negative, " + + "something is wrong internally " + + "or check counter value bound is over!"); + } + } + } + log.trace("checkAndMoveLiveFlowAll, AdaptiveStats for {}", sw.getStringId()); + } + + /** + * Remove the typed flow entry from table. + * + * @param rule the flow rule + * + */ + public synchronized void remove(FlowRule rule) { + checkNotNull(rule); + + TypedStoredFlowEntry removeStore = getFlowEntryInternal(rule); + if (removeStore != null) { + removeLiveFlowsInternal((TypedStoredFlowEntry) removeStore); + boolean result = getFlowEntriesInternal(rule.id()).remove(removeStore); + + if (result) { + removeCount++; + } + } + } + + // Remove the typed flow entry from corresponding table + private void removeLiveFlowsInternal(TypedStoredFlowEntry fe) { + switch (fe.flowLiveType()) { + case IMMEDIATE_FLOW: + // do nothing + break; + case SHORT_FLOW: + shortFlows.remove(fe); + break; + case MID_FLOW: + midFlows.remove(fe); + break; + case LONG_FLOW: + longFlows.remove(fe); + break; + default: // error in Flow Live Type + log.error("removeLiveFlowsInternal, Unknown Live Type error!"); + break; + } + } + } +} diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java index 2f0831c6..556f76f5 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java @@ -20,6 +20,7 @@ import com.google.common.collect.EnumHashBiMap; import org.onosproject.net.ChannelSpacing; import org.onosproject.net.GridType; import org.onosproject.net.OchSignalType; +import org.onosproject.net.OduSignalType; /** * Collection of helper methods to convert protocol agnostic models to values used in OpenFlow spec. @@ -54,6 +55,17 @@ final class OpenFlowValueMapper { OCH_SIGNAL_TYPES.put(OchSignalType.FLEX_GRID, (byte) 2); // OFPOCHT_FLEX_GRID of enum ofp_och_signal_type } + private static final BiMap ODU_SIGNAL_TYPES = EnumHashBiMap.create(OduSignalType.class); + static { + // See ONF "Optical Transport Protocol Extensions Version 1.0" for the following values + ODU_SIGNAL_TYPES.put(OduSignalType.ODU1, (byte) 1); // OFPODUT_ODU1 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU2, (byte) 2); // OFPODUT_ODU2 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU3, (byte) 3); // OFPODUT_ODU3 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU4, (byte) 4); // OFPODUT_ODU4 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU0, (byte) 10); // OFPODUT_ODU0 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU2e, (byte) 11); // OFPODUT_ODU2E of enum ofp_odu_signal_type + } + /** * Looks up the specified input value to the corresponding value with the specified map. * @@ -149,4 +161,30 @@ final class OpenFlowValueMapper { static OchSignalType lookupOchSignalType(byte signalType) { return lookup(OCH_SIGNAL_TYPES.inverse(), signalType, OchSignalType.class); } + + /** + * Looks up the corresponding byte value for ODU signal type defined in + * ONF "Optical Transport Protocol Extensions Version 1.0" + * from the specified {@link OchSignalType} instance. + * + * @param signalType ODU (Optical channel Data Unit) signal type + * @return byte value corresponding to the specified ODU signal type + * @throws NoMappingFoundException if the specified ODU signal type is not found + */ + static byte lookupOduSignalType(OduSignalType signalType) { + return lookup(ODU_SIGNAL_TYPES, signalType, Byte.class); + } + + /** + * Looks up the the corresponding {@link OchSignalType} instance + * from the specified byte value for ODU signal type defined in + * ONF "Optical Transport Protocol Extensions Version 1.0". + * + * @param signalType byte value as ODU (Optical channel Data Unit) signal type defined the spec + * @return the corresponding OchSignalType instance + * @throws NoMappingFoundException if the specified ODU signal type is not found + */ + static OduSignalType lookupOduSignalType(byte signalType) { + return lookup(ODU_SIGNAL_TYPES.inverse(), signalType, OduSignalType.class); + } } diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java index e69fd6b9..6c646d0d 100644 --- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java +++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java @@ -128,7 +128,8 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv public void deactivate() { providerRegistry.unregister(this); providerService = null; - + collectors.values().forEach(GroupStatsCollector::stop); + collectors.clear(); log.info("Stopped"); } diff --git a/framework/src/onos/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java b/framework/src/onos/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java index f5a777be..e4113790 100644 --- a/framework/src/onos/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java +++ b/framework/src/onos/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java @@ -132,6 +132,8 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv @Deactivate public void deactivate() { providerRegistry.unregister(this); + collectors.values().forEach(MeterStatsCollector::stop); + collectors.clear(); controller.removeEventListener(listener); controller.removeListener(listener); providerService = null; diff --git a/framework/src/onos/providers/pom.xml b/framework/src/onos/providers/pom.xml index 32890b92..5665d324 100644 --- a/framework/src/onos/providers/pom.xml +++ b/framework/src/onos/providers/pom.xml @@ -35,11 +35,13 @@ openflow lldp host + netcfghost netconf null pcep ovsdb bgp + snmp diff --git a/framework/src/onos/providers/snmp/alarm/pom.xml b/framework/src/onos/providers/snmp/alarm/pom.xml new file mode 100644 index 00000000..f0a292e9 --- /dev/null +++ b/framework/src/onos/providers/snmp/alarm/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + + org.onosproject + onos-snmp-providers + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-snmp-provider-alarm + bundle + + ONOS SNMP protocol alarm provider + + \ No newline at end of file diff --git a/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/SNMPAlarmProvider.java b/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/SNMPAlarmProvider.java new file mode 100644 index 00000000..dc82a2cf --- /dev/null +++ b/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/SNMPAlarmProvider.java @@ -0,0 +1,57 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.provider.snmp.alarm.impl; + +import org.apache.felix.scr.annotations.Component; +import org.onosproject.net.DeviceId; +import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider; +import org.onosproject.net.provider.AbstractProvider; +import org.onosproject.net.provider.ProviderId; +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Provider which uses an SNMP controller to detect network device alarms. The class leverages functionality from + * + * @see https://github.com/btisystems/snmp-core + * @see https://github.com/btisystems/mibbler + */ +@Component(immediate = true) +public class SNMPAlarmProvider extends AbstractProvider implements AlarmProvider { + + private static final Logger LOG = getLogger(SNMPAlarmProvider.class); + + /** + * Creates a SNMP alarm provider, dummy class provided as template, tbd later. + */ + public SNMPAlarmProvider() { + super(new ProviderId("snmp", "org.onosproject.provider.alarm")); + } + + @Override + public void triggerProbe(final DeviceId deviceId) { + + // TODO in shout term should this just be synchronous and return result? + LOG.info("Run a SNMP discovery for device at {} when done invoke on AlarmProviderService", deviceId); + + // TODO Look up AlarmProviderService + // TODO Decide threading + // TODO Decide shouldn't it be generic not alarm-specific ? Its user responsible for passing in OID list ? + // Same for its callack AlarmProviderService ? + } + +} diff --git a/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/package-info.java b/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/package-info.java new file mode 100644 index 00000000..2c138cbb --- /dev/null +++ b/framework/src/onos/providers/snmp/alarm/src/main/java/org/onosproject/provider/snmp/alarm/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Provider that uses SNMP as a means of discovering alarms on devices. + */ +package org.onosproject.provider.snmp.alarm.impl; diff --git a/framework/src/onos/providers/snmp/pom.xml b/framework/src/onos/providers/snmp/pom.xml new file mode 100644 index 00000000..21031d98 --- /dev/null +++ b/framework/src/onos/providers/snmp/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + + org.onosproject + onos-providers + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-snmp-providers + pom + + ONOS SNMP Protocol Adapters + + + alarm + + + \ No newline at end of file diff --git a/framework/src/onos/tools/build/conf/pom.xml b/framework/src/onos/tools/build/conf/pom.xml index d56168f2..c76939ce 100644 --- a/framework/src/onos/tools/build/conf/pom.xml +++ b/framework/src/onos/tools/build/conf/pom.xml @@ -27,7 +27,7 @@ org.onosproject onos-build-conf - 1.1-SNAPSHOT + 1.2-SNAPSHOT Various ONOS build settings diff --git a/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml b/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml index fc6757a5..9260bae8 100644 --- a/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml +++ b/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml @@ -257,10 +257,6 @@ - - - - diff --git a/framework/src/onos/tools/build/onos-change-version b/framework/src/onos/tools/build/onos-change-version index a7117429..b41255b1 100755 --- a/framework/src/onos/tools/build/onos-change-version +++ b/framework/src/onos/tools/build/onos-change-version @@ -41,7 +41,7 @@ sed -i "" -E "s/Version\.version\(\"[^\"]*\"\)/Version.version(\"$NEW_VERSION\") # Augment the version in archetypes tree. mvn -f tools/package/archetypes/pom.xml versions:set -DnewVersion=$NEW_VERSION versions:commit -for atype in api bundle cli ui; do +for atype in api bundle cli ui uitab uitopo; do pom="tools/package/archetypes/$atype/src/main/resources/archetype-resources/pom.xml" sed -i "" -E "1,//s/[^<]*$NEW_VERSIONcord-gui<.*\n.*version>#cord-gui\n $NEW_VERSION#" $ONOS_ROOT/apps/demo/cord-gui/pom.xml sed -i "" -E "s#demo/cord-gui/target/cord-gui-.*\.war#demo/cord-gui/target/cord-gui-$NEW_VERSION.war#" $ONOS_ROOT/apps/demo/cord-gui/src/scripts/pullwar.sh sed -i "" -E "s#CORD=./cord-gui-.*\.war#CORD=./cord-gui-$NEW_VERSION.war#" $ONOS_ROOT/apps/demo/cord-gui/src/scripts/run.me - -# Augment the acl app -sed -i "" -E "s/[^<]*$NEW_VERSION bin/onos chmod a+x bin/onos-service bin/onos - # Stage the ONOS bundles, but only those that match the version - mkdir -p $ONOS_STAGE/$KARAF_DIST/system/org/onosproject - find $M2_REPO/org/onosproject -type f -path "*/$ONOS_POM_VERSION/*" \ - \( -name '*.jar' -o -name '*.pom' -o -name '*-features.xml' \) \ - | grep -v -Ee '-tests.jar|-[0-9]{8}.[0-9]{6}-' \ - | while read src; do - dst=$ONOS_STAGE/$KARAF_DIST/system/${src#$M2_REPO/*} - mkdir -p $(dirname $dst) - cp $src $dst - done + if [ -d $ONOS_ROOT/tools/package/karaf-assembly/target/repo ]; then + cp -r $ONOS_ROOT/tools/package/karaf-assembly/target/repo/* $ONOS_STAGE/$KARAF_DIST/system + #FIXME we need to add onos-features manually + mkdir -p $ONOS_STAGE/$KARAF_DIST/system/org/onosproject/onos-features/$ONOS_POM_VERSION + cp $M2_REPO/org/onosproject/onos-features/$ONOS_POM_VERSION/onos-features* \ + $ONOS_STAGE/$KARAF_DIST/system/org/onosproject/onos-features/$ONOS_POM_VERSION + else + # TODO: Deprecated so remove when confident staging works. + # Stage the ONOS bundles, but only those that match the version + mkdir -p $ONOS_STAGE/$KARAF_DIST/system/org/onosproject + find $M2_REPO/org/onosproject -type f -path "*/$ONOS_POM_VERSION/*" \ + \( -name '*.jar' -o -name '*.pom' -o -name '*-features.xml' \) \ + | grep -v -Ee '-tests.jar|-[0-9]{8}.[0-9]{6}-' \ + | while read src; do + dst=$ONOS_STAGE/$KARAF_DIST/system/${src#$M2_REPO/*} + mkdir -p $(dirname $dst) + cp $src $dst + done + fi # ONOS Patching ---------------------------------------------------------------- @@ -153,6 +162,11 @@ function build_rpm() { # Bail on any errors set -e +# Run karaf assembly to collect artifacts for off-line installations. +aux=/tmp/assembly-$$.log +trap "rm -f $aux 2>/dev/null" EXIT +cd $ONOS_ROOT/tools/package/karaf-assembly && mvn clean install > $aux 2>&1 + # Before starting make sure the environment is clan - delete onos staging folder rm -fr $ONOS_STAGE diff --git a/framework/src/onos/tools/build/pom.xml b/framework/src/onos/tools/build/pom.xml index ea473ed2..33b3a09b 100644 --- a/framework/src/onos/tools/build/pom.xml +++ b/framework/src/onos/tools/build/pom.xml @@ -81,7 +81,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 attach-javadocs diff --git a/framework/src/onos/tools/dev/bash_profile b/framework/src/onos/tools/dev/bash_profile index b8244a77..6bab610e 100644 --- a/framework/src/onos/tools/dev/bash_profile +++ b/framework/src/onos/tools/dev/bash_profile @@ -140,11 +140,12 @@ function cells { done } -# Miscellaneous +# Find a process by regex function spy { ps -ef | egrep "$@" | grep -v egrep } +# Kill a process by regex function nuke { spy "$@" | cut -c7-11 | xargs kill } @@ -186,5 +187,9 @@ function vicell { ($apply) && cell ${cdf} } -# autocomplete for certain utilities +# Autocomplete for certain utilities . ${ONOS_ROOT}/tools/test/bin/ogroup-opts + + +# Load AT&T MPLS topo GEO data +alias atttopo='onos-topo-cfg $OCI $ONOS_ROOT/tools/test/topos/attmpls.json' \ No newline at end of file diff --git a/framework/src/onos/tools/dev/bin/onos-build-selective.exclude b/framework/src/onos/tools/dev/bin/onos-build-selective.exclude index 487f848c..33bf08a3 100644 --- a/framework/src/onos/tools/dev/bin/onos-build-selective.exclude +++ b/framework/src/onos/tools/dev/bin/onos-build-selective.exclude @@ -7,4 +7,5 @@ .*/jdvue/.* .*/ovsdb/api/.* .*/netconf/flow/.* -.*/vtn/sfcmgr/.* \ No newline at end of file +.*/vtn/sfcmgr/.* +/tools/package/yangtools/.* \ No newline at end of file diff --git a/framework/src/onos/tools/package/config/samples/network-cfg.json b/framework/src/onos/tools/package/config/samples/network-cfg.json index 9e9257e0..f6879f07 100644 --- a/framework/src/onos/tools/package/config/samples/network-cfg.json +++ b/framework/src/onos/tools/package/config/samples/network-cfg.json @@ -1,67 +1,86 @@ { "ports" : { - "of:0000000000000002/1" : { - "interfaces" : [ - { - "ips" : [ "192.168.10.101/24" ], - "mac" : "08:9e:01:82:38:68", - "vlan" : "100" - } - ] - }, - "of:0000000000000002/20" : { - "interfaces" : [ - { - "ips" : [ "192.168.20.101/24" ], - "mac" : "08:9e:01:82:38:68", - "vlan" : "200" - } - ] - } + "of:0000000000000002/1" : { + "interfaces" : [ + { + "ips" : [ "192.168.10.101/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000002/2" : { + "interfaces" : [ + { + "ips" : [ "192.168.20.101/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "200" + } + ] + } }, "devices" : { - "of:0000000000000002" : { - "segmentrouting" : { + "of:0000000000000002" : { + "segmentrouting" : { "name" : "Leaf-R1", "nodeSid" : 101, "routerIp" : "10.0.1.254", "routerMac" : "00:00:00:00:01:80", "isEdgeRouter" : true, "adjacencySids" : [ - { "sid" : 100, "ports" : [2, 3] }, - { "sid" : 200, "ports" : [4, 5] } + { "adjSids" : 100, "ports" : [2, 3] }, + { "adjSids" : 200, "ports" : [4, 5] } ] } - }, - "of:0000000000000191" : { - "segmentrouting" : { + }, + "of:0000000000000191" : { + "segmentrouting" : { "name" : "Spine-R1", "nodeSid" : 105, "routerIp" : "192.168.0.11", "routerMac" : "00:00:01:00:11:80", - "isEdgeRouter" : false + "isEdgeRouter" : false, + "adjacencySids" : [] } - } + } }, "apps" : { - "org.onosproject.router" : { - "bgp" : { - "bgpSpeakers" : [ - { - "connectPoint" : "of:00000000000000aa/10", - "peers" : [ - "192.168.10.1" - ] - }, - { - "connectPoint" : "of:00000000000000aa/20", - "peers" : [ - "192.168.20.1" - ] - } - ] - } - } + "org.onosproject.router" : { + "bgp" : { + "bgpSpeakers" : [ + { + "connectPoint" : "of:00000000000000aa/10", + "peers" : [ + "192.168.10.1" + ] + }, + { + "connectPoint" : "of:00000000000000aa/20", + "peers" : [ + "192.168.20.1" + ] + } + ] + } + } + }, + "hosts" : { + "00:00:00:00:00:01/4093": { + "basic": { + "ips": [ + "10.0.1.1" + ], + "location": "of:0000000000000001/3" + } + }, + "00:00:00:00:00:02/4093": { + "basic": { + "ips": [ + "10.0.1.2" + ], + "location": "of:0000000000000001/4" + } + } } } diff --git a/framework/src/onos/tools/package/etc/samples/org.onosproject.faultmanagement.impl.AlarmsManager.cfg b/framework/src/onos/tools/package/etc/samples/org.onosproject.faultmanagement.impl.AlarmsManager.cfg new file mode 100644 index 00000000..99795e57 --- /dev/null +++ b/framework/src/onos/tools/package/etc/samples/org.onosproject.faultmanagement.impl.AlarmsManager.cfg @@ -0,0 +1,6 @@ +# +# devices which may have faults. +# TODO change to NetworkConfig subsystem. +# +fmDevices = 172.27.7.110,172.27.7.110,3.3.3.3 + diff --git a/framework/src/onos/tools/package/karaf-assembly/onos-assembly.py b/framework/src/onos/tools/package/karaf-assembly/onos-assembly.py new file mode 100755 index 00000000..1e394bf6 --- /dev/null +++ b/framework/src/onos/tools/package/karaf-assembly/onos-assembly.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +''' + Builds synthetic feature file that includes all core, provider, and application + features, so that we can pre-stage all bundles required to run ONOS off-line. +''' + +import os +import xml.etree.ElementTree as ET + +FEATURE_TAG = '{http://karaf.apache.org/xmlns/features/v1.2.0}feature' +STAGED_REPOS = 'target/staged-repos.xml' + +if 'ONOS_ROOT' in os.environ: + ONOS_ROOT = os.environ['ONOS_ROOT'] +else: + # fallback to working directory if ONOS_ROOT is not set + ONOS_ROOT = os.getcwd() + +def findFeatureFiles(path=ONOS_ROOT): + #only descend into target directories that have pom + for root, dirs, files in os.walk(path): + if 'pom.xml' not in files: + if 'target' in dirs: + #pruning target dir with no pom.xml + dirs.remove('target') + if '/target' in root: + if '/classes/' in root: + #filter out features.xml for maven-plugin + continue + for f in files: + if f.endswith('features.xml'): + yield os.path.join(root, f) + +def featuresFromFile(file): + features = [] + tree = ET.parse(file) + root = tree.getroot() + for feature in root.findall(FEATURE_TAG): + features.append(feature.attrib['name']) + return features + +if __name__ == '__main__': + outputTree = ET.Element('features') + uberFeature = ET.Element('feature', attrib={'name' : 'onos-uber-synthetic'}) + for file in findFeatureFiles(): + features = featuresFromFile(file) + if len(features) > 0: + ET.SubElement(outputTree, 'repository').text = 'file:%s' % file + for feature in features: + ET.SubElement(uberFeature, 'feature').text = feature + outputTree.append(uberFeature) + + outputFile = os.path.join(os.path.dirname(os.path.realpath(__file__)), STAGED_REPOS) + outputDir = os.path.dirname(outputFile) + if not os.path.exists(outputDir): + os.mkdir(outputDir) + ET.ElementTree(outputTree).write(outputFile) + + import sys + if '-d' in sys.argv: + # -------- TODO for debug only -------- + def indent(elem, level=0): + #function borrowed from: http://effbot.org/zone/element-lib.htm#prettyprint + i = "\n" + level*" " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + indent(elem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + + print 'Writing to file:', outputFile + indent(outputTree) + ET.dump(outputTree) diff --git a/framework/src/onos/tools/package/karaf-assembly/pom.xml b/framework/src/onos/tools/package/karaf-assembly/pom.xml new file mode 100644 index 00000000..4b47c0d1 --- /dev/null +++ b/framework/src/onos/tools/package/karaf-assembly/pom.xml @@ -0,0 +1,84 @@ + + + + + 4.0.0 + + + org.onosproject + onos-base + 1 + + + org.onosproject + onos-assembly + 1.0 + pom + + ONOS Apache Karaf assembly definitions + + + + + maven-antrun-plugin + 1.8 + + + generate-sources + + + + + + + + + run + + + + + + org.apache.karaf.tooling + karaf-maven-plugin + 3.0.3 + + + + features-add-to-repo + generate-resources + + features-add-to-repository + + + + file:${basedir}/target/staged-repos.xml + + + onos-uber-synthetic + + target/repo + + + + + + + + diff --git a/framework/src/onos/tools/package/maven-plugin/pom.xml b/framework/src/onos/tools/package/maven-plugin/pom.xml index c2b5d8ae..5a287d04 100644 --- a/framework/src/onos/tools/package/maven-plugin/pom.xml +++ b/framework/src/onos/tools/package/maven-plugin/pom.xml @@ -23,8 +23,9 @@ ../../build/pom.xml + org.onosproject onos-maven-plugin - 1.6-SNAPSHOT + 1.7-SNAPSHOT maven-plugin Maven plugin for packaging ONOS applications or generating diff --git a/framework/src/onos/tools/package/maven-plugin/src/main/java/org/onosproject/maven/OnosSwaggerMojo.java b/framework/src/onos/tools/package/maven-plugin/src/main/java/org/onosproject/maven/OnosSwaggerMojo.java index 0ee5382e..a98557dc 100644 --- a/framework/src/onos/tools/package/maven-plugin/src/main/java/org/onosproject/maven/OnosSwaggerMojo.java +++ b/framework/src/onos/tools/package/maven-plugin/src/main/java/org/onosproject/maven/OnosSwaggerMojo.java @@ -243,7 +243,7 @@ public class OnosSwaggerMojo extends AbstractMojo { String resourcePath, ArrayNode tagArray, ObjectNode definitions) { String fullPath = resourcePath, consumes = "", produces = "", comment = javaMethod.getComment(); - DocletTag tag = javaMethod.getTagByName("rsModel"); + DocletTag tag = javaMethod.getTagByName("onos.rsModel"); for (JavaAnnotation annotation : javaMethod.getAnnotations()) { String name = annotation.getType().getName(); if (name.equals(PATH)) { @@ -293,6 +293,7 @@ public class OnosSwaggerMojo extends AbstractMojo { + param + ".json"); String lines = Files.readLines(config, Charsets.UTF_8).stream().reduce((t, u) -> t + u). get(); + lines = lines.replaceAll("\\s+",""); definitions.putPOJO(param, lines); } catch (IOException e) { e.printStackTrace(); diff --git a/framework/src/onos/tools/package/yangtools/pom.xml b/framework/src/onos/tools/package/yangtools/pom.xml new file mode 100644 index 00000000..82422c0f --- /dev/null +++ b/framework/src/onos/tools/package/yangtools/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + org.onosproject + yangloader + 1.0-SNAPSHOT + + + commons-configuration + commons-configuration + 1.10 + + + commons-io + commons-io + 2.4 + + + com.google.guava + guava + 18.0 + + + org.onosproject + onlab-misc + 1.4.0-SNAPSHOT + + + commons-collections + commons-collections + 3.2.1 + true + + + org.slf4j + slf4j-jdk14 + 1.7.12 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + + + org.onoproject.yangtool.YangLoaderMain + + + + + + + + + + diff --git a/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoader.java b/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoader.java new file mode 100644 index 00000000..37126890 --- /dev/null +++ b/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoader.java @@ -0,0 +1,167 @@ +package org.onoproject.yangtool; + +import com.google.common.io.Files; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.onlab.util.Tools; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Class that takes in input two paths, one to the yang file and one where + * to generate the interface, and a yang container name, generates the sources + * through OpenDaylight code generator plugin from yang, and modifies + * them accordingly to the needs of the ONOS behavior system. + */ +public class YangLoader { + /** + * Public method to take a yang file from the input folder and generate classes + * to the output folder. + * @param inputFolder forlder with the yang files + * @param completeOuputFolder folder where to put the desired classes + * @throws IOException + * @throws ConfigurationException + * @throws InterruptedException + */ + public void generateBehaviourInterface(String inputFolder, + String completeOuputFolder) + throws IOException, ConfigurationException, InterruptedException { + File projectDir = createTemporaryProject(inputFolder); + List containerNames = findContainerName( + new File(projectDir.getAbsolutePath() + "/src")); + System.out.println("Containers " + containerNames); + generateJava(projectDir); + //modifyClasses(containerName, projectDir, completeInterfaceOuputFolder); + copyFiles(new File(projectDir.getAbsolutePath() + "/dst"), + new File(completeOuputFolder)); + //System.out.println("Sources in " + completeOuputFolder); + + } + + private List findContainerName(File scrDir) { + List allContainers = new ArrayList<>(); + Arrays.asList(scrDir.listFiles()).stream().forEach(f -> { + try { + FileUtils.readLines(f).stream() + .filter(line -> line.matches("(.*)container(.*)\\{")) + .collect(Collectors.toList()).forEach(s -> { + s = s.replace("container", ""); + s = s.replace("{", ""); + allContainers.add(s.trim()); + }); + + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + return allContainers; + } + + private File createTemporaryProject(String inputFolder) throws IOException, + ConfigurationException { + File tempDir = Files.createTempDir(); + File scrDir = new File(tempDir, "src"); + scrDir.mkdir(); + copyFiles(new File(inputFolder), scrDir); + createPomFile(tempDir, scrDir); + return tempDir; + + } + + private void copyFiles(File inputFolder, File scrDir) throws IOException { + Tools.copyDirectory(inputFolder, scrDir); + } + + private void createPomFile(File tempDir, File scrDir) throws ConfigurationException { + File pom = new File(tempDir, "pom.xml"); + File dstDir = new File(tempDir, "dst"); + dstDir.mkdir(); + XMLConfiguration cfg = new XMLConfiguration(); + cfg.load(getClass().getResourceAsStream("/pom-template.xml")); + cfg.setProperty("build.plugins.plugin.executions.execution." + + "configuration.yangFilesRootDir", scrDir.getPath()); + cfg.setProperty("build.plugins.plugin.executions." + + "execution.configuration.codeGenerators." + + "generator.outputBaseDir", dstDir.getPath()); + cfg.save(pom); + } + + private void generateJava(File projectDir) + throws IOException, InterruptedException { + Runtime rt = Runtime.getRuntime(); + Process pr = rt.exec("mvn generate-sources", null, projectDir); + String s = IOUtils.toString(pr.getInputStream(), "UTF-8"); + if (pr.waitFor() == 0) { + if (s.contains("[WARNING]")) { + System.out.println("Sources not generated, warning log: \n" + s); + } else { + System.out.println("Sources generated"); + } + } else { + System.out.println("Sources not generated. " + s + + " \nError " + pr.getInputStream().read()); + } + } + + //parsing classes part, for now is not used. + private void modifyClasses(String containerName, File projectDir, + String pathToNewInterface) throws IOException { + String odlInterfacepath = getPathWithFileName(containerName, projectDir.getPath()); + odlInterfacepath = odlInterfacepath + "/"; + parseClass(odlInterfacepath, pathToNewInterface, containerName); + System.out.println("ONOS behaviour interface generated " + + "correctly at " + pathToNewInterface); + } + + private String getPathWithFileName(String filename, String pathToGenerated) { + File[] directories = new File(pathToGenerated).listFiles(File::isDirectory); + while (directories.length != 0) { + pathToGenerated = pathToGenerated + "/" + directories[0].getName(); + directories = new File(pathToGenerated).listFiles(File::isDirectory); + } + File dir = new File(pathToGenerated); + File behaviour = (File) Arrays.asList(dir.listFiles()).stream() + .filter(f -> f.getName().equals(filename)).toArray()[0]; + return behaviour.getParentFile().getAbsolutePath(); + } + + private void parseClass(String filePath, String pathToNewInterface, + String filename) throws IOException { + InputStream fis = null; + String newFile = "package org.onosproject.net.behaviour;\n" + + "import org.onosproject.net.driver.HandlerBehaviour;\n"; + fis = new FileInputStream(filePath + filename); + InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8")); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + if (!line.contains("org.opendaylight.")) { + if (line.contains("ChildOf")) { + newFile = newFile + "HandlerBehaviour\n"; + } else { + newFile = newFile + line + "\n"; + } + } + } + PrintWriter out = new PrintWriter(pathToNewInterface + + filename.replace(".java", "") + + "Interface.java"); + out.print(newFile); + out.flush(); + } + + +} diff --git a/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoaderMain.java b/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoaderMain.java new file mode 100644 index 00000000..7b137677 --- /dev/null +++ b/framework/src/onos/tools/package/yangtools/src/main/java/org/onoproject/yangtool/YangLoaderMain.java @@ -0,0 +1,16 @@ +package org.onoproject.yangtool; + +import org.apache.commons.configuration.ConfigurationException; + +import java.io.IOException; + +/** + * Main of the uangloader tool in order to be called through command line. + */ +public class YangLoaderMain { + public static void main (String args []) throws IOException, + ConfigurationException, InterruptedException { + YangLoader yl = new YangLoader(); + yl.generateBehaviourInterface(args[0], args[1]); + } +} diff --git a/framework/src/onos/tools/package/yangtools/src/main/resources/pom-template.xml b/framework/src/onos/tools/package/yangtools/src/main/resources/pom-template.xml new file mode 100644 index 00000000..5280e213 --- /dev/null +++ b/framework/src/onos/tools/package/yangtools/src/main/resources/pom-template.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + groupId + yangloader + 1.0-SNAPSHOT + + + opendaylight-release + opendaylight-release + + http://nexus.opendaylight.org/content/repositories/opendaylight.release/ + + + + opendaylight-snapshot + opendaylight-snapshot + + http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ + + + + + + opendaylight-release + opendaylight-release + + http://nexus.opendaylight.org/content/repositories/opendaylight.release/ + + + + opendaylight-snapshot + opendaylight-snapshot + + http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ + + + + + + org.opendaylight.yangtools + yang-binding + 0.7.2-Lithium-SR2 + + + + + + org.opendaylight.yangtools + yang-maven-plugin + 0.7.2-Lithium-SR2 + + + + generate-sources + + + + INPUTDIR + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + + + OUTPUTDIR + + + false + + + + + + org.opendaylight.yangtools + maven-sal-api-gen-plugin + 0.7.2-Lithium-SR2 + jar + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + diff --git a/framework/src/onos/tools/test/bin/ogroup-opts b/framework/src/onos/tools/test/bin/ogroup-opts index f02b7a8f..eec2f224 100644 --- a/framework/src/onos/tools/test/bin/ogroup-opts +++ b/framework/src/onos/tools/test/bin/ogroup-opts @@ -51,7 +51,7 @@ complete -F _cell-opts cell vicell function _ocapp-opts () { local cur=${COMP_WORDS[COMP_CWORD]} if [ $COMP_CWORD -eq 1 ]; then - COMPREPLY=( $( compgen -W "bundle ui cli" -- $cur ) ) + COMPREPLY=( $( compgen -W "app bundle ui uitable uitopo cli" -- $cur ) ) fi } diff --git a/framework/src/onos/tools/test/cells/andrea b/framework/src/onos/tools/test/cells/andrea index 1f9f22fe..0074f2d6 100644 --- a/framework/src/onos/tools/test/cells/andrea +++ b/framework/src/onos/tools/test/cells/andrea @@ -8,4 +8,4 @@ export OCN="10.128.12.4" export OCT=$OC1 export ONOS_USE_SSH=true -export ONOS_APPS=drivers,openflow,proxyarp,ovsdb +export ONOS_APPS=drivers,openflow,proxyarp,ovsdb,pathpainter diff --git a/framework/src/onos/tools/test/cells/tomx b/framework/src/onos/tools/test/cells/tomx index 91036e67..bc7f1e06 100644 --- a/framework/src/onos/tools/test/cells/tomx +++ b/framework/src/onos/tools/test/cells/tomx @@ -8,4 +8,4 @@ export OCN="10.128.11.4" export OCT=$OC1 export ONOS_USE_SSH=true -export ONOS_APPS=drivers,openflow,proxyarp,mobility \ No newline at end of file +export ONOS_APPS=drivers,openflow,proxyarp,mobility,pathpainter \ No newline at end of file diff --git a/framework/src/onos/tools/test/configs/network-cfg-2x2-leaf-spine.json b/framework/src/onos/tools/test/configs/network-cfg-2x2-leaf-spine.json new file mode 100644 index 00000000..828d2735 --- /dev/null +++ b/framework/src/onos/tools/test/configs/network-cfg-2x2-leaf-spine.json @@ -0,0 +1,108 @@ +{ + "ports" : { + "of:0000000000000001/3" : { + "interfaces" : [ + { + "ips" : [ "10.0.1.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000001/4" : { + "interfaces" : [ + { + "ips" : [ "10.0.1.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000002/3" : { + "interfaces" : [ + { + "ips" : [ "10.0.2.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000002/4" : { + "interfaces" : [ + { + "ips" : [ "10.0.2.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + } + }, + "devices" : { + "of:0000000000000001" : { + "segmentrouting" : { + "name" : "Leaf-R1", + "nodeSid" : 101, + "routerIp" : "10.0.1.254", + "routerMac" : "00:00:00:00:01:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000002" : { + "segmentrouting" : { + "name" : "Leaf-R2", + "nodeSid" : 102, + "routerIp" : "10.0.2.254", + "routerMac" : "00:00:00:00:02:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000191" : { + "segmentrouting" : { + "name" : "Spine-R1", + "nodeSid" : 103, + "routerIp" : "192.168.0.11", + "routerMac" : "00:00:01:00:11:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + }, + "of:0000000000000192" : { + "segmentrouting" : { + "name" : "Spine-R2", + "nodeSid" : 104, + "routerIp" : "192.168.0.22", + "routerMac" : "00:00:01:00:22:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + } + }, + "hosts" : { + "00:00:00:00:00:01/4093" : { + "basic": { + "ips": ["10.0.1.1"], + "location": "of:0000000000000001/3" + } + }, + "00:00:00:00:00:02/4093" : { + "basic": { + "ips": ["10.0.1.2"], + "location": "of:0000000000000001/4" + } + }, + "00:00:00:00:00:03/4093" : { + "basic": { + "ips": ["10.0.2.1"], + "location": "of:0000000000000002/3" + } + }, + "00:00:00:00:00:04/4093" : { + "basic": { + "ips": ["10.0.2.2"], + "location": "of:0000000000000002/4" + } + } + } +} diff --git a/framework/src/onos/tools/test/configs/network-cfg-4x4-leaf-spine.json b/framework/src/onos/tools/test/configs/network-cfg-4x4-leaf-spine.json new file mode 100644 index 00000000..4efcf97d --- /dev/null +++ b/framework/src/onos/tools/test/configs/network-cfg-4x4-leaf-spine.json @@ -0,0 +1,208 @@ +{ + "ports" : { + "of:0000000000000001/5" : { + "interfaces" : [ + { + "ips" : [ "10.0.1.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000001/6" : { + "interfaces" : [ + { + "ips" : [ "10.0.1.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000002/5" : { + "interfaces" : [ + { + "ips" : [ "10.0.2.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000002/6" : { + "interfaces" : [ + { + "ips" : [ "10.0.2.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000003/5" : { + "interfaces" : [ + { + "ips" : [ "10.0.3.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000003/6" : { + "interfaces" : [ + { + "ips" : [ "10.0.3.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000004/5" : { + "interfaces" : [ + { + "ips" : [ "10.0.4.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + }, + "of:0000000000000004/6" : { + "interfaces" : [ + { + "ips" : [ "10.0.4.254/24" ], + "mac" : "08:9e:01:82:38:68", + "vlan" : "100" + } + ] + } + }, + "devices" : { + "of:0000000000000001" : { + "segmentrouting" : { + "name" : "Leaf-R1", + "nodeSid" : 101, + "routerIp" : "10.0.1.254", + "routerMac" : "00:00:00:00:01:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000002" : { + "segmentrouting" : { + "name" : "Leaf-R2", + "nodeSid" : 102, + "routerIp" : "10.0.2.254", + "routerMac" : "00:00:00:00:02:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000003" : { + "segmentrouting" : { + "name" : "Leaf-R3", + "nodeSid" : 103, + "routerIp" : "10.0.3.254", + "routerMac" : "00:00:00:00:03:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000004" : { + "segmentrouting" : { + "name" : "Leaf-R4", + "nodeSid" : 104, + "routerIp" : "10.0.4.254", + "routerMac" : "00:00:00:00:04:80", + "isEdgeRouter" : true, + "adjacencySids" : [] + } + }, + "of:0000000000000191" : { + "segmentrouting" : { + "name" : "Spine-R1", + "nodeSid" : 105, + "routerIp" : "192.168.0.11", + "routerMac" : "00:00:01:00:11:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + }, + "of:0000000000000192" : { + "segmentrouting" : { + "name" : "Spine-R2", + "nodeSid" : 106, + "routerIp" : "192.168.0.22", + "routerMac" : "00:00:01:00:22:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + }, + "of:0000000000000193" : { + "segmentrouting" : { + "name" : "Spine-R3", + "nodeSid" : 107, + "routerIp" : "192.168.0.33", + "routerMac" : "00:00:03:00:33:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + }, + "of:0000000000000194" : { + "segmentrouting" : { + "name" : "Spine-R4", + "nodeSid" : 108, + "routerIp" : "192.168.0.44", + "routerMac" : "00:00:04:00:44:80", + "isEdgeRouter" : false, + "adjacencySids" : [] + } + } + }, + "hosts" : { + "00:00:00:00:00:01/4093" : { + "basic": { + "ips": ["10.0.1.1"], + "location": "of:0000000000000001/5" + } + }, + "00:00:00:00:00:02/4093" : { + "basic": { + "ips": ["10.0.1.2"], + "location": "of:0000000000000001/6" + } + }, + "00:00:00:00:00:03/4093" : { + "basic": { + "ips": ["10.0.2.1"], + "location": "of:0000000000000002/5" + } + }, + "00:00:00:00:00:04/4093" : { + "basic": { + "ips": ["10.0.2.2"], + "location": "of:0000000000000002/6" + } + }, + "00:00:00:00:00:05/4093" : { + "basic": { + "ips": ["10.0.3.1"], + "location": "of:0000000000000003/5" + } + }, + "00:00:00:00:00:06/4093" : { + "basic": { + "ips": ["10.0.3.2"], + "location": "of:0000000000000003/6" + } + }, + "00:00:00:00:00:07/4093" : { + "basic": { + "ips": ["10.0.4.1"], + "location": "of:0000000000000004/5" + } + }, + "00:00:00:00:00:08/4093" : { + "basic": { + "ips": ["10.0.4.2"], + "location": "of:0000000000000004/6" + } + } + } +} diff --git a/framework/src/onos/tools/test/topos/attmplsfast.py b/framework/src/onos/tools/test/topos/attmplsfast.py index 7f904462..cc7479be 100644 --- a/framework/src/onos/tools/test/topos/attmplsfast.py +++ b/framework/src/onos/tools/test/topos/attmplsfast.py @@ -15,19 +15,23 @@ from mininet.util import dumpNodeConnections class AttMplsTopo( Topo ): "Internet Topology Zoo Specimen." - def build( self ): + def __init__( self ): "Create a topology." + # Initialize Topology + Topo.__init__( self ) + # add nodes, switches first... + NY54 = self.addSwitch( 's25' ) # 40.728270, -73.994483 CMBR = self.addSwitch( 's1' ) # 42.373730, -71.109734 - CHCG = self.addSwitch( 's2' ) # 41.877461, -87.642892 + CHCG = self.addSwitch( 's2', protocols='OpenFlow13' ) # 41.877461, -87.642892 CLEV = self.addSwitch( 's3' ) # 41.498928, -81.695217 RLGH = self.addSwitch( 's4' ) # 35.780150, -78.644026 ATLN = self.addSwitch( 's5' ) # 33.749017, -84.394168 PHLA = self.addSwitch( 's6' ) # 39.952906, -75.172278 WASH = self.addSwitch( 's7' ) # 38.906696, -77.035509 NSVL = self.addSwitch( 's8' ) # 36.166410, -86.787305 - STLS = self.addSwitch( 's9' ) # 38.626418, -90.198143 + STLS = self.addSwitch( 's9', protocols='OpenFlow13' ) # 38.626418, -90.198143 NWOR = self.addSwitch( 's10' ) # 29.951475, -90.078434 HSTN = self.addSwitch( 's11' ) # 29.763249, -95.368332 SNAN = self.addSwitch( 's12' ) # 29.424331, -98.491745 @@ -40,12 +44,12 @@ class AttMplsTopo( Topo ): PTLD = self.addSwitch( 's19' ) # 45.523317, -122.677768 STTL = self.addSwitch( 's20' ) # 47.607326, -122.331786 SLKC = self.addSwitch( 's21' ) # 40.759577, -111.895079 - LA03 = self.addSwitch( 's22' ) # 34.056346, -118.235951 + LA03 = self.addSwitch( 's22', protocols='OpenFlow13' ) # 34.056346, -118.235951 SNDG = self.addSwitch( 's23' ) # 32.714564, -117.153528 PHNX = self.addSwitch( 's24' ) # 33.448289, -112.076299 - NY54 = self.addSwitch( 's25' ) # 40.728270, -73.994483 # ... and now hosts + NY54_host = self.addHost( 'h25' ) CMBR_host = self.addHost( 'h1' ) CHCG_host = self.addHost( 'h2' ) CLEV_host = self.addHost( 'h3' ) @@ -70,7 +74,6 @@ class AttMplsTopo( Topo ): LA03_host = self.addHost( 'h22' ) SNDG_host = self.addHost( 'h23' ) PHNX_host = self.addHost( 'h24' ) - NY54_host = self.addHost( 'h25' ) # add edges between switch and corresponding host self.addLink( NY54 , NY54_host ) diff --git a/framework/src/onos/tools/test/topos/metro.py b/framework/src/onos/tools/test/topos/metro.py index 1979b103..5a73cb6b 100755 --- a/framework/src/onos/tools/test/topos/metro.py +++ b/framework/src/onos/tools/test/topos/metro.py @@ -86,8 +86,8 @@ class Domain(object): class OpticalDomain(Domain): """ An emulated optical metro core. It is Domain 0. """ def build(self): - oean = { "optical.regens": 0 } for i in range (1,4): + oean = { "optical.regens": 0 } self.addSwitch('OE%s' % i, dpid='0000ffffffffff0%s' % i, annotations=oean, cls=LINCSwitch) an = { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/GeoLocation.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/GeoLocation.java new file mode 100644 index 00000000..7e546531 --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/GeoLocation.java @@ -0,0 +1,85 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onlab.util; + +import com.google.common.base.MoreObjects; + +/** + * Geo location specified in terms of longitude and latitude. + */ +public class GeoLocation { + + public static final double EARTH_RADIUS_KM = 6378.1370D; + + private final double latitude; + private final double longitude; + + /** + * Creates a new location using the specified coordinates. + * + * @param latitude latitude line + * @param longitude longitude line + */ + public GeoLocation(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + /** + * Returns the latitude of this location. + * + * @return latitude + */ + public double latitude() { + return latitude; + } + + /** + * Returns the longitude of this location. + * + * @return longitude + */ + public double longitude() { + return longitude; + } + + /** + * Returns the distance in kilometers, between this location and another. + * + * @param other other geo location + * @return distance in kilometers + */ + public double kilometersTo(GeoLocation other) { + double hereLat = Math.toRadians(latitude); + double hereLon = Math.toRadians(longitude); + double thereLat = Math.toRadians(other.latitude); + double thereLon = Math.toRadians(other.longitude); + + double cos = Math.sin(hereLat) * Math.sin(thereLat) + + Math.cos(hereLat) * Math.cos(thereLat) * Math.cos(hereLon - thereLon); + return Math.acos(cos) * EARTH_RADIUS_KM; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("latitude", latitude) + .add("longitude", longitude) + .toString(); + } + +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Spectrum.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Spectrum.java index 42d76090..ca01c6e3 100644 --- a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Spectrum.java +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Spectrum.java @@ -19,11 +19,12 @@ package org.onlab.util; * Telecom optical wavelength bands: O, E, S, C, L and U bands. * * See ITU-T G-Series Recommendations, Supplement 39 + * See ITU-T G.694.1 for center frequency definition. */ public final class Spectrum { - private Spectrum() { - } + // Center frequency + public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1); // O band (original): 1260 to 1360 nm public static final Frequency O_BAND_MIN = Frequency.ofTHz(220.436); @@ -48,4 +49,7 @@ public final class Spectrum { // U band (ultra-long wavelength): 1625 to 1675 nm public static final Frequency U_BAND_MIN = Frequency.ofTHz(178.981); public static final Frequency U_BAND_MAX = Frequency.ofTHz(184.488); + + private Spectrum() { + } } diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java new file mode 100644 index 00000000..a497bcc4 --- /dev/null +++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onlab.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Test suite of the geo location. + */ +public class GeoLocationTest { + + @Test + public void basics() { + GeoLocation nLoc = new GeoLocation(40.7127, -74.0059); + GeoLocation wLoc = new GeoLocation(38.9047, -77.0164); + + assertEquals("incorrect latitude", 40.7127, nLoc.latitude(), 0.0001); + assertEquals("incorrect longitude", -74.00598, nLoc.longitude(), 0.0001); + assertEquals("incorrect distance", 326.74, nLoc.kilometersTo(wLoc), 0.01); + } + +} \ No newline at end of file diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java index b38633bf..f0383346 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java @@ -44,7 +44,7 @@ public class ApplicationsWebResource extends AbstractWebResource { * Get all installed applications. * Returns array of all installed applications. * - * @rsModel Applications + * @onos.rsModel Applications * @return 200 OK */ @GET @@ -57,7 +57,7 @@ public class ApplicationsWebResource extends AbstractWebResource { /** * Get application details. * Returns details of the specified application. - * @rsModel Application + * @onos.rsModel Application * @param name application name * @return 200 OK; 404; 401 */ diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java index 16a4dc7f..cedbd6b6 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java @@ -49,7 +49,7 @@ public class ClusterWebResource extends AbstractWebResource { * Returns array of all cluster nodes. * * @return 200 OK - * @rsModel Cluster + * @onos.rsModel Cluster */ @GET public Response getClusterNodes() { @@ -63,7 +63,7 @@ public class ClusterWebResource extends AbstractWebResource { * * @param id cluster node identifier * @return 200 OK - * @rsModel ClusterNode + * @onos.rsModel ClusterNode */ @GET @Path("{id}") @@ -80,7 +80,7 @@ public class ClusterWebResource extends AbstractWebResource { * @param config cluster definition * @return 200 OK * @throws IOException to signify bad request - * @rsModel ClusterPost + * @onos.rsModel ClusterPost */ @POST @Path("configuration") diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java index 23ca46e7..be1e5b63 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/DevicesWebResource.java @@ -46,7 +46,7 @@ public class DevicesWebResource extends AbstractWebResource { * Returns array of all discovered infrastructure devices. * * @return 200 OK - * @rsModel DevicesGet + * @onos.rsModel DevicesGet */ @GET public Response getDevices() { @@ -60,7 +60,7 @@ public class DevicesWebResource extends AbstractWebResource { * * @param id device identifier * @return 200 OK - * @rsModel DeviceGet + * @onos.rsModel DeviceGet */ @GET @Path("{id}") @@ -91,7 +91,7 @@ public class DevicesWebResource extends AbstractWebResource { * Get ports of infrastructure device. * Returns details of the specified infrastructure device. * - * @rsModel DeviceGetPorts + * @onos.rsModel DeviceGetPorts * @param id device identifier * @return 200 OK */ diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java index 252a3ba7..e5e1ddab 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/FlowsWebResource.java @@ -58,7 +58,7 @@ public class FlowsWebResource extends AbstractWebResource { /** * Get all flow entries. Returns array of all flow rules in the system. - * @rsModel Flows + * @onos.rsModel Flows * @return array of all the intents in the system */ @GET @@ -80,7 +80,7 @@ public class FlowsWebResource extends AbstractWebResource { /** * Get flow entries of a device. Returns array of all flow rules for the * specified device. - * @rsModel Flows + * @onos.rsModel Flows * @param deviceId device identifier * @return flow data as an array */ @@ -103,7 +103,7 @@ public class FlowsWebResource extends AbstractWebResource { /** * Get flow rule. Returns the flow entry specified by the device id and * flow rule id. - * @rsModel Flows + * @onos.rsModel Flows * @param deviceId device identifier * @param flowId flow rule identifier * @return flow data as an array @@ -130,7 +130,7 @@ public class FlowsWebResource extends AbstractWebResource { /** * Create new flow rule. Creates and installs a new flow rule for the * specified device. - * @rsModel FlowsPost + * @onos.rsModel FlowsPost * @param deviceId device identifier * @param stream flow rule JSON * @return status of the request - CREATED if the JSON is correct, diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java index 00cbdf2f..8f69c24d 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/HostsWebResource.java @@ -73,7 +73,7 @@ public class HostsWebResource extends AbstractWebResource { * Returns array of all known end-station hosts. * * @return 200 OK - * @rsModel Hosts + * @onos.rsModel Hosts */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -89,7 +89,7 @@ public class HostsWebResource extends AbstractWebResource { * * @param id host identifier * @return 200 OK - * @rsModel Host + * @onos.rsModel Host */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -108,7 +108,7 @@ public class HostsWebResource extends AbstractWebResource { * @param mac host MAC address * @param vlan host VLAN identifier * @return 200 OK - * @rsModel Host + * @onos.rsModel Host */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -128,7 +128,7 @@ public class HostsWebResource extends AbstractWebResource { * @param stream input JSON * @return status of the request - CREATED if the JSON is correct, * BAD_REQUEST if the JSON is invalid - * @rsModel HostPut + * @onos.rsModel HostPut */ @POST @Consumes(MediaType.APPLICATION_JSON) diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java index 2c63db9c..e6955045 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/IntentsWebResource.java @@ -70,7 +70,7 @@ public class IntentsWebResource extends AbstractWebResource { /** * Get all intents. * Returns array containing all the intents in the system. - * @rsModel Intents + * @onos.rsModel Intents * @return array of all the intents in the system */ @GET @@ -84,7 +84,7 @@ public class IntentsWebResource extends AbstractWebResource { /** * Get intent by application and key. * Returns details of the specified intent. - * @rsModel Intents + * @onos.rsModel Intents * @param appId application identifier * @param key intent key * @return intent data @@ -136,7 +136,7 @@ public class IntentsWebResource extends AbstractWebResource { /** * Submit a new intent. * Creates and submits intent from the JSON request. - * @rsModel IntentHost + * @onos.rsModel IntentHost * @param stream input JSON * @return status of the request - CREATED if the JSON is correct, * BAD_REQUEST if the JSON is invalid diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java index e36ea8af..edf9f028 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java @@ -44,7 +44,7 @@ public class LinksWebResource extends AbstractWebResource { /** * Get infrastructure links. * Returns array of all links, or links for the specified device or port. - * @rsModel LinksGet + * @onos.rsModel LinksGet * @param deviceId (optional) device identifier * @param port (optional) port number * @param direction (optional) direction qualifier diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java index 69c0b6a3..9e474fd3 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/NetworkConfigWebResource.java @@ -68,7 +68,6 @@ public class NetworkConfigWebResource extends AbstractWebResource { /** * Get entire network configuration base. * - * @rsModel NetCfgGet * @return network configuration JSON */ @GET @@ -185,7 +184,6 @@ public class NetworkConfigWebResource extends AbstractWebResource { /** * Upload bulk network configuration. * - * @rsModel NetCfgGet * @param request network configuration JSON rooted at the top node * @return empty response * @throws IOException if unable to parse the request diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java index c14b4ec2..9968d1e7 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/PathsWebResource.java @@ -60,7 +60,7 @@ public class PathsWebResource extends AbstractWebResource { /** * Get all shortest paths between any two hosts or devices. * Returns array of all shortest paths between any two elements. - * @rsModel Paths + * @onos.rsModel Paths * @param src source identifier * @param dst destination identifier * @return path data @@ -79,7 +79,7 @@ public class PathsWebResource extends AbstractWebResource { /** * Get all shortest disjoint paths between any two hosts or devices. * Returns array of all shortest disjoint paths between any two elements. - * @rsModel Paths + * @onos.rsModel Paths * @param src source identifier * @param dst destination identifier * @return path data diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java index 284d3775..7c6dd74e 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/StatisticsWebResource.java @@ -60,7 +60,7 @@ public class StatisticsWebResource extends AbstractWebResource { /** * Get load statistics for all links or for a specific link. - * @rsModel StatisticsFlowsLink + * @onos.rsModel StatisticsFlowsLink * @param deviceId (optional) device ID for a specific link * @param port (optional) port number for a specified link * @return JSON encoded array lof Load objects @@ -102,7 +102,7 @@ public class StatisticsWebResource extends AbstractWebResource { /** * Get table statistics for all tables of all devices. - * @rsModel StatisticsFlowsTables + * @onos.rsModel StatisticsFlowsTables * @return JSON encoded array of table statistics */ @GET @@ -131,7 +131,7 @@ public class StatisticsWebResource extends AbstractWebResource { /** * Get table statistics for all tables of a specified device. - * @rsModel StatisticsFlowsTables + * @onos.rsModel StatisticsFlowsTables * @param deviceId device ID * @return JSON encoded array of table statistics */ @@ -157,7 +157,7 @@ public class StatisticsWebResource extends AbstractWebResource { /** * Get port statistics of all devices. - * @rsModel StatisticsPorts + * @onos.rsModel StatisticsPorts * @return JSON encoded array of port statistics */ @GET @@ -186,7 +186,7 @@ public class StatisticsWebResource extends AbstractWebResource { /** * Get port statistics of a specified devices. - * @rsModel StatisticsPorts + * @onos.rsModel StatisticsPorts * @param deviceId device ID * @return JSON encoded array of port statistics */ diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java index d51bd5a0..683f7afe 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/TopologyWebResource.java @@ -50,7 +50,7 @@ public class TopologyWebResource extends AbstractWebResource { * Get overview of current topology. * * @return topology overview - * @rsModel Topology + * @onos.rsModel Topology */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -64,7 +64,7 @@ public class TopologyWebResource extends AbstractWebResource { * Get overview of topology SCCs. * * @return topology clusters overview - * @rsModel TopologyClusters + * @onos.rsModel TopologyClusters */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -82,7 +82,7 @@ public class TopologyWebResource extends AbstractWebResource { * * @param clusterId id of the cluster to query * @return topology cluster details - * @rsModel TopologyCluster + * @onos.rsModel TopologyCluster */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -106,7 +106,7 @@ public class TopologyWebResource extends AbstractWebResource { * * @param clusterId id of the cluster to query * @return topology cluster devices - * @rsModel TopologyClustersDevices + * @onos.rsModel TopologyClustersDevices */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -130,7 +130,7 @@ public class TopologyWebResource extends AbstractWebResource { * * @param clusterId id of the cluster to query * @return topology cluster links - * @rsModel LinksGet + * @onos.rsModel LinksGet */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -180,7 +180,7 @@ public class TopologyWebResource extends AbstractWebResource { * @param connectPointString deviceid:portnumber * @return JSON representation of true if the connect point is broadcast, * false otherwise - * @rsModel TopologyBroadcast + * @onos.rsModel TopologyBroadcast */ @GET @Produces(MediaType.APPLICATION_JSON) @@ -205,7 +205,7 @@ public class TopologyWebResource extends AbstractWebResource { * @param connectPointString deviceid:portnumber * @return JSON representation of true if the connect point is broadcast, * false otherwise - * @rsModel TopologyInfrastructure + * @onos.rsModel TopologyInfrastructure */ @GET @Produces(MediaType.APPLICATION_JSON) diff --git a/framework/src/onos/web/api/src/main/resources/definitions/Application.json b/framework/src/onos/web/api/src/main/resources/definitions/Application.json index ea6c3ea2..fb5bbeb9 100644 --- a/framework/src/onos/web/api/src/main/resources/definitions/Application.json +++ b/framework/src/onos/web/api/src/main/resources/definitions/Application.json @@ -25,7 +25,7 @@ }, "version": { "type": "string", - "example": "1.4.0.SNAPSHOT" + "example": "1.2.3" }, "description": { "type": "string", @@ -48,7 +48,7 @@ }, "featuresRepo": { "type": "string", - "example": "mvn:org.onosproject/onos-app-cip/1.4.0-SNAPSHOT/xml/features" + "example": "mvn:org.onosproject/onos-app-cip/1.2.3/xml/features" }, "features": { "type": "array", diff --git a/framework/src/onos/web/api/src/main/resources/definitions/ApplicationPost.json b/framework/src/onos/web/api/src/main/resources/definitions/ApplicationPost.json index ea6c3ea2..fb5bbeb9 100644 --- a/framework/src/onos/web/api/src/main/resources/definitions/ApplicationPost.json +++ b/framework/src/onos/web/api/src/main/resources/definitions/ApplicationPost.json @@ -25,7 +25,7 @@ }, "version": { "type": "string", - "example": "1.4.0.SNAPSHOT" + "example": "1.2.3" }, "description": { "type": "string", @@ -48,7 +48,7 @@ }, "featuresRepo": { "type": "string", - "example": "mvn:org.onosproject/onos-app-cip/1.4.0-SNAPSHOT/xml/features" + "example": "mvn:org.onosproject/onos-app-cip/1.2.3/xml/features" }, "features": { "type": "array", diff --git a/framework/src/onos/web/api/src/main/resources/definitions/Applications.json b/framework/src/onos/web/api/src/main/resources/definitions/Applications.json index d7653619..304404a4 100644 --- a/framework/src/onos/web/api/src/main/resources/definitions/Applications.json +++ b/framework/src/onos/web/api/src/main/resources/definitions/Applications.json @@ -38,7 +38,7 @@ }, "version": { "type": "string", - "example": "1.4.0.SNAPSHOT" + "example": "1.2.3" }, "description": { "type": "string", @@ -61,7 +61,7 @@ }, "featuresRepo": { "type": "string", - "example": "mvn:org.onosproject/onos-app-cip/1.4.0-SNAPSHOT/xml/features" + "example": "mvn:org.onosproject/onos-app-cip/1.2.3/xml/features" }, "features": { "type": "array", diff --git a/framework/src/onos/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java b/framework/src/onos/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java new file mode 100644 index 00000000..2b341af2 --- /dev/null +++ b/framework/src/onos/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java @@ -0,0 +1,352 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.rest.resources; + +import java.net.HttpURLConnection; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.net.DefaultDevice; +import org.onosproject.net.Device; +import org.onosproject.net.Link; +import org.onosproject.net.config.Config; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.net.config.NetworkConfigServiceAdapter; +import org.onosproject.net.config.SubjectFactory; +import org.onosproject.rest.ResourceTest; + +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableSet; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.fail; + +/** + * Unit tests for network config web resource. + */ +public class NetworkConfigWebResourceTest extends ResourceTest { + + MockNetworkConfigService mockNetworkConfigService; + + public class MockDeviceConfig extends Config { + + final String field1Value; + final String field2Value; + + MockDeviceConfig(String value1, String value2) { + field1Value = value1; + field2Value = value2; + } + + @Override + public String key() { + return "basic"; + } + + @Override + public JsonNode node() { + return new ObjectMapper() + .createObjectNode() + .put("field1", field1Value) + .put("field2", field2Value); + } + } + + /** + * Mock config factory for devices. + */ + private final SubjectFactory mockDevicesSubjectFactory = + new SubjectFactory(Device.class, "devices") { + @Override + public Device createSubject(String subjectKey) { + DefaultDevice device = createMock(DefaultDevice.class); + replay(device); + return device; + } + + @Override + public Class subjectClass() { + return Device.class; + } + }; + + /** + * Mock config factory for links. + */ + private final SubjectFactory mockLinksSubjectFactory = + new SubjectFactory(Link.class, "links") { + @Override + public Link createSubject(String subjectKey) { + return null; + } + + @Override + public Class subjectClass() { + return Link.class; + } + }; + + /** + * Mocked config service. + */ + class MockNetworkConfigService extends NetworkConfigServiceAdapter { + + Set devicesSubjects = new HashSet<>(); + Set devicesConfigs = new HashSet<>(); + Set linksSubjects = new HashSet(); + Set linksConfigs = new HashSet<>(); + + @Override + public Set getSubjectClasses() { + return ImmutableSet.of(Device.class, Link.class); + } + + @Override + public SubjectFactory getSubjectFactory(Class subjectClass) { + if (subjectClass == Device.class) { + return mockDevicesSubjectFactory; + } else if (subjectClass == Link.class) { + return mockLinksSubjectFactory; + } + return null; + } + + @Override + public SubjectFactory getSubjectFactory(String subjectClassKey) { + if (subjectClassKey.equals("devices")) { + return mockDevicesSubjectFactory; + } else if (subjectClassKey.equals("links")) { + return mockLinksSubjectFactory; + } + return null; + } + + @SuppressWarnings("unchecked") + @Override + public Set getSubjects(Class subjectClass) { + if (subjectClass == Device.class) { + return devicesSubjects; + } else if (subjectClass == Link.class) { + return linksSubjects; + } + return null; + } + + @SuppressWarnings("unchecked") + @Override + public Set> getConfigs(S subject) { + if (subject instanceof Device || subject.toString().contains("device")) { + return devicesConfigs; + } else if (subject.toString().contains("link")) { + return linksConfigs; + } + return null; + } + + @SuppressWarnings("unchecked") + @Override + public > C getConfig(S subject, Class configClass) { + + if (configClass == MockDeviceConfig.class) { + return (C) devicesConfigs.toArray()[0]; + } + return null; + } + + @Override + public Class getConfigClass(String subjectClassKey, String configKey) { + return MockDeviceConfig.class; + } + } + + /** + * Sets up mocked config service. + */ + @Before + public void setUp() { + mockNetworkConfigService = new MockNetworkConfigService(); + ServiceDirectory testDirectory = + new TestServiceDirectory() + .add(NetworkConfigService.class, mockNetworkConfigService); + BaseResource.setServiceDirectory(testDirectory); + } + + /** + * Sets up test config data. + */ + @SuppressWarnings("unchecked") + public void setUpConfigData() { + mockNetworkConfigService.devicesSubjects.add("device1"); + mockNetworkConfigService.devicesConfigs.add(new MockDeviceConfig("v1", "v2")); + } + + /** + * Tests the result of the rest api GET when there are no configs. + */ + @Test + public void testEmptyConfigs() { + final WebResource rs = resource(); + final String response = rs.path("network/configuration").get(String.class); + + assertThat(response, containsString("\"devices\":{}")); + assertThat(response, containsString("\"links\":{}")); + } + + /** + * Tests the result of the rest api GET for a single subject with no configs. + */ + @Test + public void testEmptyConfig() { + final WebResource rs = resource(); + final String response = rs.path("network/configuration/devices").get(String.class); + + assertThat(response, is("{}")); + } + + /** + * Tests the result of the rest api GET for a single subject that + * is undefined. + */ + @Test + public void testNonExistentConfig() { + final WebResource rs = resource(); + + try { + final String response = rs.path("network/configuration/nosuchkey").get(String.class); + fail("GET of non-existent key does not produce an exception " + response); + } catch (UniformInterfaceException e) { + assertThat(e.getResponse().getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND)); + } + } + + private void checkBasicAttributes(JsonValue basic) { + Assert.assertThat(basic.asObject().get("field1").asString(), is("v1")); + Assert.assertThat(basic.asObject().get("field2").asString(), is("v2")); + } + + /** + * Tests the result of the rest api GET when there is a config. + */ + @Test + + public void testConfigs() { + setUpConfigData(); + final WebResource rs = resource(); + final String response = rs.path("network/configuration").get(String.class); + + final JsonObject result = JsonObject.readFrom(response); + Assert.assertThat(result, notNullValue()); + + Assert.assertThat(result.names(), hasSize(2)); + + JsonValue devices = result.get("devices"); + Assert.assertThat(devices, notNullValue()); + + JsonValue device1 = devices.asObject().get("device1"); + Assert.assertThat(device1, notNullValue()); + + JsonValue basic = device1.asObject().get("basic"); + Assert.assertThat(basic, notNullValue()); + + checkBasicAttributes(basic); + } + + /** + * Tests the result of the rest api single subject key GET when + * there is a config. + */ + @Test + public void testSingleSubjectKeyConfig() { + setUpConfigData(); + final WebResource rs = resource(); + final String response = rs.path("network/configuration/devices").get(String.class); + + final JsonObject result = JsonObject.readFrom(response); + Assert.assertThat(result, notNullValue()); + + Assert.assertThat(result.names(), hasSize(1)); + + JsonValue device1 = result.asObject().get("device1"); + Assert.assertThat(device1, notNullValue()); + + JsonValue basic = device1.asObject().get("basic"); + Assert.assertThat(basic, notNullValue()); + + checkBasicAttributes(basic); + } + + /** + * Tests the result of the rest api single subject GET when + * there is a config. + */ + @Test + public void testSingleSubjectConfig() { + setUpConfigData(); + final WebResource rs = resource(); + final String response = + rs.path("network/configuration/devices/device1") + .get(String.class); + + final JsonObject result = JsonObject.readFrom(response); + Assert.assertThat(result, notNullValue()); + + Assert.assertThat(result.names(), hasSize(1)); + + JsonValue basic = result.asObject().get("basic"); + Assert.assertThat(basic, notNullValue()); + + checkBasicAttributes(basic); + } + + /** + * Tests the result of the rest api single subject single config GET when + * there is a config. + */ + @Test + public void testSingleSubjectSingleConfig() { + setUpConfigData(); + final WebResource rs = resource(); + final String response = + rs.path("network/configuration/devices/device1/basic") + .get(String.class); + + final JsonObject result = JsonObject.readFrom(response); + Assert.assertThat(result, notNullValue()); + + Assert.assertThat(result.names(), hasSize(2)); + + checkBasicAttributes(result); + } + + // TODO: Add test for DELETE and POST +} diff --git a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java index f35b6c03..a8e112a4 100644 --- a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java +++ b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java @@ -386,15 +386,16 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { Topology topology = topologyService.currentTopology(); return new PropertyPanel("ONOS Summary", "node") - .addProp(Properties.DEVICES, topology.deviceCount()) + .addProp(Properties.VERSION, version) + .addSeparator() + .addProp(Properties.DEVICES, deviceService.getDeviceCount()) .addProp(Properties.LINKS, topology.linkCount()) .addProp(Properties.HOSTS, hostService.getHostCount()) .addProp(Properties.TOPOLOGY_SSCS, topology.clusterCount()) .addSeparator() .addProp(Properties.INTENTS, intentService.getIntentCount()) .addProp(Properties.TUNNELS, tunnelService.tunnelCount()) - .addProp(Properties.FLOWS, flowService.getFlowRuleCount()) - .addProp(Properties.VERSION, version); + .addProp(Properties.FLOWS, flowService.getFlowRuleCount()); } // Returns property panel model for device details response. diff --git a/framework/src/onos/web/gui/src/main/webapp/_sdh/topojson/countrycodes.html b/framework/src/onos/web/gui/src/main/webapp/_sdh/topojson/countrycodes.html new file mode 100644 index 00000000..246d9e4c --- /dev/null +++ b/framework/src/onos/web/gui/src/main/webapp/_sdh/topojson/countrycodes.html @@ -0,0 +1,376 @@ + + + + + 2-Letter, 3-Letter, Country Codes for All Countries in the World + + + + + + + +
+
+
+
+

Complete List of Country Codes

+
+

+ The 2-letter codes shown below are supplied by the ISO + (International Organization for Standardization). + It bases its list of country names and abbreviations on + the list of names published by the United Nations. + The UN also uses 3-letter codes, and numerical codes + to identify nations. +

+ + + + + + + + + + + + +
Country A2 (ISO) A3 (UN) NUM (UN)
+
+
+
+ + + + + diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js index cc26360f..d6a517fc 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js @@ -149,6 +149,10 @@ rx: 4 }, host: { + badge: { + dx: 14, + dy: -14 + }, radius: { noGlyph: 9, withGlyph: 14 diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css index dda6d5c6..0319b9b7 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css @@ -82,10 +82,10 @@ #topo-p-detail { /* Base css from panel.css */ - top: 320px; + top: 338px; } html[data-platform='iPad'] #topo-p-detail { - top: 336px; + top: 354px; } #topo-p-detail .actionBtns .actionBtn { @@ -452,7 +452,7 @@ html[data-platform='iPad'] #topo-p-detail { } #ov-topo svg .node .badge.badgeInfo circle { - fill: #ccf; + fill: #99d; } #ov-topo svg .node .badge.badgeWarn circle { @@ -464,7 +464,7 @@ html[data-platform='iPad'] #topo-p-detail { } #ov-topo svg .node .badge use { - fill: white; + fill: white !important; } #ov-topo svg .node .badge.badgeInfo use { @@ -472,7 +472,7 @@ html[data-platform='iPad'] #topo-p-detail { } #ov-topo svg .node .badge text { - fill: white; + fill: white !important; } #ov-topo svg .node .badge.badgeInfo text { diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js index 702584af..3564eb33 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js @@ -304,6 +304,12 @@ return c.properties.continent === 'South America'; }, + ns_america: function (c) { + return c.properties.custom === 'US-cont' || + c.properties.subregion === 'Central America' || + c.properties.continent === 'South America'; + }, + japan: function (c) { return c.properties.geounit === 'Japan'; }, diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js index 1d2c5b10..5bf2eb4f 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js @@ -200,7 +200,6 @@ }; } - function updateDeviceRendering(d) { var label = trimLabel(deviceLabel(d)), noLabel = !label, @@ -237,31 +236,50 @@ // handle badge, if defined if (bdg) { - node.select('g.badge').remove(); - - bsel = node.append('g') - .classed('badge', true) - .classed(badgeStatus(bdg), true) - .attr('transform', sus.translate(dx + dim, dy)); - - bsel.append('circle') - .attr('r', bcr); - - if (bdg.txt) { - bsel.append('text') - .attr('dy', badgeConfig.yoff) - .attr('text-anchor', 'middle') - .text(bdg.txt); - } else if (bdg.gid) { - bsel.append('use') - .attr({ - width: bcgd * 2, - height: bcgd * 2, - transform: sus.translate(-bcgd, -bcgd), - 'xlink:href': '#' + bdg.gid - }); + renderBadge(node, bdg, { dx: dx + dim, dy: dy }); + } + } - } + function updateHostRendering(d) { + var node = d.el, + bdg = d.badge; + + updateHostLabel(d); + + // handle badge, if defined + if (bdg) { + renderBadge(node, bdg, icfg.host.badge); + } + } + + function renderBadge(node, bdg, boff) { + var bsel, + bcr = badgeConfig.radius, + bcgd = badgeConfig.gdelta; + + node.select('g.badge').remove(); + + bsel = node.append('g') + .classed('badge', true) + .classed(badgeStatus(bdg), true) + .attr('transform', sus.translate(boff.dx, boff.dy)); + + bsel.append('circle') + .attr('r', bcr); + + if (bdg.txt) { + bsel.append('text') + .attr('dy', badgeConfig.yoff) + .attr('text-anchor', 'middle') + .text(bdg.txt); + } else if (bdg.gid) { + bsel.append('use') + .attr({ + width: bcgd * 2, + height: bcgd * 2, + transform: sus.translate(-bcgd, -bcgd), + 'xlink:href': '#' + bdg.gid + }); } } @@ -292,7 +310,7 @@ } function hostExisting(d) { - updateHostLabel(d); + updateHostRendering(d); api.posNode(d, true); } diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js index 2dee4c40..fb7921ad 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js @@ -312,8 +312,11 @@ } data.hosts.forEach(function (host) { - var hdata = api.findNodeById(host.id); + var hdata = api.findNodeById(host.id), + badgeData = host.badge || null; + if (hdata && !hdata.el.empty()) { + hdata.badge = badgeData; if (!host.subdue) { api.unsupNode(hdata.id, less); } diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoPanel.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoPanel.js index 7db17f0d..1b8c2192 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoPanel.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoPanel.js @@ -32,7 +32,7 @@ panelOpts = { width: 260 }, - sumMax = 240, + sumMax = 262, padTop = 20, devPath = 'device'; diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js index 804e2a3c..fbcdaf6d 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js @@ -167,7 +167,7 @@ // generate radio button set for overlays; start with 'none' var rset = [{ - gid: 'topo', + gid: 'unknown', tooltip: 'No Overlay', cb: function () { tov.tbSelection(null, switchOverlayActions); diff --git a/framework/src/onos/web/gui/src/main/webapp/data/map/countries.topojson b/framework/src/onos/web/gui/src/main/webapp/data/map/countries.topojson index 8116a00d..778d51d8 100644 --- a/framework/src/onos/web/gui/src/main/webapp/data/map/countries.topojson +++ b/framework/src/onos/web/gui/src/main/webapp/data/map/countries.topojson @@ -1 +1,9 @@ -{"type":"Topology","objects":{"countries":{"type":"GeometryCollection","geometries":[{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Aruba","adm0_a3":"ABW","geou_dif":0,"geounit":"Aruba","gu_a3":"ABW","su_dif":0,"subunit":"Aruba","su_a3":"ABW","brk_diff":0,"name":"Aruba","name_long":"Aruba","brk_a3":"ABW","brk_name":"Aruba","brk_group":null,"abbrev":"Aruba","postal":"AW","formal_en":"Aruba","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"Aruba","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":103065,"gdp_md_est":2258,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AW","iso_a3":"ABW","iso_n3":"533","un_a3":"533","wb_a2":"AW","wb_a3":"ABW","woe_id":-99,"adm0_a3_is":"ABW","adm0_a3_us":"ABW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":4,"homepart":-99},"arcs":[[0]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Afghanistan","sov_a3":"AFG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Afghanistan","adm0_a3":"AFG","geou_dif":0,"geounit":"Afghanistan","gu_a3":"AFG","su_dif":0,"subunit":"Afghanistan","su_a3":"AFG","brk_diff":0,"name":"Afghanistan","name_long":"Afghanistan","brk_a3":"AFG","brk_name":"Afghanistan","brk_group":null,"abbrev":"Afg.","postal":"AF","formal_en":"Islamic State of Afghanistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Afghanistan","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":8,"mapcolor13":7,"pop_est":28400000,"gdp_md_est":22270,"pop_year":-99,"lastcensus":1979,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"AF","iso_a3":"AFG","iso_n3":"004","un_a3":"004","wb_a2":"AF","wb_a3":"AFG","woe_id":-99,"adm0_a3_is":"AFG","adm0_a3_us":"AFG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1,2,3,4,5,6,7]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Angola","sov_a3":"AGO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Angola","adm0_a3":"AGO","geou_dif":0,"geounit":"Angola","gu_a3":"AGO","su_dif":0,"subunit":"Angola","su_a3":"AGO","brk_diff":0,"name":"Angola","name_long":"Angola","brk_a3":"AGO","brk_name":"Angola","brk_group":null,"abbrev":"Ang.","postal":"AO","formal_en":"People's Republic of Angola","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Angola","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":6,"mapcolor13":1,"pop_est":12799293,"gdp_md_est":110300,"pop_year":-99,"lastcensus":1970,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AO","iso_a3":"AGO","iso_n3":"024","un_a3":"024","wb_a2":"AO","wb_a3":"AGO","woe_id":-99,"adm0_a3_is":"AGO","adm0_a3_us":"AGO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[8,9,10,11]],[[12,13,14]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Anguilla","adm0_a3":"AIA","geou_dif":0,"geounit":"Anguilla","gu_a3":"AIA","su_dif":0,"subunit":"Anguilla","su_a3":"AIA","brk_diff":0,"name":"Anguilla","name_long":"Anguilla","brk_a3":"AIA","brk_name":"Anguilla","brk_group":null,"abbrev":"Ang.","postal":"AI","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Anguilla","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":14436,"gdp_md_est":108.9,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AI","iso_a3":"AIA","iso_n3":"660","un_a3":"660","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"AIA","adm0_a3_us":"AIA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[15]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Albania","sov_a3":"ALB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Albania","adm0_a3":"ALB","geou_dif":0,"geounit":"Albania","gu_a3":"ALB","su_dif":0,"subunit":"Albania","su_a3":"ALB","brk_diff":0,"name":"Albania","name_long":"Albania","brk_a3":"ALB","brk_name":"Albania","brk_group":null,"abbrev":"Alb.","postal":"AL","formal_en":"Republic of Albania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Albania","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":3639453,"gdp_md_est":21810,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AL","iso_a3":"ALB","iso_n3":"008","un_a3":"008","wb_a2":"AL","wb_a3":"ALB","woe_id":-99,"adm0_a3_is":"ALB","adm0_a3_us":"ALB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[16,17,18,19,20]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Finland","sov_a3":"FI1","adm0_dif":1,"level":2,"type":"Country","admin":"Aland","adm0_a3":"ALD","geou_dif":0,"geounit":"Aland","gu_a3":"ALD","su_dif":0,"subunit":"Aland","su_a3":"ALD","brk_diff":0,"name":"Aland","name_long":"Aland Islands","brk_a3":"ALD","brk_name":"Aland","brk_group":null,"abbrev":"Aland","postal":"AI","formal_en":"Åland Islands","formal_fr":null,"note_adm0":"Fin.","note_brk":null,"name_sort":"Aland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":6,"pop_est":27153,"gdp_md_est":1563,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AX","iso_a3":"ALA","iso_n3":"248","un_a3":"248","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ALA","adm0_a3_us":"ALD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":13,"abbrev_len":5,"tiny":5,"homepart":-99},"arcs":[[[21]],[[22]],[[23]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Andorra","sov_a3":"AND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Andorra","adm0_a3":"AND","geou_dif":0,"geounit":"Andorra","gu_a3":"AND","su_dif":0,"subunit":"Andorra","su_a3":"AND","brk_diff":0,"name":"Andorra","name_long":"Andorra","brk_a3":"AND","brk_name":"Andorra","brk_group":null,"abbrev":"And.","postal":"AND","formal_en":"Principality of Andorra","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Andorra","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":83888,"gdp_md_est":3660,"pop_year":-99,"lastcensus":1989,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AD","iso_a3":"AND","iso_n3":"020","un_a3":"020","wb_a2":"AD","wb_a3":"ADO","woe_id":-99,"adm0_a3_is":"AND","adm0_a3_us":"AND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[24,25]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Arab Emirates","sov_a3":"ARE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"United Arab Emirates","adm0_a3":"ARE","geou_dif":0,"geounit":"United Arab Emirates","gu_a3":"ARE","su_dif":0,"subunit":"United Arab Emirates","su_a3":"ARE","brk_diff":0,"name":"United Arab Emirates","name_long":"United Arab Emirates","brk_a3":"ARE","brk_name":"United Arab Emirates","brk_group":null,"abbrev":"U.A.E.","postal":"AE","formal_en":"United Arab Emirates","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United Arab Emirates","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":3,"pop_est":4798491,"gdp_md_est":184300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AE","iso_a3":"ARE","iso_n3":"784","un_a3":"784","wb_a2":"AE","wb_a3":"ARE","woe_id":-99,"adm0_a3_is":"ARE","adm0_a3_us":"ARE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":20,"long_len":20,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[26]],[[27]],[[28]],[[29]],[[30,31,32,33,34],[35]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Argentina","sov_a3":"ARG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Argentina","adm0_a3":"ARG","geou_dif":0,"geounit":"Argentina","gu_a3":"ARG","su_dif":0,"subunit":"Argentina","su_a3":"ARG","brk_diff":0,"name":"Argentina","name_long":"Argentina","brk_a3":"ARG","brk_name":"Argentina","brk_group":null,"abbrev":"Arg.","postal":"AR","formal_en":"Argentine Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Argentina","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":13,"pop_est":40913584,"gdp_md_est":573900,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AR","iso_a3":"ARG","iso_n3":"032","un_a3":"032","wb_a2":"AR","wb_a3":"ARG","woe_id":-99,"adm0_a3_is":"ARG","adm0_a3_us":"ARG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[36]],[[37,38]],[[39]],[[40,41,42,43,44,45]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Armenia","sov_a3":"ARM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Armenia","adm0_a3":"ARM","geou_dif":0,"geounit":"Armenia","gu_a3":"ARM","su_dif":0,"subunit":"Armenia","su_a3":"ARM","brk_diff":0,"name":"Armenia","name_long":"Armenia","brk_a3":"ARM","brk_name":"Armenia","brk_group":null,"abbrev":"Arm.","postal":"ARM","formal_en":"Republic of Armenia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Armenia","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":2,"mapcolor13":10,"pop_est":2967004,"gdp_md_est":18770,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AM","iso_a3":"ARM","iso_n3":"051","un_a3":"051","wb_a2":"AM","wb_a3":"ARM","woe_id":-99,"adm0_a3_is":"ARM","adm0_a3_us":"ARM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[46]],[[47,48,49,50,51],[52]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"American Samoa","adm0_a3":"ASM","geou_dif":0,"geounit":"American Samoa","gu_a3":"ASM","su_dif":0,"subunit":"American Samoa","su_a3":"ASM","brk_diff":0,"name":"American Samoa","name_long":"American Samoa","brk_a3":"ASM","brk_name":"American Samoa","brk_group":null,"abbrev":"Am. Samoa","postal":"AS","formal_en":"American Samoa","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"American Samoa","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":65628,"gdp_md_est":575.3,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AS","iso_a3":"ASM","iso_n3":"016","un_a3":"016","wb_a2":"AS","wb_a3":"ASM","woe_id":-99,"adm0_a3_is":"ASM","adm0_a3_us":"ASM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":14,"long_len":14,"abbrev_len":9,"tiny":3,"homepart":-99},"arcs":[[53]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Antarctica","sov_a3":"ATA","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Antarctica","adm0_a3":"ATA","geou_dif":0,"geounit":"Antarctica","gu_a3":"ATA","su_dif":0,"subunit":"Antarctica","su_a3":"ATA","brk_diff":0,"name":"Antarctica","name_long":"Antarctica","brk_a3":"ATA","brk_name":"Antarctica","brk_group":null,"abbrev":"Ant.","postal":"AQ","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Multiple claims held in abeyance","name_sort":"Antarctica","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":-99,"pop_est":3802,"gdp_md_est":760.4,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AQ","iso_a3":"ATA","iso_n3":"010","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ATA","adm0_a3_us":"ATA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Antarctica","region_un":"Antarctica","subregion":"Antarctica","region_wb":"Antarctica","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[54]],[[55]],[[56]],[[57]],[[58]],[[59]],[[60]],[[61]],[[62]],[[63]],[[64]],[[65]],[[66]],[[67]],[[68]],[[69]],[[70]],[[71]],[[72]],[[73]],[[74]],[[75]],[[76]],[[77]],[[78]],[[79]],[[80]],[[81]],[[82]],[[83]],[[84]],[[85]],[[86]],[[87]],[[88]],[[89]],[[90]],[[91]],[[92]],[[93]],[[94]],[[95]],[[96]],[[97]],[[98]],[[99]],[[100]],[[101]],[[102]],[[103]],[[104]],[[105]],[[106]],[[107]],[[108]],[[109]],[[110]],[[111]],[[112]],[[113]],[[114]],[[115]],[[116]],[[117]],[[118]],[[119]],[[120]],[[121]],[[122]],[[123]],[[124]],[[125]],[[126]],[[127]],[[128]],[[129]],[[130]],[[131]],[[132]],[[133]],[[134]],[[135]],[[136]],[[137]],[[138]],[[139]],[[140]],[[141]],[[142]],[[143]],[[144]],[[145]],[[146]],[[147]],[[148]],[[149]],[[150]],[[151]],[[152]],[[153]],[[154]],[[155]],[[156]],[[157]],[[158]],[[159]],[[160]],[[161]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"French Southern and Antarctic Lands","adm0_a3":"ATF","geou_dif":0,"geounit":"French Southern and Antarctic Lands","gu_a3":"ATF","su_dif":0,"subunit":"French Southern and Antarctic Lands","su_a3":"ATF","brk_diff":0,"name":"Fr. S. Antarctic Lands","name_long":"French Southern and Antarctic Lands","brk_a3":"ATF","brk_name":"Fr. S. and Antarctic Lands","brk_group":null,"abbrev":"Fr. S.A.L.","postal":"TF","formal_en":"Territory of the French Southern and Antarctic Lands","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"French Southern and Antarctic Lands","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":140,"gdp_md_est":16,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TF","iso_a3":"ATF","iso_n3":"260","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ATF","adm0_a3_us":"ATF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":22,"long_len":35,"abbrev_len":10,"tiny":2,"homepart":-99},"arcs":[[[162]],[[163]],[[164]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Antigua and Barbuda","sov_a3":"ATG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Antigua and Barbuda","adm0_a3":"ATG","geou_dif":0,"geounit":"Antigua and Barbuda","gu_a3":"ATG","su_dif":0,"subunit":"Antigua and Barbuda","su_a3":"ATG","brk_diff":0,"name":"Antigua and Barb.","name_long":"Antigua and Barbuda","brk_a3":"ATG","brk_name":"Antigua and Barb.","brk_group":null,"abbrev":"Ant.B.","postal":"AG","formal_en":"Antigua and Barbuda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Antigua and Barbuda","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":5,"pop_est":85632,"gdp_md_est":1657,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AG","iso_a3":"ATG","iso_n3":"028","un_a3":"028","wb_a2":"AG","wb_a3":"ATG","woe_id":-99,"adm0_a3_is":"ATG","adm0_a3_us":"ATG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":17,"long_len":19,"abbrev_len":6,"tiny":4,"homepart":1},"arcs":[[[165]],[[166]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Country","admin":"Australia","adm0_a3":"AUS","geou_dif":0,"geounit":"Australia","gu_a3":"AUS","su_dif":0,"subunit":"Australia","su_a3":"AUS","brk_diff":0,"name":"Australia","name_long":"Australia","brk_a3":"AUS","brk_name":"Australia","brk_group":null,"abbrev":"Auz.","postal":"AU","formal_en":"Commonwealth of Australia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Australia","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":21262641,"gdp_md_est":800200,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AU","iso_a3":"AUS","iso_n3":"036","un_a3":"036","wb_a2":"AU","wb_a3":"AUS","woe_id":-99,"adm0_a3_is":"AUS","adm0_a3_us":"AUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[167]],[[168]],[[169]],[[170]],[[171]],[[172]],[[173]],[[174]],[[175]],[[176]],[[177]],[[178]],[[179]],[[180]],[[181]],[[182]],[[183]],[[184]],[[185]],[[186]],[[187]],[[188]],[[189]],[[190]],[[191]],[[192]],[[193]],[[194]],[[195]],[[196]],[[197]],[[198]],[[199]],[[200]],[[201]],[[202]],[[203]],[[204]],[[205]],[[206]],[[207]],[[208]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Austria","sov_a3":"AUT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Austria","adm0_a3":"AUT","geou_dif":0,"geounit":"Austria","gu_a3":"AUT","su_dif":0,"subunit":"Austria","su_a3":"AUT","brk_diff":0,"name":"Austria","name_long":"Austria","brk_a3":"AUT","brk_name":"Austria","brk_group":null,"abbrev":"Aust.","postal":"A","formal_en":"Republic of Austria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Austria","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":4,"pop_est":8210281,"gdp_md_est":329500,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AT","iso_a3":"AUT","iso_n3":"040","un_a3":"040","wb_a2":"AT","wb_a3":"AUT","woe_id":-99,"adm0_a3_is":"AUT","adm0_a3_us":"AUT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[209,210,211,212,213,214,215,216,217]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Azerbaijan","sov_a3":"AZE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Azerbaijan","adm0_a3":"AZE","geou_dif":0,"geounit":"Azerbaijan","gu_a3":"AZE","su_dif":0,"subunit":"Azerbaijan","su_a3":"AZE","brk_diff":0,"name":"Azerbaijan","name_long":"Azerbaijan","brk_a3":"AZE","brk_name":"Azerbaijan","brk_group":null,"abbrev":"Aze.","postal":"AZ","formal_en":"Republic of Azerbaijan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Azerbaijan","name_alt":null,"mapcolor7":1,"mapcolor8":6,"mapcolor9":5,"mapcolor13":8,"pop_est":8238672,"gdp_md_est":77610,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AZ","iso_a3":"AZE","iso_n3":"031","un_a3":"031","wb_a2":"AZ","wb_a3":"AZE","woe_id":-99,"adm0_a3_is":"AZE","adm0_a3_us":"AZE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[218,219,-49]],[[-53]],[[220,221,-52,222,223],[-47]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Burundi","sov_a3":"BDI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Burundi","adm0_a3":"BDI","geou_dif":0,"geounit":"Burundi","gu_a3":"BDI","su_dif":0,"subunit":"Burundi","su_a3":"BDI","brk_diff":0,"name":"Burundi","name_long":"Burundi","brk_a3":"BDI","brk_name":"Burundi","brk_group":null,"abbrev":"Bur.","postal":"BI","formal_en":"Republic of Burundi","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Burundi","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":8,"pop_est":8988091,"gdp_md_est":3102,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BI","iso_a3":"BDI","iso_n3":"108","un_a3":"108","wb_a2":"BI","wb_a3":"BDI","woe_id":-99,"adm0_a3_is":"BDI","adm0_a3_us":"BDI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[224,225,226]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Belgium","sov_a3":"BEL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belgium","adm0_a3":"BEL","geou_dif":0,"geounit":"Belgium","gu_a3":"BEL","su_dif":0,"subunit":"Belgium","su_a3":"BEL","brk_diff":0,"name":"Belgium","name_long":"Belgium","brk_a3":"BEL","brk_name":"Belgium","brk_group":null,"abbrev":"Belg.","postal":"B","formal_en":"Kingdom of Belgium","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belgium","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":8,"pop_est":10414336,"gdp_md_est":389300,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"BE","iso_a3":"BEL","iso_n3":"056","un_a3":"056","wb_a2":"BE","wb_a3":"BEL","woe_id":-99,"adm0_a3_is":"BEL","adm0_a3_us":"BEL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[227,228,229,230,231,232,233]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Benin","sov_a3":"BEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Benin","adm0_a3":"BEN","geou_dif":0,"geounit":"Benin","gu_a3":"BEN","su_dif":0,"subunit":"Benin","su_a3":"BEN","brk_diff":0,"name":"Benin","name_long":"Benin","brk_a3":"BEN","brk_name":"Benin","brk_group":null,"abbrev":"Benin","postal":"BJ","formal_en":"Republic of Benin","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Benin","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":12,"pop_est":8791832,"gdp_md_est":12830,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BJ","iso_a3":"BEN","iso_n3":"204","un_a3":"204","wb_a2":"BJ","wb_a3":"BEN","woe_id":-99,"adm0_a3_is":"BEN","adm0_a3_us":"BEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[234,235,236,237,238]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Burkina Faso","sov_a3":"BFA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Burkina Faso","adm0_a3":"BFA","geou_dif":0,"geounit":"Burkina Faso","gu_a3":"BFA","su_dif":0,"subunit":"Burkina Faso","su_a3":"BFA","brk_diff":0,"name":"Burkina Faso","name_long":"Burkina Faso","brk_a3":"BFA","brk_name":"Burkina Faso","brk_group":null,"abbrev":"B.F.","postal":"BF","formal_en":"Burkina Faso","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Burkina Faso","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":5,"mapcolor13":11,"pop_est":15746232,"gdp_md_est":17820,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BF","iso_a3":"BFA","iso_n3":"854","un_a3":"854","wb_a2":"BF","wb_a3":"BFA","woe_id":-99,"adm0_a3_is":"BFA","adm0_a3_us":"BFA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[239,-238,240,241,242,243]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Bangladesh","sov_a3":"BGD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bangladesh","adm0_a3":"BGD","geou_dif":0,"geounit":"Bangladesh","gu_a3":"BGD","su_dif":0,"subunit":"Bangladesh","su_a3":"BGD","brk_diff":0,"name":"Bangladesh","name_long":"Bangladesh","brk_a3":"BGD","brk_name":"Bangladesh","brk_group":null,"abbrev":"Bang.","postal":"BD","formal_en":"People's Republic of Bangladesh","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bangladesh","name_alt":null,"mapcolor7":3,"mapcolor8":4,"mapcolor9":7,"mapcolor13":7,"pop_est":156050883,"gdp_md_est":224000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BD","iso_a3":"BGD","iso_n3":"050","un_a3":"050","wb_a2":"BD","wb_a3":"BGD","woe_id":-99,"adm0_a3_is":"BGD","adm0_a3_us":"BGD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[244]],[[245]],[[246]],[[247]],[[248]],[[249]],[[250,251,252]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Bulgaria","sov_a3":"BGR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bulgaria","adm0_a3":"BGR","geou_dif":0,"geounit":"Bulgaria","gu_a3":"BGR","su_dif":0,"subunit":"Bulgaria","su_a3":"BGR","brk_diff":0,"name":"Bulgaria","name_long":"Bulgaria","brk_a3":"BGR","brk_name":"Bulgaria","brk_group":null,"abbrev":"Bulg.","postal":"BG","formal_en":"Republic of Bulgaria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bulgaria","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":8,"pop_est":7204687,"gdp_md_est":93750,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BG","iso_a3":"BGR","iso_n3":"100","un_a3":"100","wb_a2":"BG","wb_a3":"BGR","woe_id":-99,"adm0_a3_is":"BGR","adm0_a3_us":"BGR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[253,254,255,256,257,258]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Bahrain","sov_a3":"BHR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bahrain","adm0_a3":"BHR","geou_dif":0,"geounit":"Bahrain","gu_a3":"BHR","su_dif":0,"subunit":"Bahrain","su_a3":"BHR","brk_diff":0,"name":"Bahrain","name_long":"Bahrain","brk_a3":"BHR","brk_name":"Bahrain","brk_group":null,"abbrev":"Bahr.","postal":"BH","formal_en":"Kingdom of Bahrain","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bahrain","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":9,"pop_est":727785,"gdp_md_est":26820,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BH","iso_a3":"BHR","iso_n3":"048","un_a3":"048","wb_a2":"BH","wb_a3":"BHR","woe_id":-99,"adm0_a3_is":"BHR","adm0_a3_us":"BHR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[259]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"The Bahamas","sov_a3":"BHS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"The Bahamas","adm0_a3":"BHS","geou_dif":0,"geounit":"The Bahamas","gu_a3":"BHS","su_dif":0,"subunit":"The Bahamas","su_a3":"BHS","brk_diff":0,"name":"Bahamas","name_long":"Bahamas","brk_a3":"BHS","brk_name":"Bahamas","brk_group":null,"abbrev":"Bhs.","postal":"BS","formal_en":"Commonwealth of the Bahamas","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bahamas, The","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":5,"pop_est":309156,"gdp_md_est":9093,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BS","iso_a3":"BHS","iso_n3":"044","un_a3":"044","wb_a2":"BS","wb_a3":"BHS","woe_id":-99,"adm0_a3_is":"BHS","adm0_a3_us":"BHS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[260]],[[261]],[[262]],[[263]],[[264]],[[265]],[[266]],[[267]],[[268]],[[269]],[[270]],[[271]],[[272]],[[273]],[[274]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Bosnia and Herzegovina","sov_a3":"BIH","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bosnia and Herzegovina","adm0_a3":"BIH","geou_dif":0,"geounit":"Bosnia and Herzegovina","gu_a3":"BIH","su_dif":0,"subunit":"Bosnia and Herzegovina","su_a3":"BIH","brk_diff":0,"name":"Bosnia and Herz.","name_long":"Bosnia and Herzegovina","brk_a3":"BIH","brk_name":"Bosnia and Herz.","brk_group":null,"abbrev":"B.H.","postal":"BiH","formal_en":"Bosnia and Herzegovina","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bosnia and Herzegovina","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":2,"pop_est":4613414,"gdp_md_est":29700,"pop_year":-99,"lastcensus":1991,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BA","iso_a3":"BIH","iso_n3":"070","un_a3":"070","wb_a2":"BA","wb_a3":"BIH","woe_id":-99,"adm0_a3_is":"BIH","adm0_a3_us":"BIH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":16,"long_len":22,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[275,276,277,278,279]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Barthelemy","adm0_a3":"BLM","geou_dif":0,"geounit":"Saint Barthelemy","gu_a3":"BLM","su_dif":0,"subunit":"Saint Barthelemy","su_a3":"BLM","brk_diff":0,"name":"St-Barthélemy","name_long":"Saint-Barthélemy","brk_a3":"BLM","brk_name":"St-Barthélemy","brk_group":null,"abbrev":"St. B.","postal":"BL","formal_en":"Saint-Barthélemy","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St-Barthélemy","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":7448,"gdp_md_est":255,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"BL","iso_a3":"BLM","iso_n3":"652","un_a3":"652","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"BLM","adm0_a3_us":"BLM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":13,"long_len":16,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[280]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Belarus","sov_a3":"BLR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belarus","adm0_a3":"BLR","geou_dif":0,"geounit":"Belarus","gu_a3":"BLR","su_dif":0,"subunit":"Belarus","su_a3":"BLR","brk_diff":0,"name":"Belarus","name_long":"Belarus","brk_a3":"BLR","brk_name":"Belarus","brk_group":null,"abbrev":"Bela.","postal":"BY","formal_en":"Republic of Belarus","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belarus","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":5,"mapcolor13":11,"pop_est":9648533,"gdp_md_est":114100,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BY","iso_a3":"BLR","iso_n3":"112","un_a3":"112","wb_a2":"BY","wb_a3":"BLR","woe_id":-99,"adm0_a3_is":"BLR","adm0_a3_us":"BLR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[281,282,283,284,285]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Belize","sov_a3":"BLZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belize","adm0_a3":"BLZ","geou_dif":0,"geounit":"Belize","gu_a3":"BLZ","su_dif":0,"subunit":"Belize","su_a3":"BLZ","brk_diff":0,"name":"Belize","name_long":"Belize","brk_a3":"BLZ","brk_name":"Belize","brk_group":null,"abbrev":"Belize","postal":"BZ","formal_en":"Belize","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belize","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":5,"mapcolor13":7,"pop_est":307899,"gdp_md_est":2536,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BZ","iso_a3":"BLZ","iso_n3":"084","un_a3":"084","wb_a2":"BZ","wb_a3":"BLZ","woe_id":-99,"adm0_a3_is":"BLZ","adm0_a3_us":"BLZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[286]],[[287]],[[288,289,290]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Bermuda","adm0_a3":"BMU","geou_dif":0,"geounit":"Bermuda","gu_a3":"BMU","su_dif":0,"subunit":"Bermuda","su_a3":"BMU","brk_diff":0,"name":"Bermuda","name_long":"Bermuda","brk_a3":"BMU","brk_name":"Bermuda","brk_group":null,"abbrev":"Berm.","postal":"BM","formal_en":"The Bermudas or Somers Isles","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Bermuda","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":67837,"gdp_md_est":4500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BM","iso_a3":"BMU","iso_n3":"060","un_a3":"060","wb_a2":"BM","wb_a3":"BMU","woe_id":-99,"adm0_a3_is":"BMU","adm0_a3_us":"BMU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":7,"long_len":7,"abbrev_len":5,"tiny":4,"homepart":-99},"arcs":[[291]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Bolivia","sov_a3":"BOL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bolivia","adm0_a3":"BOL","geou_dif":0,"geounit":"Bolivia","gu_a3":"BOL","su_dif":0,"subunit":"Bolivia","su_a3":"BOL","brk_diff":0,"name":"Bolivia","name_long":"Bolivia","brk_a3":"BOL","brk_name":"Bolivia","brk_group":null,"abbrev":"Bolivia","postal":"BO","formal_en":"Plurinational State of Bolivia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bolivia","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":3,"pop_est":9775246,"gdp_md_est":43270,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BO","iso_a3":"BOL","iso_n3":"068","un_a3":"068","wb_a2":"BO","wb_a3":"BOL","woe_id":-99,"adm0_a3_is":"BOL","adm0_a3_us":"BOL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[292,-46,293,294,295]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Brazil","sov_a3":"BRA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Brazil","adm0_a3":"BRA","geou_dif":0,"geounit":"Brazil","gu_a3":"BRA","su_dif":0,"subunit":"Brazil","su_a3":"BRA","brk_diff":0,"name":"Brazil","name_long":"Brazil","brk_a3":"BRA","brk_name":"Brazil","brk_group":null,"abbrev":"Brazil","postal":"BR","formal_en":"Federative Republic of Brazil","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Brazil","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":5,"mapcolor13":7,"pop_est":198739269,"gdp_md_est":1993000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BR","iso_a3":"BRA","iso_n3":"076","un_a3":"076","wb_a2":"BR","wb_a3":"BRA","woe_id":-99,"adm0_a3_is":"BRA","adm0_a3_us":"BRA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[296]],[[297]],[[298]],[[299]],[[300]],[[301]],[[302]],[[303]],[[304]],[[305]],[[306]],[[307]],[[308]],[[309]],[[310]],[[311]],[[312,313,314,315,-42,316,-296,317,318,319,320]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Barbados","sov_a3":"BRB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Barbados","adm0_a3":"BRB","geou_dif":0,"geounit":"Barbados","gu_a3":"BRB","su_dif":0,"subunit":"Barbados","su_a3":"BRB","brk_diff":0,"name":"Barbados","name_long":"Barbados","brk_a3":"BRB","brk_name":"Barbados","brk_group":null,"abbrev":"Barb.","postal":"BB","formal_en":"Barbados","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Barbados","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":5,"mapcolor13":3,"pop_est":284589,"gdp_md_est":5425,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BB","iso_a3":"BRB","iso_n3":"052","un_a3":"052","wb_a2":"BB","wb_a3":"BRB","woe_id":-99,"adm0_a3_is":"BRB","adm0_a3_us":"BRB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[321]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Brunei","sov_a3":"BRN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Brunei","adm0_a3":"BRN","geou_dif":0,"geounit":"Brunei","gu_a3":"BRN","su_dif":0,"subunit":"Brunei","su_a3":"BRN","brk_diff":0,"name":"Brunei","name_long":"Brunei Darussalam","brk_a3":"BRN","brk_name":"Brunei","brk_group":null,"abbrev":"Brunei","postal":"BN","formal_en":"Negara Brunei Darussalam","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Brunei","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":6,"mapcolor13":12,"pop_est":388190,"gdp_md_est":20250,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BN","iso_a3":"BRN","iso_n3":"096","un_a3":"096","wb_a2":"BN","wb_a3":"BRN","woe_id":-99,"adm0_a3_is":"BRN","adm0_a3_us":"BRN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":6,"long_len":17,"abbrev_len":6,"tiny":2,"homepart":1},"arcs":[[[322,323]],[[324,325]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Bhutan","sov_a3":"BTN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bhutan","adm0_a3":"BTN","geou_dif":0,"geounit":"Bhutan","gu_a3":"BTN","su_dif":0,"subunit":"Bhutan","su_a3":"BTN","brk_diff":0,"name":"Bhutan","name_long":"Bhutan","brk_a3":"BTN","brk_name":"Bhutan","brk_group":null,"abbrev":"Bhutan","postal":"BT","formal_en":"Kingdom of Bhutan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bhutan","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":1,"mapcolor13":8,"pop_est":691141,"gdp_md_est":3524,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BT","iso_a3":"BTN","iso_n3":"064","un_a3":"064","wb_a2":"BT","wb_a3":"BTN","woe_id":-99,"adm0_a3_is":"BTN","adm0_a3_us":"BTN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[326,327]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Botswana","sov_a3":"BWA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Botswana","adm0_a3":"BWA","geou_dif":0,"geounit":"Botswana","gu_a3":"BWA","su_dif":0,"subunit":"Botswana","su_a3":"BWA","brk_diff":0,"name":"Botswana","name_long":"Botswana","brk_a3":"BWA","brk_name":"Botswana","brk_group":null,"abbrev":"Bwa.","postal":"BW","formal_en":"Republic of Botswana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Botswana","name_alt":null,"mapcolor7":6,"mapcolor8":5,"mapcolor9":7,"mapcolor13":3,"pop_est":1990876,"gdp_md_est":27060,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BW","iso_a3":"BWA","iso_n3":"072","un_a3":"072","wb_a2":"BW","wb_a3":"BWA","woe_id":-99,"adm0_a3_is":"BWA","adm0_a3_us":"BWA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[328,329,330]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Central African Republic","sov_a3":"CAF","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Central African Republic","adm0_a3":"CAF","geou_dif":0,"geounit":"Central African Republic","gu_a3":"CAF","su_dif":0,"subunit":"Central African Republic","su_a3":"CAF","brk_diff":0,"name":"Central African Rep.","name_long":"Central African Republic","brk_a3":"CAF","brk_name":"Central African Rep.","brk_group":null,"abbrev":"C.A.R.","postal":"CF","formal_en":"Central African Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Central African Republic","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":6,"mapcolor13":9,"pop_est":4511488,"gdp_md_est":3198,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"CF","iso_a3":"CAF","iso_n3":"140","un_a3":"140","wb_a2":"CF","wb_a3":"CAF","woe_id":-99,"adm0_a3_is":"CAF","adm0_a3_us":"CAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":20,"long_len":24,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[331,332,333,334,335,336]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Canada","sov_a3":"CAN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Canada","adm0_a3":"CAN","geou_dif":0,"geounit":"Canada","gu_a3":"CAN","su_dif":0,"subunit":"Canada","su_a3":"CAN","brk_diff":0,"name":"Canada","name_long":"Canada","brk_a3":"CAN","brk_name":"Canada","brk_group":null,"abbrev":"Can.","postal":"CA","formal_en":"Canada","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Canada","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":2,"mapcolor13":2,"pop_est":33487208,"gdp_md_est":1300000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CA","iso_a3":"CAN","iso_n3":"124","un_a3":"124","wb_a2":"CA","wb_a3":"CAN","woe_id":-99,"adm0_a3_is":"CAN","adm0_a3_us":"CAN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[337]],[[338]],[[339]],[[340]],[[341]],[[342]],[[343]],[[344]],[[345]],[[346]],[[347]],[[348]],[[349]],[[350]],[[351]],[[352,353]],[[354]],[[355]],[[356]],[[357]],[[358]],[[359]],[[360]],[[361]],[[362]],[[363]],[[364]],[[365]],[[366]],[[367]],[[368]],[[369]],[[370]],[[371]],[[372]],[[373]],[[374]],[[375]],[[376]],[[377]],[[378]],[[379]],[[380]],[[381,382]],[[383]],[[384]],[[385]],[[386]],[[387]],[[388]],[[389]],[[390]],[[391]],[[392]],[[393]],[[394]],[[395]],[[396]],[[397]],[[398]],[[399]],[[400]],[[401]],[[402]],[[403]],[[404]],[[405]],[[406]],[[407]],[[408]],[[409]],[[410]],[[411]],[[412]],[[413]],[[414]],[[415]],[[416]],[[417]],[[418]],[[419]],[[420]],[[421]],[[422]],[[423]],[[424]],[[425]],[[426]],[[427]],[[428]],[[429]],[[430]],[[431]],[[432]],[[433]],[[434]],[[435]],[[436]],[[437]],[[438]],[[439,440,441,442]],[[443]],[[444]],[[445]],[[446]],[[447]],[[448]],[[449]],[[450]],[[451]],[[452]],[[453]],[[454]],[[455]],[[456]],[[457]],[[458]],[[459]],[[460]],[[461]],[[462]],[[463]],[[464]],[[465]],[[466]],[[467]],[[468]],[[469]],[[470]],[[471]],[[472]],[[473]],[[474]],[[475]],[[476]],[[477]],[[478]],[[479]],[[480]],[[481]],[[482]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Switzerland","sov_a3":"CHE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Switzerland","adm0_a3":"CHE","geou_dif":0,"geounit":"Switzerland","gu_a3":"CHE","su_dif":0,"subunit":"Switzerland","su_a3":"CHE","brk_diff":0,"name":"Switzerland","name_long":"Switzerland","brk_a3":"CHE","brk_name":"Switzerland","brk_group":null,"abbrev":"Switz.","postal":"CH","formal_en":"Swiss Confederation","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Switzerland","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":7,"mapcolor13":3,"pop_est":7604467,"gdp_md_est":316700,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CH","iso_a3":"CHE","iso_n3":"756","un_a3":"756","wb_a2":"CH","wb_a3":"CHE","woe_id":-99,"adm0_a3_is":"CHE","adm0_a3_us":"CHE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-216,483,-214,484,485,486]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Chile","sov_a3":"CHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Chile","adm0_a3":"CHL","geou_dif":0,"geounit":"Chile","gu_a3":"CHL","su_dif":0,"subunit":"Chile","su_a3":"CHL","brk_diff":0,"name":"Chile","name_long":"Chile","brk_a3":"CHL","brk_name":"Chile","brk_group":null,"abbrev":"Chile","postal":"CL","formal_en":"Republic of Chile","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Chile","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":5,"mapcolor13":9,"pop_est":16601707,"gdp_md_est":244500,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CL","iso_a3":"CHL","iso_n3":"152","un_a3":"152","wb_a2":"CL","wb_a3":"CHL","woe_id":-99,"adm0_a3_is":"CHL","adm0_a3_us":"CHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[487]],[[488]],[[489]],[[490]],[[491]],[[492]],[[493]],[[494]],[[495]],[[-38,496]],[[497]],[[498]],[[499]],[[500]],[[501]],[[502]],[[503]],[[504]],[[505]],[[506]],[[507]],[[508]],[[509]],[[510]],[[511]],[[512]],[[513]],[[514]],[[515]],[[516]],[[-45,517,518,-294]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"China","adm0_a3":"CHN","geou_dif":0,"geounit":"China","gu_a3":"CHN","su_dif":0,"subunit":"China","su_a3":"CHN","brk_diff":0,"name":"China","name_long":"China","brk_a3":"CHN","brk_name":"China","brk_group":null,"abbrev":"China","postal":"CN","formal_en":"People's Republic of China","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":1338612970,"gdp_md_est":7973000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CN","iso_a3":"CHN","iso_n3":"156","un_a3":"156","wb_a2":"CN","wb_a3":"CHN","woe_id":-99,"adm0_a3_is":"CHN","adm0_a3_us":"CHN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[519]],[[520]],[[521]],[[522]],[[523]],[[524]],[[525]],[[526]],[[527]],[[528]],[[529]],[[530]],[[531,532,533,534,535,536,537,538,539,540,-328,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,-2,557,558,559,560,561,562]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ivory Coast","sov_a3":"CIV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ivory Coast","adm0_a3":"CIV","geou_dif":0,"geounit":"Ivory Coast","gu_a3":"CIV","su_dif":0,"subunit":"Ivory Coast","su_a3":"CIV","brk_diff":0,"name":"Côte d'Ivoire","name_long":"Côte d'Ivoire","brk_a3":"CIV","brk_name":"Côte d'Ivoire","brk_group":null,"abbrev":"I.C.","postal":"CI","formal_en":"Republic of Ivory Coast","formal_fr":"Republic of Cote D'Ivoire","note_adm0":null,"note_brk":null,"name_sort":"Côte d'Ivoire","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":3,"mapcolor13":3,"pop_est":20617068,"gdp_md_est":33850,"pop_year":-99,"lastcensus":1998,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CI","iso_a3":"CIV","iso_n3":"384","un_a3":"384","wb_a2":"CI","wb_a3":"CIV","woe_id":-99,"adm0_a3_is":"CIV","adm0_a3_us":"CIV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":13,"long_len":13,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[563,564]],[[-243,565,566,567,568,569]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cameroon","sov_a3":"CMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cameroon","adm0_a3":"CMR","geou_dif":0,"geounit":"Cameroon","gu_a3":"CMR","su_dif":0,"subunit":"Cameroon","su_a3":"CMR","brk_diff":0,"name":"Cameroon","name_long":"Cameroon","brk_a3":"CMR","brk_name":"Cameroon","brk_group":null,"abbrev":"Cam.","postal":"CM","formal_en":"Republic of Cameroon","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cameroon","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":3,"pop_est":18879301,"gdp_md_est":42750,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CM","iso_a3":"CMR","iso_n3":"120","un_a3":"120","wb_a2":"CM","wb_a3":"CMR","woe_id":-99,"adm0_a3_is":"CMR","adm0_a3_us":"CMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-336,570,571,572,573,574,575]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Democratic Republic of the Congo","sov_a3":"COD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Democratic Republic of the Congo","adm0_a3":"COD","geou_dif":0,"geounit":"Democratic Republic of the Congo","gu_a3":"COD","su_dif":0,"subunit":"Democratic Republic of the Congo","su_a3":"COD","brk_diff":0,"name":"Dem. Rep. Congo","name_long":"Democratic Republic of the Congo","brk_a3":"COD","brk_name":"Democratic Republic of the Congo","brk_group":null,"abbrev":"D.R.C.","postal":"DRC","formal_en":"Democratic Republic of the Congo","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Congo, Dem. Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":7,"pop_est":68692542,"gdp_md_est":20640,"pop_year":-99,"lastcensus":1984,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"CD","iso_a3":"COD","iso_n3":"180","un_a3":"180","wb_a2":"ZR","wb_a3":"ZAR","woe_id":-99,"adm0_a3_is":"COD","adm0_a3_us":"COD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":15,"long_len":32,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[576,577,578,-226,579,580,-12,581,-15,582,-334]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Republic of Congo","sov_a3":"COG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Republic of Congo","adm0_a3":"COG","geou_dif":0,"geounit":"Republic of Congo","gu_a3":"COG","su_dif":0,"subunit":"Republic of Congo","su_a3":"COG","brk_diff":0,"name":"Congo","name_long":"Republic of Congo","brk_a3":"COG","brk_name":"Republic of Congo","brk_group":null,"abbrev":"Rep. Congo","postal":"CG","formal_en":"Republic of Congo","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Congo, Rep.","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":10,"pop_est":4012809,"gdp_md_est":15350,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CG","iso_a3":"COG","iso_n3":"178","un_a3":"178","wb_a2":"CG","wb_a3":"COG","woe_id":-99,"adm0_a3_is":"COG","adm0_a3_us":"COG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":17,"abbrev_len":10,"tiny":-99,"homepart":1},"arcs":[[-583,-14,583,584,-571,-335]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Cook Islands","adm0_a3":"COK","geou_dif":0,"geounit":"Cook Islands","gu_a3":"COK","su_dif":0,"subunit":"Cook Islands","su_a3":"COK","brk_diff":0,"name":"Cook Is.","name_long":"Cook Islands","brk_a3":"COK","brk_name":"Cook Is.","brk_group":null,"abbrev":"Cook Is.","postal":"CK","formal_en":null,"formal_fr":null,"note_adm0":"Assoc. with N.Z.","note_brk":null,"name_sort":"Cook Islands","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":11870,"gdp_md_est":183.2,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CK","iso_a3":"COK","iso_n3":"184","un_a3":"184","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"COK","adm0_a3_us":"COK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":8,"long_len":12,"abbrev_len":8,"tiny":3,"homepart":-99},"arcs":[[585]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Colombia","sov_a3":"COL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Colombia","adm0_a3":"COL","geou_dif":0,"geounit":"Colombia","gu_a3":"COL","su_dif":0,"subunit":"Colombia","su_a3":"COL","brk_diff":0,"name":"Colombia","name_long":"Colombia","brk_a3":"COL","brk_name":"Colombia","brk_group":null,"abbrev":"Col.","postal":"CO","formal_en":"Republic of Colombia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Colombia","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":1,"pop_est":45644023,"gdp_md_est":395400,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CO","iso_a3":"COL","iso_n3":"170","un_a3":"170","wb_a2":"CO","wb_a3":"COL","woe_id":-99,"adm0_a3_is":"COL","adm0_a3_us":"COL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[586]],[[587,-319,588,589,590,591,592]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Comoros","sov_a3":"COM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Comoros","adm0_a3":"COM","geou_dif":0,"geounit":"Comoros","gu_a3":"COM","su_dif":0,"subunit":"Comoros","su_a3":"COM","brk_diff":0,"name":"Comoros","name_long":"Comoros","brk_a3":"COM","brk_name":"Comoros","brk_group":null,"abbrev":"Com.","postal":"KM","formal_en":"Union of the Comoros","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Comoros","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":4,"mapcolor13":10,"pop_est":752438,"gdp_md_est":751.2,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KM","iso_a3":"COM","iso_n3":"174","un_a3":"174","wb_a2":"KM","wb_a3":"COM","woe_id":-99,"adm0_a3_is":"COM","adm0_a3_us":"COM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[593]],[[594]],[[595]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Cape Verde","sov_a3":"CPV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cape Verde","adm0_a3":"CPV","geou_dif":0,"geounit":"Cape Verde","gu_a3":"CPV","su_dif":0,"subunit":"Cape Verde","su_a3":"CPV","brk_diff":0,"name":"Cape Verde","name_long":"Cape Verde","brk_a3":"CPV","brk_name":"Cape Verde","brk_group":null,"abbrev":"C.Vd.","postal":"CV","formal_en":"Republic of Cape Verde","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cape Verde","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":4,"mapcolor13":11,"pop_est":429474,"gdp_md_est":1626,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CV","iso_a3":"CPV","iso_n3":"132","un_a3":"132","wb_a2":"CV","wb_a3":"CPV","woe_id":-99,"adm0_a3_is":"CPV","adm0_a3_us":"CPV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[596]],[[597]],[[598]],[[599]],[[600]],[[601]],[[602]],[[603]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Costa Rica","sov_a3":"CRI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Costa Rica","adm0_a3":"CRI","geou_dif":0,"geounit":"Costa Rica","gu_a3":"CRI","su_dif":0,"subunit":"Costa Rica","su_a3":"CRI","brk_diff":0,"name":"Costa Rica","name_long":"Costa Rica","brk_a3":"CRI","brk_name":"Costa Rica","brk_group":null,"abbrev":"C.R.","postal":"CR","formal_en":"Republic of Costa Rica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Costa Rica","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":4,"mapcolor13":2,"pop_est":4253877,"gdp_md_est":48320,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CR","iso_a3":"CRI","iso_n3":"188","un_a3":"188","wb_a2":"CR","wb_a3":"CRI","woe_id":-99,"adm0_a3_is":"CRI","adm0_a3_us":"CRI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[604,605,606,607]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cuba","sov_a3":"CUB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cuba","adm0_a3":"CUB","geou_dif":0,"geounit":"Cuba","gu_a3":"CUB","su_dif":0,"subunit":"Cuba","su_a3":"CUB","brk_diff":0,"name":"Cuba","name_long":"Cuba","brk_a3":"CUB","brk_name":"Cuba","brk_group":null,"abbrev":"Cuba","postal":"CU","formal_en":"Republic of Cuba","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cuba","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":4,"pop_est":11451652,"gdp_md_est":108200,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CU","iso_a3":"CUB","iso_n3":"192","un_a3":"192","wb_a2":"CU","wb_a3":"CUB","woe_id":-99,"adm0_a3_is":"CUB","adm0_a3_us":"CUB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[608]],[[609]],[[610]],[[611]],[[612]],[[613]],[[614]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Curaçao","adm0_a3":"CUW","geou_dif":0,"geounit":"Curaçao","gu_a3":"CUW","su_dif":0,"subunit":"Curaçao","su_a3":"CUW","brk_diff":0,"name":"Curaçao","name_long":"Curaçao","brk_a3":"CUW","brk_name":"Curaçao","brk_group":null,"abbrev":"Cur.","postal":"CW","formal_en":"Curaçao","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"Curaçao","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":141766,"gdp_md_est":2838,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"CW","iso_a3":"CUW","iso_n3":"531","un_a3":"531","wb_a2":"CW","wb_a3":"CUW","woe_id":-99,"adm0_a3_is":"CUW","adm0_a3_us":"CUW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":4,"homepart":-99},"arcs":[[615]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Cayman Islands","adm0_a3":"CYM","geou_dif":0,"geounit":"Cayman Islands","gu_a3":"CYM","su_dif":0,"subunit":"Cayman Islands","su_a3":"CYM","brk_diff":0,"name":"Cayman Is.","name_long":"Cayman Islands","brk_a3":"CYM","brk_name":"Cayman Is.","brk_group":null,"abbrev":"Cym. Is.","postal":"KY","formal_en":"Cayman Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Cayman Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":49035,"gdp_md_est":1939,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KY","iso_a3":"CYM","iso_n3":"136","un_a3":"136","wb_a2":"KY","wb_a3":"CYM","woe_id":-99,"adm0_a3_is":"CYM","adm0_a3_us":"CYM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":10,"long_len":14,"abbrev_len":8,"tiny":2,"homepart":-99},"arcs":[[[616]],[[617]],[[618]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Northern Cyprus","sov_a3":"CYN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Northern Cyprus","adm0_a3":"CYN","geou_dif":0,"geounit":"Northern Cyprus","gu_a3":"CYN","su_dif":0,"subunit":"Northern Cyprus","su_a3":"CYN","brk_diff":1,"name":"N. Cyprus","name_long":"Northern Cyprus","brk_a3":"B20","brk_name":"N. Cyprus","brk_group":null,"abbrev":"N. Cy.","postal":"CN","formal_en":"Turkish Republic of Northern Cyprus","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Cyprus","name_sort":"Cyprus, Northern","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":265100,"gdp_md_est":3600,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"CYP","adm0_a3_us":"CYP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":9,"long_len":15,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[619,620]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Cyprus","sov_a3":"CYP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cyprus","adm0_a3":"CYP","geou_dif":0,"geounit":"Cyprus","gu_a3":"CYP","su_dif":0,"subunit":"Cyprus","su_a3":"CYP","brk_diff":0,"name":"Cyprus","name_long":"Cyprus","brk_a3":"CYP","brk_name":"Cyprus","brk_group":null,"abbrev":"Cyp.","postal":"CY","formal_en":"Republic of Cyprus","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cyprus","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":3,"mapcolor13":7,"pop_est":531640,"gdp_md_est":22700,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"CY","iso_a3":"CYP","iso_n3":"196","un_a3":"196","wb_a2":"CY","wb_a3":"CYP","woe_id":-99,"adm0_a3_is":"CYP","adm0_a3_us":"CYP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-620,621]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Czech Republic","sov_a3":"CZE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Czech Republic","adm0_a3":"CZE","geou_dif":0,"geounit":"Czech Republic","gu_a3":"CZE","su_dif":0,"subunit":"Czech Republic","su_a3":"CZE","brk_diff":0,"name":"Czech Rep.","name_long":"Czech Republic","brk_a3":"CZE","brk_name":"Czech Rep.","brk_group":null,"abbrev":"Cz. Rep.","postal":"CZ","formal_en":"Czech Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Czech Republic","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":6,"pop_est":10211904,"gdp_md_est":265200,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CZ","iso_a3":"CZE","iso_n3":"203","un_a3":"203","wb_a2":"CZ","wb_a3":"CZE","woe_id":-99,"adm0_a3_is":"CZE","adm0_a3_us":"CZE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":14,"abbrev_len":8,"tiny":-99,"homepart":1},"arcs":[[622,623,-218,624]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Germany","sov_a3":"DEU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Germany","adm0_a3":"DEU","geou_dif":0,"geounit":"Germany","gu_a3":"DEU","su_dif":0,"subunit":"Germany","su_a3":"DEU","brk_diff":0,"name":"Germany","name_long":"Germany","brk_a3":"DEU","brk_name":"Germany","brk_group":null,"abbrev":"Ger.","postal":"D","formal_en":"Federal Republic of Germany","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Germany","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":5,"mapcolor13":1,"pop_est":82329758,"gdp_md_est":2918000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"DE","iso_a3":"DEU","iso_n3":"276","un_a3":"276","wb_a2":"DE","wb_a3":"DEU","woe_id":-99,"adm0_a3_is":"DEU","adm0_a3_us":"DEU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[625,626]],[[627]],[[628]],[[629]],[[630,631,-625,-217,-487,632,633,-229,634,635,636]],[[637]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Djibouti","sov_a3":"DJI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Djibouti","adm0_a3":"DJI","geou_dif":0,"geounit":"Djibouti","gu_a3":"DJI","su_dif":0,"subunit":"Djibouti","su_a3":"DJI","brk_diff":0,"name":"Djibouti","name_long":"Djibouti","brk_a3":"DJI","brk_name":"Djibouti","brk_group":null,"abbrev":"Dji.","postal":"DJ","formal_en":"Republic of Djibouti","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Djibouti","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":4,"mapcolor13":8,"pop_est":516055,"gdp_md_est":1885,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DJ","iso_a3":"DJI","iso_n3":"262","un_a3":"262","wb_a2":"DJ","wb_a3":"DJI","woe_id":-99,"adm0_a3_is":"DJI","adm0_a3_us":"DJI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Middle East & North Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[638,639,640,641]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Dominica","sov_a3":"DMA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Dominica","adm0_a3":"DMA","geou_dif":0,"geounit":"Dominica","gu_a3":"DMA","su_dif":0,"subunit":"Dominica","su_a3":"DMA","brk_diff":0,"name":"Dominica","name_long":"Dominica","brk_a3":"DMA","brk_name":"Dominica","brk_group":null,"abbrev":"D'inca","postal":"DM","formal_en":"Commonwealth of Dominica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Dominica","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":2,"mapcolor13":12,"pop_est":72660,"gdp_md_est":719.6,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DM","iso_a3":"DMA","iso_n3":"212","un_a3":"212","wb_a2":"DM","wb_a3":"DMA","woe_id":-99,"adm0_a3_is":"DMA","adm0_a3_us":"DMA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":6,"tiny":4,"homepart":1},"arcs":[[642]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Country","admin":"Denmark","adm0_a3":"DNK","geou_dif":0,"geounit":"Denmark","gu_a3":"DNK","su_dif":0,"subunit":"Denmark","su_a3":"DNK","brk_diff":0,"name":"Denmark","name_long":"Denmark","brk_a3":"DNK","brk_name":"Denmark","brk_group":null,"abbrev":"Den.","postal":"DK","formal_en":"Kingdom of Denmark","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Denmark","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":5500510,"gdp_md_est":203600,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"DK","iso_a3":"DNK","iso_n3":"208","un_a3":"208","wb_a2":"DK","wb_a3":"DNK","woe_id":-99,"adm0_a3_is":"DNK","adm0_a3_us":"DNK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[643]],[[644]],[[645]],[[646]],[[647]],[[648]],[[649]],[[650]],[[651]],[[652]],[[653]],[[-637,654]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Dominican Republic","sov_a3":"DOM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Dominican Republic","adm0_a3":"DOM","geou_dif":0,"geounit":"Dominican Republic","gu_a3":"DOM","su_dif":0,"subunit":"Dominican Republic","su_a3":"DOM","brk_diff":0,"name":"Dominican Rep.","name_long":"Dominican Republic","brk_a3":"DOM","brk_name":"Dominican Rep.","brk_group":null,"abbrev":"Dom. Rep.","postal":"DO","formal_en":"Dominican Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Dominican Republic","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":5,"mapcolor13":7,"pop_est":9650054,"gdp_md_est":78000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DO","iso_a3":"DOM","iso_n3":"214","un_a3":"214","wb_a2":"DO","wb_a3":"DOM","woe_id":-99,"adm0_a3_is":"DOM","adm0_a3_us":"DOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":14,"long_len":18,"abbrev_len":9,"tiny":-99,"homepart":1},"arcs":[[655,656]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Algeria","sov_a3":"DZA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Algeria","adm0_a3":"DZA","geou_dif":0,"geounit":"Algeria","gu_a3":"DZA","su_dif":0,"subunit":"Algeria","su_a3":"DZA","brk_diff":0,"name":"Algeria","name_long":"Algeria","brk_a3":"DZA","brk_name":"Algeria","brk_group":null,"abbrev":"Alg.","postal":"DZ","formal_en":"People's Democratic Republic of Algeria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Algeria","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":6,"mapcolor13":3,"pop_est":34178188,"gdp_md_est":232900,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DZ","iso_a3":"DZA","iso_n3":"012","un_a3":"012","wb_a2":"DZ","wb_a3":"DZA","woe_id":-99,"adm0_a3_is":"DZA","adm0_a3_us":"DZA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[657,658,659,660,661,662,663,664]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ecuador","sov_a3":"ECU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ecuador","adm0_a3":"ECU","geou_dif":0,"geounit":"Ecuador","gu_a3":"ECU","su_dif":0,"subunit":"Ecuador","su_a3":"ECU","brk_diff":0,"name":"Ecuador","name_long":"Ecuador","brk_a3":"ECU","brk_name":"Ecuador","brk_group":null,"abbrev":"Ecu.","postal":"EC","formal_en":"Republic of Ecuador","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ecuador","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":12,"pop_est":14573101,"gdp_md_est":107700,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"EC","iso_a3":"ECU","iso_n3":"218","un_a3":"218","wb_a2":"EC","wb_a3":"ECU","woe_id":-99,"adm0_a3_is":"ECU","adm0_a3_us":"ECU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[665]],[[666]],[[667]],[[668]],[[669]],[[670]],[[671]],[[672]],[[673,674,-590]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Egypt","sov_a3":"EGY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Egypt","adm0_a3":"EGY","geou_dif":0,"geounit":"Egypt","gu_a3":"EGY","su_dif":0,"subunit":"Egypt","su_a3":"EGY","brk_diff":0,"name":"Egypt","name_long":"Egypt","brk_a3":"EGY","brk_name":"Egypt","brk_group":null,"abbrev":"Egypt","postal":"EG","formal_en":"Arab Republic of Egypt","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Egypt, Arab Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":7,"mapcolor13":2,"pop_est":83082869,"gdp_md_est":443700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"EG","iso_a3":"EGY","iso_n3":"818","un_a3":"818","wb_a2":"EG","wb_a3":"EGY","woe_id":-99,"adm0_a3_is":"EGY","adm0_a3_us":"EGY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[675,676,677,678,679,680]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Eritrea","sov_a3":"ERI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Eritrea","adm0_a3":"ERI","geou_dif":0,"geounit":"Eritrea","gu_a3":"ERI","su_dif":0,"subunit":"Eritrea","su_a3":"ERI","brk_diff":0,"name":"Eritrea","name_long":"Eritrea","brk_a3":"ERI","brk_name":"Eritrea","brk_group":null,"abbrev":"Erit.","postal":"ER","formal_en":"State of Eritrea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Eritrea","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":2,"mapcolor13":12,"pop_est":5647168,"gdp_md_est":3945,"pop_year":-99,"lastcensus":1984,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ER","iso_a3":"ERI","iso_n3":"232","un_a3":"232","wb_a2":"ER","wb_a3":"ERI","woe_id":-99,"adm0_a3_is":"ERI","adm0_a3_us":"ERI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[681]],[[682]],[[683,-641,684,685]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Spain","sov_a3":"ESP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Spain","adm0_a3":"ESP","geou_dif":0,"geounit":"Spain","gu_a3":"ESP","su_dif":0,"subunit":"Spain","su_a3":"ESP","brk_diff":0,"name":"Spain","name_long":"Spain","brk_a3":"ESP","brk_name":"Spain","brk_group":null,"abbrev":"Sp.","postal":"E","formal_en":"Kingdom of Spain","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Spain","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":5,"mapcolor13":5,"pop_est":40525002,"gdp_md_est":1403000,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"ES","iso_a3":"ESP","iso_n3":"724","un_a3":"724","wb_a2":"ES","wb_a3":"ESP","woe_id":-99,"adm0_a3_is":"ESP","adm0_a3_us":"ESP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":5,"abbrev_len":3,"tiny":-99,"homepart":1},"arcs":[[[686]],[[687]],[[688]],[[689]],[[690]],[[691]],[[692]],[[693]],[[694]],[[695]],[[696]],[[697,-25,698,699,700,701]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Estonia","sov_a3":"EST","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Estonia","adm0_a3":"EST","geou_dif":0,"geounit":"Estonia","gu_a3":"EST","su_dif":0,"subunit":"Estonia","su_a3":"EST","brk_diff":0,"name":"Estonia","name_long":"Estonia","brk_a3":"EST","brk_name":"Estonia","brk_group":null,"abbrev":"Est.","postal":"EST","formal_en":"Republic of Estonia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Estonia","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":10,"pop_est":1299371,"gdp_md_est":27410,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"EE","iso_a3":"EST","iso_n3":"233","un_a3":"233","wb_a2":"EE","wb_a3":"EST","woe_id":-99,"adm0_a3_is":"EST","adm0_a3_us":"EST","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[702]],[[703]],[[704]],[[705,706,707]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Ethiopia","sov_a3":"ETH","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ethiopia","adm0_a3":"ETH","geou_dif":0,"geounit":"Ethiopia","gu_a3":"ETH","su_dif":0,"subunit":"Ethiopia","su_a3":"ETH","brk_diff":0,"name":"Ethiopia","name_long":"Ethiopia","brk_a3":"ETH","brk_name":"Ethiopia","brk_group":null,"abbrev":"Eth.","postal":"ET","formal_en":"Federal Democratic Republic of Ethiopia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ethiopia","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":1,"mapcolor13":13,"pop_est":85237338,"gdp_md_est":68770,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ET","iso_a3":"ETH","iso_n3":"231","un_a3":"231","wb_a2":"ET","wb_a3":"ETH","woe_id":-99,"adm0_a3_is":"ETH","adm0_a3_us":"ETH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-640,708,709,710,711,712,-685]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Finland","sov_a3":"FI1","adm0_dif":1,"level":2,"type":"Country","admin":"Finland","adm0_a3":"FIN","geou_dif":0,"geounit":"Finland","gu_a3":"FIN","su_dif":0,"subunit":"Finland","su_a3":"FIN","brk_diff":0,"name":"Finland","name_long":"Finland","brk_a3":"FIN","brk_name":"Finland","brk_group":null,"abbrev":"Fin.","postal":"FIN","formal_en":"Republic of Finland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Finland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":6,"pop_est":5250275,"gdp_md_est":193500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FI","iso_a3":"FIN","iso_n3":"246","un_a3":"246","wb_a2":"FI","wb_a3":"FIN","woe_id":-99,"adm0_a3_is":"FIN","adm0_a3_us":"FIN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[713]],[[714]],[[715]],[[716]],[[717]],[[718]],[[719]],[[720,721,722,723]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Fiji","sov_a3":"FJI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Fiji","adm0_a3":"FJI","geou_dif":0,"geounit":"Fiji","gu_a3":"FJI","su_dif":0,"subunit":"Fiji","su_a3":"FJI","brk_diff":0,"name":"Fiji","name_long":"Fiji","brk_a3":"FJI","brk_name":"Fiji","brk_group":null,"abbrev":"Fiji","postal":"FJ","formal_en":"Republic of Fiji","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Fiji","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":2,"mapcolor13":2,"pop_est":944720,"gdp_md_est":3579,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"FJ","iso_a3":"FJI","iso_n3":"242","un_a3":"242","wb_a2":"FJ","wb_a3":"FJI","woe_id":-99,"adm0_a3_is":"FJI","adm0_a3_us":"FJI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[724]],[[725]],[[726]],[[727]],[[728]],[[729]],[[730]],[[731]],[[732]],[[733]],[[734]],[[735]],[[736]],[[737]],[[738]],[[739]],[[740]],[[741]],[[742]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Falkland Islands","adm0_a3":"FLK","geou_dif":0,"geounit":"Falkland Islands","gu_a3":"FLK","su_dif":0,"subunit":"Falkland Islands","su_a3":"FLK","brk_diff":1,"name":"Falkland Is.","name_long":"Falkland Islands","brk_a3":"B12","brk_name":"Falkland Is.","brk_group":null,"abbrev":"Flk. Is.","postal":"FK","formal_en":"Falkland Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":"Admin. by U.K.; Claimed by Argentina","name_sort":"Falkland Islands","name_alt":"Islas Malvinas","mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":3140,"gdp_md_est":105.1,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FK","iso_a3":"FLK","iso_n3":"238","un_a3":"238","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"FLK","adm0_a3_us":"FLK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":12,"long_len":16,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[[743]],[[744]],[[745]],[[746]],[[747]],[[748]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Country","admin":"France","adm0_a3":"FRA","geou_dif":0,"geounit":"France","gu_a3":"FRA","su_dif":0,"subunit":"France","su_a3":"FRA","brk_diff":0,"name":"France","name_long":"France","brk_a3":"FRA","brk_name":"France","brk_group":null,"abbrev":"Fr.","postal":"F","formal_en":"French Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"France","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":64057792,"gdp_md_est":2128000,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FR","iso_a3":"FRA","iso_n3":"250","un_a3":"250","wb_a2":"FR","wb_a3":"FRA","woe_id":-99,"adm0_a3_is":"FRA","adm0_a3_us":"FRA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":3,"tiny":-99,"homepart":1},"arcs":[[[749]],[[750]],[[-314,751,752]],[[753]],[[754]],[[755]],[[756]],[[757]],[[758]],[[759,-633,-486,760,761,762,763,-699,-26,-698,764,-231]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Faroe Islands","adm0_a3":"FRO","geou_dif":0,"geounit":"Faroe Islands","gu_a3":"FRO","su_dif":0,"subunit":"Faroe Islands","su_a3":"FRO","brk_diff":0,"name":"Faeroe Is.","name_long":"Faeroe Islands","brk_a3":"FRO","brk_name":"Faeroe Islands","brk_group":null,"abbrev":"Faeroe Is.","postal":"FO","formal_en":"Føroyar Is. (Faeroe Is.)","formal_fr":null,"note_adm0":"Den.","note_brk":null,"name_sort":"Faeroe Islands","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":48856,"gdp_md_est":1000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"FO","iso_a3":"FRO","iso_n3":"234","un_a3":"234","wb_a2":"FO","wb_a3":"FRO","woe_id":-99,"adm0_a3_is":"FRO","adm0_a3_us":"FRO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":14,"abbrev_len":10,"tiny":3,"homepart":-99},"arcs":[[[765]],[[766]],[[767]],[[768]],[[769]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Federated States of Micronesia","sov_a3":"FSM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Federated States of Micronesia","adm0_a3":"FSM","geou_dif":0,"geounit":"Federated States of Micronesia","gu_a3":"FSM","su_dif":0,"subunit":"Federated States of Micronesia","su_a3":"FSM","brk_diff":0,"name":"Micronesia","name_long":"Federated States of Micronesia","brk_a3":"FSM","brk_name":"Micronesia","brk_group":null,"abbrev":"F.S.M.","postal":"FSM","formal_en":"Federated States of Micronesia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Micronesia, Federated States of","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":4,"mapcolor13":13,"pop_est":107434,"gdp_md_est":238.1,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"FM","iso_a3":"FSM","iso_n3":"583","un_a3":"583","wb_a2":"FM","wb_a3":"FSM","woe_id":-99,"adm0_a3_is":"FSM","adm0_a3_us":"FSM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":10,"long_len":30,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[770]],[[771]],[[772]],[[773]],[[774]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Gabon","sov_a3":"GAB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Gabon","adm0_a3":"GAB","geou_dif":0,"geounit":"Gabon","gu_a3":"GAB","su_dif":0,"subunit":"Gabon","su_a3":"GAB","brk_diff":0,"name":"Gabon","name_long":"Gabon","brk_a3":"GAB","brk_name":"Gabon","brk_group":null,"abbrev":"Gabon","postal":"GA","formal_en":"Gabonese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Gabon","name_alt":null,"mapcolor7":6,"mapcolor8":2,"mapcolor9":5,"mapcolor13":5,"pop_est":1514993,"gdp_md_est":21110,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GA","iso_a3":"GAB","iso_n3":"266","un_a3":"266","wb_a2":"GA","wb_a3":"GAB","woe_id":-99,"adm0_a3_is":"GAB","adm0_a3_us":"GAB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[-585,775,776,-572]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"United Kingdom","adm0_a3":"GBR","geou_dif":0,"geounit":"United Kingdom","gu_a3":"GBR","su_dif":0,"subunit":"United Kingdom","su_a3":"GBR","brk_diff":0,"name":"United Kingdom","name_long":"United Kingdom","brk_a3":"GBR","brk_name":"United Kingdom","brk_group":null,"abbrev":"U.K.","postal":"GB","formal_en":"United Kingdom of Great Britain and Northern Ireland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United Kingdom","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":62262000,"gdp_md_est":1977704,"pop_year":0,"lastcensus":2011,"gdp_year":2009,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"GB","iso_a3":"GBR","iso_n3":"826","un_a3":"826","wb_a2":"GB","wb_a3":"GBR","woe_id":-99,"adm0_a3_is":"GBR","adm0_a3_us":"GBR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":14,"long_len":14,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[777]],[[778]],[[779,780]],[[781]],[[782]],[[783]],[[784]],[[785]],[[786]],[[787]],[[788]],[[789]],[[790]],[[791]],[[792]],[[793]],[[794]],[[795]],[[796]],[[797]],[[798]],[[799]],[[800]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Georgia","sov_a3":"GEO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Georgia","adm0_a3":"GEO","geou_dif":0,"geounit":"Georgia","gu_a3":"GEO","su_dif":0,"subunit":"Georgia","su_a3":"GEO","brk_diff":0,"name":"Georgia","name_long":"Georgia","brk_a3":"GEO","brk_name":"Georgia","brk_group":null,"abbrev":"Geo.","postal":"GE","formal_en":"Georgia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Georgia","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":3,"mapcolor13":2,"pop_est":4615807,"gdp_md_est":21510,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GE","iso_a3":"GEO","iso_n3":"268","un_a3":"268","wb_a2":"GE","wb_a3":"GEO","woe_id":-99,"adm0_a3_is":"GEO","adm0_a3_us":"GEO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-223,-51,801,802,803]]},{"type":"Polygon","properties":{"scalerank":4,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Guernsey","adm0_a3":"GGY","geou_dif":0,"geounit":"Guernsey","gu_a3":"GGY","su_dif":0,"subunit":"Guernsey","su_a3":"GGY","brk_diff":0,"name":"Guernsey","name_long":"Guernsey","brk_a3":"GGY","brk_name":"Guernsey","brk_group":"Channel Islands","abbrev":"Guern.","postal":"GG","formal_en":"Bailiwick of Guernsey","formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Guernsey","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":68633,"gdp_md_est":2742,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GG","iso_a3":"GGY","iso_n3":"831","un_a3":"831","wb_a2":"JG","wb_a3":"CHI","woe_id":-99,"adm0_a3_is":"GGY","adm0_a3_us":"GGY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[804]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ghana","sov_a3":"GHA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ghana","adm0_a3":"GHA","geou_dif":0,"geounit":"Ghana","gu_a3":"GHA","su_dif":0,"subunit":"Ghana","su_a3":"GHA","brk_diff":0,"name":"Ghana","name_long":"Ghana","brk_a3":"GHA","brk_name":"Ghana","brk_group":null,"abbrev":"Ghana","postal":"GH","formal_en":"Republic of Ghana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ghana","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":1,"mapcolor13":4,"pop_est":23832495,"gdp_md_est":34200,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GH","iso_a3":"GHA","iso_n3":"288","un_a3":"288","wb_a2":"GH","wb_a3":"GHA","woe_id":-99,"adm0_a3_is":"GHA","adm0_a3_us":"GHA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[805,806,-564,807,-566,-242]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Guinea","sov_a3":"GIN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guinea","adm0_a3":"GIN","geou_dif":0,"geounit":"Guinea","gu_a3":"GIN","su_dif":0,"subunit":"Guinea","su_a3":"GIN","brk_diff":0,"name":"Guinea","name_long":"Guinea","brk_a3":"GIN","brk_name":"Guinea","brk_group":null,"abbrev":"Gin.","postal":"GN","formal_en":"Republic of Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guinea","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":7,"mapcolor13":2,"pop_est":10057975,"gdp_md_est":10600,"pop_year":-99,"lastcensus":1996,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GN","iso_a3":"GIN","iso_n3":"324","un_a3":"324","wb_a2":"GN","wb_a3":"GIN","woe_id":-99,"adm0_a3_is":"GIN","adm0_a3_us":"GIN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[808,-569,809,810,811,812,813]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Gambia","sov_a3":"GMB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Gambia","adm0_a3":"GMB","geou_dif":0,"geounit":"Gambia","gu_a3":"GMB","su_dif":0,"subunit":"Gambia","su_a3":"GMB","brk_diff":0,"name":"Gambia","name_long":"The Gambia","brk_a3":"GMB","brk_name":"Gambia","brk_group":null,"abbrev":"Gambia","postal":"GM","formal_en":"Republic of the Gambia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Gambia, The","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":1782893,"gdp_md_est":2272,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GM","iso_a3":"GMB","iso_n3":"270","un_a3":"270","wb_a2":"GM","wb_a3":"GMB","woe_id":-99,"adm0_a3_is":"GMB","adm0_a3_us":"GMB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":10,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[814,815]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Guinea Bissau","sov_a3":"GNB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guinea Bissau","adm0_a3":"GNB","geou_dif":0,"geounit":"Guinea Bissau","gu_a3":"GNB","su_dif":0,"subunit":"Guinea Bissau","su_a3":"GNB","brk_diff":0,"name":"Guinea-Bissau","name_long":"Guinea-Bissau","brk_a3":"GNB","brk_name":"Guinea-Bissau","brk_group":null,"abbrev":"GnB.","postal":"GW","formal_en":"Republic of Guinea-Bissau","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guinea-Bissau","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":4,"pop_est":1533964,"gdp_md_est":904.2,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GW","iso_a3":"GNB","iso_n3":"624","un_a3":"624","wb_a2":"GW","wb_a3":"GNB","woe_id":-99,"adm0_a3_is":"GNB","adm0_a3_us":"GNB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":13,"long_len":13,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[816]],[[817]],[[818]],[[819]],[[820]],[[821]],[[822,823,-813]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Equatorial Guinea","sov_a3":"GNQ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Equatorial Guinea","adm0_a3":"GNQ","geou_dif":0,"geounit":"Equatorial Guinea","gu_a3":"GNQ","su_dif":0,"subunit":"Equatorial Guinea","su_a3":"GNQ","brk_diff":0,"name":"Eq. Guinea","name_long":"Equatorial Guinea","brk_a3":"GNQ","brk_name":"Eq. Guinea","brk_group":null,"abbrev":"Eq. G.","postal":"GQ","formal_en":"Republic of Equatorial Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Equatorial Guinea","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":650702,"gdp_md_est":14060,"pop_year":0,"lastcensus":2002,"gdp_year":0,"economy":"7. Least developed region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GQ","iso_a3":"GNQ","iso_n3":"226","un_a3":"226","wb_a2":"GQ","wb_a3":"GNQ","woe_id":-99,"adm0_a3_is":"GNQ","adm0_a3_us":"GNQ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":17,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[824,-573,-777]],[[825]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Greece","sov_a3":"GRC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Greece","adm0_a3":"GRC","geou_dif":0,"geounit":"Greece","gu_a3":"GRC","su_dif":0,"subunit":"Greece","su_a3":"GRC","brk_diff":0,"name":"Greece","name_long":"Greece","brk_a3":"GRC","brk_name":"Greece","brk_group":null,"abbrev":"Greece","postal":"GR","formal_en":"Hellenic Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Greece","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":10737428,"gdp_md_est":343000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"GR","iso_a3":"GRC","iso_n3":"300","un_a3":"300","wb_a2":"GR","wb_a3":"GRC","woe_id":-99,"adm0_a3_is":"GRC","adm0_a3_us":"GRC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[826]],[[827]],[[828]],[[829]],[[830]],[[831]],[[832]],[[833]],[[834]],[[835]],[[836]],[[837]],[[838]],[[839]],[[840]],[[841]],[[842]],[[843]],[[844]],[[845]],[[846]],[[847]],[[848]],[[849]],[[850]],[[851]],[[852]],[[853]],[[854]],[[855]],[[856]],[[857]],[[858]],[[859]],[[860]],[[861]],[[862]],[[863]],[[864]],[[865,-19,866,-256,867]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Grenada","sov_a3":"GRD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Grenada","adm0_a3":"GRD","geou_dif":0,"geounit":"Grenada","gu_a3":"GRD","su_dif":0,"subunit":"Grenada","su_a3":"GRD","brk_diff":0,"name":"Grenada","name_long":"Grenada","brk_a3":"GRD","brk_name":"Grenada","brk_group":null,"abbrev":"Gren.","postal":"GD","formal_en":"Grenada","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Grenada","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":3,"mapcolor13":6,"pop_est":90739,"gdp_md_est":1161,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GD","iso_a3":"GRD","iso_n3":"308","un_a3":"308","wb_a2":"GD","wb_a3":"GRD","woe_id":-99,"adm0_a3_is":"GRD","adm0_a3_us":"GRD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[868]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Country","admin":"Greenland","adm0_a3":"GRL","geou_dif":0,"geounit":"Greenland","gu_a3":"GRL","su_dif":0,"subunit":"Greenland","su_a3":"GRL","brk_diff":0,"name":"Greenland","name_long":"Greenland","brk_a3":"GRL","brk_name":"Greenland","brk_group":null,"abbrev":"Grlnd.","postal":"GL","formal_en":"Greenland","formal_fr":null,"note_adm0":"Den.","note_brk":null,"name_sort":"Greenland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":57600,"gdp_md_est":1100,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GL","iso_a3":"GRL","iso_n3":"304","un_a3":"304","wb_a2":"GL","wb_a3":"GRL","woe_id":-99,"adm0_a3_is":"GRL","adm0_a3_us":"GRL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[[869]],[[870]],[[871]],[[872]],[[873]],[[874]],[[875]],[[876]],[[877]],[[878]],[[879]],[[880]],[[881]],[[882]],[[883]],[[884]],[[885]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Guatemala","sov_a3":"GTM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guatemala","adm0_a3":"GTM","geou_dif":0,"geounit":"Guatemala","gu_a3":"GTM","su_dif":0,"subunit":"Guatemala","su_a3":"GTM","brk_diff":0,"name":"Guatemala","name_long":"Guatemala","brk_a3":"GTM","brk_name":"Guatemala","brk_group":null,"abbrev":"Guat.","postal":"GT","formal_en":"Republic of Guatemala","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guatemala","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":3,"mapcolor13":6,"pop_est":13276517,"gdp_md_est":68580,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GT","iso_a3":"GTM","iso_n3":"320","un_a3":"320","wb_a2":"GT","wb_a3":"GTM","woe_id":-99,"adm0_a3_is":"GTM","adm0_a3_us":"GTM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":5,"tiny":4,"homepart":1},"arcs":[[-289,886,887,888,889,890]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Guam","adm0_a3":"GUM","geou_dif":0,"geounit":"Guam","gu_a3":"GUM","su_dif":0,"subunit":"Guam","su_a3":"GUM","brk_diff":0,"name":"Guam","name_long":"Guam","brk_a3":"GUM","brk_name":"Guam","brk_group":null,"abbrev":"Guam","postal":"GU","formal_en":"Territory of Guam","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"Guam","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":178430,"gdp_md_est":2500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GU","iso_a3":"GUM","iso_n3":"316","un_a3":"316","wb_a2":"GU","wb_a3":"GUM","woe_id":-99,"adm0_a3_is":"GUM","adm0_a3_us":"GUM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":2,"homepart":-99},"arcs":[[891]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Guyana","sov_a3":"GUY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guyana","adm0_a3":"GUY","geou_dif":0,"geounit":"Guyana","gu_a3":"GUY","su_dif":0,"subunit":"Guyana","su_a3":"GUY","brk_diff":0,"name":"Guyana","name_long":"Guyana","brk_a3":"GUY","brk_name":"Guyana","brk_group":null,"abbrev":"Guy.","postal":"GY","formal_en":"Co-operative Republic of Guyana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guyana","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":772298,"gdp_md_est":2966,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GY","iso_a3":"GUY","iso_n3":"328","un_a3":"328","wb_a2":"GY","wb_a3":"GUY","woe_id":-99,"adm0_a3_is":"GUY","adm0_a3_us":"GUY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[892,-321,893,894]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"Hong Kong S.A.R.","adm0_a3":"HKG","geou_dif":0,"geounit":"Hong Kong S.A.R.","gu_a3":"HKG","su_dif":0,"subunit":"Hong Kong S.A.R.","su_a3":"HKG","brk_diff":0,"name":"Hong Kong","name_long":"Hong Kong","brk_a3":"HKG","brk_name":"Hong Kong","brk_group":null,"abbrev":"H.K.","postal":"HK","formal_en":"Hong Kong Special Administrative Region, PRC","formal_fr":null,"note_adm0":"China","note_brk":null,"name_sort":"Hong Kong SAR, China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":7061200,"gdp_md_est":351119,"pop_year":2010,"lastcensus":2006,"gdp_year":2011,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":0,"fips_10":null,"iso_a2":"HK","iso_a3":"HKG","iso_n3":"344","un_a3":"344","wb_a2":"HK","wb_a3":"HKG","woe_id":-99,"adm0_a3_is":"HKG","adm0_a3_us":"HKG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[895]],[[896]],[[-534,897]]]},{"type":"Polygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Heard Island and McDonald Islands","adm0_a3":"HMD","geou_dif":0,"geounit":"Heard Island and McDonald Islands","gu_a3":"HMD","su_dif":0,"subunit":"Heard Island and McDonald Islands","su_a3":"HMD","brk_diff":0,"name":"Heard I. and McDonald Is.","name_long":"Heard I. and McDonald Islands","brk_a3":"HMD","brk_name":"Heard I. and McDonald Is.","brk_group":null,"abbrev":"H.M.Is.","postal":"HM","formal_en":"Territory of Heard Island and McDonald Islands","formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Heard Island and McDonald Islands","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":-99,"gdp_md_est":-99,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"HM","iso_a3":"HMD","iso_n3":"334","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"HMD","adm0_a3_us":"HMD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":25,"long_len":29,"abbrev_len":7,"tiny":-99,"homepart":-99},"arcs":[[898]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Honduras","sov_a3":"HND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Honduras","adm0_a3":"HND","geou_dif":0,"geounit":"Honduras","gu_a3":"HND","su_dif":0,"subunit":"Honduras","su_a3":"HND","brk_diff":0,"name":"Honduras","name_long":"Honduras","brk_a3":"HND","brk_name":"Honduras","brk_group":null,"abbrev":"Hond.","postal":"HN","formal_en":"Republic of Honduras","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Honduras","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":2,"mapcolor13":5,"pop_est":7792854,"gdp_md_est":33720,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"HN","iso_a3":"HND","iso_n3":"340","un_a3":"340","wb_a2":"HN","wb_a3":"HND","woe_id":-99,"adm0_a3_is":"HND","adm0_a3_us":"HND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[899,900,901,-888,902]],[[903]],[[904]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Croatia","sov_a3":"HRV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Croatia","adm0_a3":"HRV","geou_dif":0,"geounit":"Croatia","gu_a3":"HRV","su_dif":0,"subunit":"Croatia","su_a3":"HRV","brk_diff":0,"name":"Croatia","name_long":"Croatia","brk_a3":"HRV","brk_name":"Croatia","brk_group":null,"abbrev":"Cro.","postal":"HR","formal_en":"Republic of Croatia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Croatia","name_alt":null,"mapcolor7":5,"mapcolor8":4,"mapcolor9":5,"mapcolor13":1,"pop_est":4489409,"gdp_md_est":82390,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"HR","iso_a3":"HRV","iso_n3":"191","un_a3":"191","wb_a2":"HR","wb_a3":"HRV","woe_id":-99,"adm0_a3_is":"HRV","adm0_a3_us":"HRV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[905]],[[906]],[[-278,907,908]],[[909]],[[910]],[[911]],[[912]],[[913]],[[914]],[[915]],[[916]],[[917]],[[918,-280,919,920,921]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Haiti","sov_a3":"HTI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Haiti","adm0_a3":"HTI","geou_dif":0,"geounit":"Haiti","gu_a3":"HTI","su_dif":0,"subunit":"Haiti","su_a3":"HTI","brk_diff":0,"name":"Haiti","name_long":"Haiti","brk_a3":"HTI","brk_name":"Haiti","brk_group":null,"abbrev":"Haiti","postal":"HT","formal_en":"Republic of Haiti","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Haiti","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":7,"mapcolor13":2,"pop_est":9035536,"gdp_md_est":11500,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"HT","iso_a3":"HTI","iso_n3":"332","un_a3":"332","wb_a2":"HT","wb_a3":"HTI","woe_id":-99,"adm0_a3_is":"HTI","adm0_a3_us":"HTI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[922]],[[-656,923]],[[924]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Hungary","sov_a3":"HUN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Hungary","adm0_a3":"HUN","geou_dif":0,"geounit":"Hungary","gu_a3":"HUN","su_dif":0,"subunit":"Hungary","su_a3":"HUN","brk_diff":0,"name":"Hungary","name_long":"Hungary","brk_a3":"HUN","brk_name":"Hungary","brk_group":null,"abbrev":"Hun.","postal":"HU","formal_en":"Republic of Hungary","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Hungary","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":1,"mapcolor13":5,"pop_est":9905596,"gdp_md_est":196600,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"HU","iso_a3":"HUN","iso_n3":"348","un_a3":"348","wb_a2":"HU","wb_a3":"HUN","woe_id":-99,"adm0_a3_is":"HUN","adm0_a3_us":"HUN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[925,926,927,-922,928,-211,929]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Indonesia","sov_a3":"IDN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Indonesia","adm0_a3":"IDN","geou_dif":0,"geounit":"Indonesia","gu_a3":"IDN","su_dif":0,"subunit":"Indonesia","su_a3":"IDN","brk_diff":0,"name":"Indonesia","name_long":"Indonesia","brk_a3":"IDN","brk_name":"Indonesia","brk_group":null,"abbrev":"Indo.","postal":"INDO","formal_en":"Republic of Indonesia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Indonesia","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":11,"pop_est":240271522,"gdp_md_est":914600,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ID","iso_a3":"IDN","iso_n3":"360","un_a3":"360","wb_a2":"ID","wb_a3":"IDN","woe_id":-99,"adm0_a3_is":"IDN","adm0_a3_us":"IDN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[930]],[[931]],[[932]],[[933]],[[934,935,936,937]],[[938]],[[939]],[[940]],[[941]],[[942]],[[943]],[[944]],[[945]],[[946]],[[947]],[[948]],[[949]],[[950]],[[951]],[[952]],[[953]],[[954]],[[955]],[[956]],[[957]],[[958]],[[959]],[[960]],[[961]],[[962]],[[963]],[[964]],[[965]],[[966]],[[967]],[[968]],[[969]],[[970]],[[971]],[[972]],[[973]],[[974]],[[975]],[[976]],[[977]],[[978]],[[979]],[[980]],[[981]],[[982]],[[983]],[[984]],[[985]],[[986]],[[987]],[[988]],[[989]],[[990]],[[991]],[[992]],[[993]],[[994]],[[995]],[[996]],[[997]],[[998]],[[999]],[[1000]],[[1001]],[[1002]],[[1003]],[[1004]],[[1005]],[[1006]],[[1007]],[[1008]],[[1009]],[[1010]],[[1011]],[[1012]],[[1013]],[[1014]],[[1015]],[[1016]],[[1017]],[[1018]],[[1019]],[[1020]],[[1021,1022,1023]],[[1024]],[[1025]],[[1026]],[[1027]],[[1028]],[[1029]],[[1030]],[[1031]],[[1032]],[[1033]],[[1034]],[[1035]],[[1036]],[[1037]],[[1038]],[[1039]],[[1040]],[[1041]],[[1042]],[[1043]],[[1044]],[[1045]],[[1046]],[[1047]],[[1048]],[[1049]],[[1050]],[[1051]],[[1052]],[[1053]],[[1054]],[[1055]],[[1056]],[[1057]],[[1058]],[[1059]],[[1060]],[[1061]],[[1062,1063]],[[1064]],[[1065,1066]],[[1067]],[[1068]],[[1069]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Isle of Man","adm0_a3":"IMN","geou_dif":0,"geounit":"Isle of Man","gu_a3":"IMN","su_dif":0,"subunit":"Isle of Man","su_a3":"IMN","brk_diff":0,"name":"Isle of Man","name_long":"Isle of Man","brk_a3":"IMN","brk_name":"Isle of Man","brk_group":null,"abbrev":"IoMan","postal":"IM","formal_en":null,"formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Isle of Man","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":76512,"gdp_md_est":2719,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"IM","iso_a3":"IMN","iso_n3":"833","un_a3":"833","wb_a2":"IM","wb_a3":"IMY","woe_id":-99,"adm0_a3_is":"IMN","adm0_a3_us":"IMN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":-99},"arcs":[[1070]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"India","sov_a3":"IND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"India","adm0_a3":"IND","geou_dif":0,"geounit":"India","gu_a3":"IND","su_dif":0,"subunit":"India","su_a3":"IND","brk_diff":0,"name":"India","name_long":"India","brk_a3":"IND","brk_name":"India","brk_group":null,"abbrev":"India","postal":"IND","formal_en":"Republic of India","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"India","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":2,"mapcolor13":2,"pop_est":1166079220,"gdp_md_est":3297000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IN","iso_a3":"IND","iso_n3":"356","un_a3":"356","wb_a2":"IN","wb_a3":"IND","woe_id":-99,"adm0_a3_is":"IND","adm0_a3_us":"IND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1071]],[[1072]],[[1073]],[[1074]],[[1075]],[[1076]],[[1077]],[[1078]],[[1079]],[[1080]],[[1081]],[[1082]],[[1083,-549,1084,-547,1085,1086,-544,1087,-542,-327,-541,1088,-253,1089,1090,1091,1092,-554,1093,-552,1094,-550]]]},{"type":"MultiPolygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Indian Ocean Territories","adm0_a3":"IOA","geou_dif":0,"geounit":"Indian Ocean Territories","gu_a3":"IOA","su_dif":0,"subunit":"Indian Ocean Territories","su_a3":"IOA","brk_diff":0,"name":"Indian Ocean Ter.","name_long":"Indian Ocean Territories","brk_a3":"IOA","brk_name":"Indian Ocean Ter.","brk_group":null,"abbrev":"Ind. Oc. Ter.","postal":"IOT","formal_en":null,"formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Indian Ocean Territories","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":2069,"gdp_md_est":31.035,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"AUS","adm0_a3_us":"AUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"East Asia & Pacific","name_len":17,"long_len":24,"abbrev_len":13,"tiny":-99,"homepart":-99},"arcs":[[[1095]],[[1096]],[[1097]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"British Indian Ocean Territory","adm0_a3":"IOT","geou_dif":0,"geounit":"British Indian Ocean Territory","gu_a3":"IOT","su_dif":0,"subunit":"British Indian Ocean Territory","su_a3":"IOT","brk_diff":1,"name":"Br. Indian Ocean Ter.","name_long":"British Indian Ocean Territory","brk_a3":"B69","brk_name":"Br. Indian Ocean Ter.","brk_group":null,"abbrev":"I.O.T.","postal":"IO","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":"Admin. by U.K.; Claimed by Mauritius and Seychelles","name_sort":"British Indian Ocean Territory","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":4000,"gdp_md_est":160,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"IO","iso_a3":"IOT","iso_n3":"086","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"IOT","adm0_a3_us":"IOT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":21,"long_len":30,"abbrev_len":6,"tiny":5,"homepart":-99},"arcs":[[1098]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ireland","sov_a3":"IRL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ireland","adm0_a3":"IRL","geou_dif":0,"geounit":"Ireland","gu_a3":"IRL","su_dif":0,"subunit":"Ireland","su_a3":"IRL","brk_diff":0,"name":"Ireland","name_long":"Ireland","brk_a3":"IRL","brk_name":"Ireland","brk_group":null,"abbrev":"Ire.","postal":"IRL","formal_en":"Ireland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ireland","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":2,"mapcolor13":2,"pop_est":4203200,"gdp_md_est":188400,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IE","iso_a3":"IRL","iso_n3":"372","un_a3":"372","wb_a2":"IE","wb_a3":"IRL","woe_id":-99,"adm0_a3_is":"IRL","adm0_a3_us":"IRL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1099]],[[1100,-780]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Iran","sov_a3":"IRN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iran","adm0_a3":"IRN","geou_dif":0,"geounit":"Iran","gu_a3":"IRN","su_dif":0,"subunit":"Iran","su_a3":"IRN","brk_diff":0,"name":"Iran","name_long":"Iran","brk_a3":"IRN","brk_name":"Iran","brk_group":null,"abbrev":"Iran","postal":"IRN","formal_en":"Islamic Republic of Iran","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iran, Islamic Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":3,"mapcolor9":4,"mapcolor13":13,"pop_est":66429284,"gdp_md_est":841700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IR","iso_a3":"IRN","iso_n3":"364","un_a3":"364","wb_a2":"IR","wb_a3":"IRN","woe_id":-99,"adm0_a3_is":"IRN","adm0_a3_us":"IRN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1101]],[[-48,-222,1102,1103,-5,1104,1105,1106,1107,1108,-219]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Iraq","sov_a3":"IRQ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iraq","adm0_a3":"IRQ","geou_dif":0,"geounit":"Iraq","gu_a3":"IRQ","su_dif":0,"subunit":"Iraq","su_a3":"IRQ","brk_diff":0,"name":"Iraq","name_long":"Iraq","brk_a3":"IRQ","brk_name":"Iraq","brk_group":null,"abbrev":"Iraq","postal":"IRQ","formal_en":"Republic of Iraq","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iraq","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":3,"mapcolor13":1,"pop_est":31129225,"gdp_md_est":103900,"pop_year":-99,"lastcensus":1997,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IQ","iso_a3":"IRQ","iso_n3":"368","un_a3":"368","wb_a2":"IQ","wb_a3":"IRQ","woe_id":-99,"adm0_a3_is":"IRQ","adm0_a3_us":"IRQ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1108,1109,1110,1111,1112,1113,1114]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Iceland","sov_a3":"ISL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iceland","adm0_a3":"ISL","geou_dif":0,"geounit":"Iceland","gu_a3":"ISL","su_dif":0,"subunit":"Iceland","su_a3":"ISL","brk_diff":0,"name":"Iceland","name_long":"Iceland","brk_a3":"ISL","brk_name":"Iceland","brk_group":null,"abbrev":"Iceland","postal":"IS","formal_en":"Republic of Iceland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iceland","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":4,"mapcolor13":9,"pop_est":306694,"gdp_md_est":12710,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IS","iso_a3":"ISL","iso_n3":"352","un_a3":"352","wb_a2":"IS","wb_a3":"ISL","woe_id":-99,"adm0_a3_is":"ISL","adm0_a3_us":"ISL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[1115]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Israel","sov_a3":"ISR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Israel","adm0_a3":"ISR","geou_dif":0,"geounit":"Israel","gu_a3":"ISR","su_dif":0,"subunit":"Israel","su_a3":"ISR","brk_diff":0,"name":"Israel","name_long":"Israel","brk_a3":"ISR","brk_name":"Israel","brk_group":null,"abbrev":"Isr.","postal":"IS","formal_en":"State of Israel","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Israel","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":9,"pop_est":7233701,"gdp_md_est":201400,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IL","iso_a3":"ISR","iso_n3":"376","un_a3":"376","wb_a2":"IL","wb_a3":"ISR","woe_id":-99,"adm0_a3_is":"ISR","adm0_a3_us":"ISR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1116,1117,1118,1119,-677,1120,1121,1122,1123]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Italy","sov_a3":"ITA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Italy","adm0_a3":"ITA","geou_dif":0,"geounit":"Italy","gu_a3":"ITA","su_dif":0,"subunit":"Italy","su_a3":"ITA","brk_diff":0,"name":"Italy","name_long":"Italy","brk_a3":"ITA","brk_name":"Italy","brk_group":null,"abbrev":"Italy","postal":"I","formal_en":"Italian Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Italy","name_alt":null,"mapcolor7":6,"mapcolor8":7,"mapcolor9":8,"mapcolor13":7,"pop_est":58126212,"gdp_md_est":1823000,"pop_year":-99,"lastcensus":2012,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IT","iso_a3":"ITA","iso_n3":"380","un_a3":"380","wb_a2":"IT","wb_a3":"ITA","woe_id":-99,"adm0_a3_is":"ITA","adm0_a3_us":"ITA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1124]],[[1125]],[[1126]],[[1127]],[[1128]],[[1129]],[[1130]],[[1131,1132,-761,-485,-213],[1133]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Jamaica","sov_a3":"JAM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Jamaica","adm0_a3":"JAM","geou_dif":0,"geounit":"Jamaica","gu_a3":"JAM","su_dif":0,"subunit":"Jamaica","su_a3":"JAM","brk_diff":0,"name":"Jamaica","name_long":"Jamaica","brk_a3":"JAM","brk_name":"Jamaica","brk_group":null,"abbrev":"Jam.","postal":"J","formal_en":"Jamaica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Jamaica","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":4,"mapcolor13":10,"pop_est":2825928,"gdp_md_est":20910,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"JM","iso_a3":"JAM","iso_n3":"388","un_a3":"388","wb_a2":"JM","wb_a3":"JAM","woe_id":-99,"adm0_a3_is":"JAM","adm0_a3_us":"JAM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1134]]},{"type":"Polygon","properties":{"scalerank":4,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Jersey","adm0_a3":"JEY","geou_dif":0,"geounit":"Jersey","gu_a3":"JEY","su_dif":0,"subunit":"Jersey","su_a3":"JEY","brk_diff":0,"name":"Jersey","name_long":"Jersey","brk_a3":"JEY","brk_name":"Jersey","brk_group":"Channel Islands","abbrev":"Jey.","postal":"JE","formal_en":"Bailiwick of Jersey","formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Jersey","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":91626,"gdp_md_est":5100,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"JE","iso_a3":"JEY","iso_n3":"832","un_a3":"832","wb_a2":"JG","wb_a3":"CHI","woe_id":-99,"adm0_a3_is":"JEY","adm0_a3_us":"JEY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[1135]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Jordan","sov_a3":"JOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Jordan","adm0_a3":"JOR","geou_dif":0,"geounit":"Jordan","gu_a3":"JOR","su_dif":0,"subunit":"Jordan","su_a3":"JOR","brk_diff":0,"name":"Jordan","name_long":"Jordan","brk_a3":"JOR","brk_name":"Jordan","brk_group":null,"abbrev":"Jord.","postal":"J","formal_en":"Hashemite Kingdom of Jordan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Jordan","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":6342948,"gdp_md_est":31610,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"JO","iso_a3":"JOR","iso_n3":"400","un_a3":"400","wb_a2":"JO","wb_a3":"JOR","woe_id":-99,"adm0_a3_is":"JOR","adm0_a3_us":"JOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1136,1137,-1119,1138,-1117,1139,-1113]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Japan","sov_a3":"JPN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Japan","adm0_a3":"JPN","geou_dif":0,"geounit":"Japan","gu_a3":"JPN","su_dif":0,"subunit":"Japan","su_a3":"JPN","brk_diff":0,"name":"Japan","name_long":"Japan","brk_a3":"JPN","brk_name":"Japan","brk_group":null,"abbrev":"Japan","postal":"J","formal_en":"Japan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Japan","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":5,"mapcolor13":4,"pop_est":127078679,"gdp_md_est":4329000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"JP","iso_a3":"JPN","iso_n3":"392","un_a3":"392","wb_a2":"JP","wb_a3":"JPN","woe_id":-99,"adm0_a3_is":"JPN","adm0_a3_us":"JPN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1140]],[[1141]],[[1142]],[[1143]],[[1144]],[[1145]],[[1146]],[[1147]],[[1148]],[[1149]],[[1150]],[[1151]],[[1152]],[[1153]],[[1154]],[[1155]],[[1156]],[[1157]],[[1158]],[[1159]],[[1160]],[[1161]],[[1162]],[[1163]],[[1164]],[[1165]],[[1166]],[[1167]],[[1168]],[[1169]],[[1170]],[[1171]],[[1172]],[[1173]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Kashmir","sov_a3":"KAS","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Siachen Glacier","adm0_a3":"KAS","geou_dif":0,"geounit":"Siachen Glacier","gu_a3":"KAS","su_dif":0,"subunit":"Siachen Glacier","su_a3":"KAS","brk_diff":1,"name":"Siachen Glacier","name_long":"Siachen Glacier","brk_a3":"B45","brk_name":"Siachen Glacier","brk_group":"Jammu and Kashmir","abbrev":"Siachen","postal":"SG","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Claimed by Pakistan and India","name_sort":"Kashmir","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":6,"mapcolor13":-99,"pop_est":6000,"gdp_md_est":15,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"-99","adm0_a3_us":"KAS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":15,"long_len":15,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-1092,1174,-556]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Kazakhstan","sov_a3":"KAZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kazakhstan","adm0_a3":"KAZ","geou_dif":0,"geounit":"Kazakhstan","gu_a3":"KAZ","su_dif":0,"subunit":"Kazakhstan","su_a3":"KAZ","brk_diff":0,"name":"Kazakhstan","name_long":"Kazakhstan","brk_a3":"KAZ","brk_name":"Kazakhstan","brk_group":null,"abbrev":"Kaz.","postal":"KZ","formal_en":"Republic of Kazakhstan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kazakhstan","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":6,"mapcolor13":1,"pop_est":15399437,"gdp_md_est":175800,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"KZ","iso_a3":"KAZ","iso_n3":"398","un_a3":"398","wb_a2":"KZ","wb_a3":"KAZ","woe_id":-99,"adm0_a3_is":"KAZ","adm0_a3_us":"KAZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1175]],[[1176]],[[1177]],[[-560,1178,1179,1180,1181,1182]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Kenya","sov_a3":"KEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kenya","adm0_a3":"KEN","geou_dif":0,"geounit":"Kenya","gu_a3":"KEN","su_dif":0,"subunit":"Kenya","su_a3":"KEN","brk_diff":0,"name":"Kenya","name_long":"Kenya","brk_a3":"KEN","brk_name":"Kenya","brk_group":null,"abbrev":"Ken.","postal":"KE","formal_en":"Republic of Kenya","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kenya","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":7,"mapcolor13":3,"pop_est":39002772,"gdp_md_est":61510,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KE","iso_a3":"KEN","iso_n3":"404","un_a3":"404","wb_a2":"KE","wb_a3":"KEN","woe_id":-99,"adm0_a3_is":"KEN","adm0_a3_us":"KEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1183]],[[1184,1185,1186,1187,1188,-711]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Kyrgyzstan","sov_a3":"KGZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kyrgyzstan","adm0_a3":"KGZ","geou_dif":0,"geounit":"Kyrgyzstan","gu_a3":"KGZ","su_dif":0,"subunit":"Kyrgyzstan","su_a3":"KGZ","brk_diff":0,"name":"Kyrgyzstan","name_long":"Kyrgyzstan","brk_a3":"KGZ","brk_name":"Kyrgyzstan","brk_group":null,"abbrev":"Kgz.","postal":"KG","formal_en":"Kyrgyz Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kyrgyz Republic","name_alt":null,"mapcolor7":5,"mapcolor8":7,"mapcolor9":7,"mapcolor13":6,"pop_est":5431747,"gdp_md_est":11610,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KG","iso_a3":"KGZ","iso_n3":"417","un_a3":"417","wb_a2":"KG","wb_a3":"KGZ","woe_id":-99,"adm0_a3_is":"KGZ","adm0_a3_us":"KGZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-559,1189,1190,-1179],[1191],[1192],[1193]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cambodia","sov_a3":"KHM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cambodia","adm0_a3":"KHM","geou_dif":0,"geounit":"Cambodia","gu_a3":"KHM","su_dif":0,"subunit":"Cambodia","su_a3":"KHM","brk_diff":0,"name":"Cambodia","name_long":"Cambodia","brk_a3":"KHM","brk_name":"Cambodia","brk_group":null,"abbrev":"Camb.","postal":"KH","formal_en":"Kingdom of Cambodia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cambodia","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":5,"pop_est":14494293,"gdp_md_est":27940,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KH","iso_a3":"KHM","iso_n3":"116","un_a3":"116","wb_a2":"KH","wb_a3":"KHM","woe_id":-99,"adm0_a3_is":"KHM","adm0_a3_us":"KHM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1194]],[[1195]],[[1196,1197,1198,1199]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kiribati","sov_a3":"KIR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kiribati","adm0_a3":"KIR","geou_dif":0,"geounit":"Kiribati","gu_a3":"KIR","su_dif":0,"subunit":"Kiribati","su_a3":"KIR","brk_diff":0,"name":"Kiribati","name_long":"Kiribati","brk_a3":"KIR","brk_name":"Kiribati","brk_group":null,"abbrev":"Kir.","postal":"KI","formal_en":"Republic of Kiribati","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kiribati","name_alt":null,"mapcolor7":5,"mapcolor8":7,"mapcolor9":6,"mapcolor13":12,"pop_est":112850,"gdp_md_est":579.5,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"KI","iso_a3":"KIR","iso_n3":"296","un_a3":"296","wb_a2":"KI","wb_a3":"KIR","woe_id":-99,"adm0_a3_is":"KIR","adm0_a3_us":"KIR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[1200]],[[1201]],[[1202]],[[1203]],[[1204]],[[1205]],[[1206]],[[1207]],[[1208]],[[1209]],[[1210]],[[1211]],[[1212]],[[1213]],[[1214]],[[1215]],[[1216]],[[1217]],[[1218]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Kitts and Nevis","sov_a3":"KNA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Kitts and Nevis","adm0_a3":"KNA","geou_dif":0,"geounit":"Saint Kitts and Nevis","gu_a3":"KNA","su_dif":0,"subunit":"Saint Kitts and Nevis","su_a3":"KNA","brk_diff":0,"name":"St. Kitts and Nevis","name_long":"Saint Kitts and Nevis","brk_a3":"KNA","brk_name":"Saint Kitts and Nevis","brk_group":null,"abbrev":"St.K.N.","postal":"KN","formal_en":"Federation of Saint Kitts and Nevis","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Kitts and Nevis","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":40131,"gdp_md_est":777.7,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KN","iso_a3":"KNA","iso_n3":"659","un_a3":"659","wb_a2":"KN","wb_a3":"KNA","woe_id":-99,"adm0_a3_is":"KNA","adm0_a3_us":"KNA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":19,"long_len":21,"abbrev_len":7,"tiny":4,"homepart":1},"arcs":[[[1219]],[[1220]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"South Korea","sov_a3":"KOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Korea","adm0_a3":"KOR","geou_dif":0,"geounit":"South Korea","gu_a3":"KOR","su_dif":0,"subunit":"South Korea","su_a3":"KOR","brk_diff":0,"name":"Korea","name_long":"Republic of Korea","brk_a3":"KOR","brk_name":"Republic of Korea","brk_group":null,"abbrev":"S.K.","postal":"KR","formal_en":"Republic of Korea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Korea, Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":1,"mapcolor13":5,"pop_est":48508972,"gdp_md_est":1335000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"KR","iso_a3":"KOR","iso_n3":"410","un_a3":"410","wb_a2":"KR","wb_a3":"KOR","woe_id":-99,"adm0_a3_is":"KOR","adm0_a3_us":"KOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":17,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1221]],[[1222]],[[1223]],[[1224]],[[1225]],[[1226]],[[1227]],[[1228]],[[1229]],[[1230]],[[1231,1232]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kosovo","sov_a3":"KOS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kosovo","adm0_a3":"KOS","geou_dif":0,"geounit":"Kosovo","gu_a3":"KOS","su_dif":0,"subunit":"Kosovo","su_a3":"KOS","brk_diff":1,"name":"Kosovo","name_long":"Kosovo","brk_a3":"B57","brk_name":"Kosovo","brk_group":null,"abbrev":"Kos.","postal":"KO","formal_en":"Republic of Kosovo","formal_fr":null,"note_adm0":null,"note_brk":"Self admin.; Claimed by Serbia","name_sort":"Kosovo","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":11,"pop_est":1804838,"gdp_md_est":5352,"pop_year":-99,"lastcensus":1981,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"KV","wb_a3":"KSV","woe_id":-99,"adm0_a3_is":"SRB","adm0_a3_us":"KOS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1233,-17,1234,1235]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kuwait","sov_a3":"KWT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kuwait","adm0_a3":"KWT","geou_dif":0,"geounit":"Kuwait","gu_a3":"KWT","su_dif":0,"subunit":"Kuwait","su_a3":"KWT","brk_diff":0,"name":"Kuwait","name_long":"Kuwait","brk_a3":"KWT","brk_name":"Kuwait","brk_group":null,"abbrev":"Kwt.","postal":"KW","formal_en":"State of Kuwait","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kuwait","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":2,"mapcolor13":2,"pop_est":2691158,"gdp_md_est":149100,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KW","iso_a3":"KWT","iso_n3":"414","un_a3":"414","wb_a2":"KW","wb_a3":"KWT","woe_id":-99,"adm0_a3_is":"KWT","adm0_a3_us":"KWT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1236]],[[1237,-1111,1238]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Laos","sov_a3":"LAO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Laos","adm0_a3":"LAO","geou_dif":0,"geounit":"Laos","gu_a3":"LAO","su_dif":0,"subunit":"Laos","su_a3":"LAO","brk_diff":0,"name":"Lao PDR","name_long":"Lao PDR","brk_a3":"LAO","brk_name":"Laos","brk_group":null,"abbrev":"Laos","postal":"LA","formal_en":"Lao People's Democratic Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lao PDR","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":9,"pop_est":6834942,"gdp_md_est":13980,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LA","iso_a3":"LAO","iso_n3":"418","un_a3":"418","wb_a2":"LA","wb_a3":"LAO","woe_id":-99,"adm0_a3_is":"LAO","adm0_a3_us":"LAO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1239,1240,1241,-1199,1242,1243,-539]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Lebanon","sov_a3":"LBN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lebanon","adm0_a3":"LBN","geou_dif":0,"geounit":"Lebanon","gu_a3":"LBN","su_dif":0,"subunit":"Lebanon","su_a3":"LBN","brk_diff":0,"name":"Lebanon","name_long":"Lebanon","brk_a3":"LBN","brk_name":"Lebanon","brk_group":null,"abbrev":"Leb.","postal":"LB","formal_en":"Lebanese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lebanon","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":12,"pop_est":4017095,"gdp_md_est":44060,"pop_year":-99,"lastcensus":1970,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LB","iso_a3":"LBN","iso_n3":"422","un_a3":"422","wb_a2":"LB","wb_a3":"LBN","woe_id":-99,"adm0_a3_is":"LBN","adm0_a3_us":"LBN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":4,"homepart":1},"arcs":[[-1123,1244,1245]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Liberia","sov_a3":"LBR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Liberia","adm0_a3":"LBR","geou_dif":0,"geounit":"Liberia","gu_a3":"LBR","su_dif":0,"subunit":"Liberia","su_a3":"LBR","brk_diff":0,"name":"Liberia","name_long":"Liberia","brk_a3":"LBR","brk_name":"Liberia","brk_group":null,"abbrev":"Liberia","postal":"LR","formal_en":"Republic of Liberia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Liberia","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":4,"mapcolor13":9,"pop_est":3441790,"gdp_md_est":1526,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"LR","iso_a3":"LBR","iso_n3":"430","un_a3":"430","wb_a2":"LR","wb_a3":"LBR","woe_id":-99,"adm0_a3_is":"LBR","adm0_a3_us":"LBR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-568,1246,1247,-810]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Libya","sov_a3":"LBY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Libya","adm0_a3":"LBY","geou_dif":0,"geounit":"Libya","gu_a3":"LBY","su_dif":0,"subunit":"Libya","su_a3":"LBY","brk_diff":0,"name":"Libya","name_long":"Libya","brk_a3":"LBY","brk_name":"Libya","brk_group":null,"abbrev":"Libya","postal":"LY","formal_en":"Libya","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Libya","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":11,"pop_est":6310434,"gdp_md_est":88830,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LY","iso_a3":"LBY","iso_n3":"434","un_a3":"434","wb_a2":"LY","wb_a3":"LBY","woe_id":-99,"adm0_a3_is":"LBY","adm0_a3_us":"LBY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-680,1248,1249,1250,-659,1251,1252]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Lucia","sov_a3":"LCA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Lucia","adm0_a3":"LCA","geou_dif":0,"geounit":"Saint Lucia","gu_a3":"LCA","su_dif":0,"subunit":"Saint Lucia","su_a3":"LCA","brk_diff":0,"name":"Saint Lucia","name_long":"Saint Lucia","brk_a3":"LCA","brk_name":"Saint Lucia","brk_group":null,"abbrev":"S.L.","postal":"LC","formal_en":"Saint Lucia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Lucia","name_alt":null,"mapcolor7":3,"mapcolor8":4,"mapcolor9":3,"mapcolor13":4,"pop_est":160267,"gdp_md_est":1778,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LC","iso_a3":"LCA","iso_n3":"662","un_a3":"662","wb_a2":"LC","wb_a3":"LCA","woe_id":-99,"adm0_a3_is":"LCA","adm0_a3_us":"LCA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":4,"tiny":4,"homepart":1},"arcs":[[1253]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Liechtenstein","sov_a3":"LIE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Liechtenstein","adm0_a3":"LIE","geou_dif":0,"geounit":"Liechtenstein","gu_a3":"LIE","su_dif":0,"subunit":"Liechtenstein","su_a3":"LIE","brk_diff":0,"name":"Liechtenstein","name_long":"Liechtenstein","brk_a3":"LIE","brk_name":"Liechtenstein","brk_group":null,"abbrev":"Liech.","postal":"FL","formal_en":"Principality of Liechtenstein","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Liechtenstein","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":2,"mapcolor13":9,"pop_est":34761,"gdp_md_est":4160,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"LI","iso_a3":"LIE","iso_n3":"438","un_a3":"438","wb_a2":"LI","wb_a3":"LIE","woe_id":-99,"adm0_a3_is":"LIE","adm0_a3_us":"LIE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":13,"long_len":13,"abbrev_len":6,"tiny":6,"homepart":1},"arcs":[[-484,-215]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sri Lanka","sov_a3":"LKA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sri Lanka","adm0_a3":"LKA","geou_dif":0,"geounit":"Sri Lanka","gu_a3":"LKA","su_dif":0,"subunit":"Sri Lanka","su_a3":"LKA","brk_diff":0,"name":"Sri Lanka","name_long":"Sri Lanka","brk_a3":"LKA","brk_name":"Sri Lanka","brk_group":null,"abbrev":"Sri L.","postal":"LK","formal_en":"Democratic Socialist Republic of Sri Lanka","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sri Lanka","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":4,"mapcolor13":9,"pop_est":21324791,"gdp_md_est":91870,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LK","iso_a3":"LKA","iso_n3":"144","un_a3":"144","wb_a2":"LK","wb_a3":"LKA","woe_id":-99,"adm0_a3_is":"LKA","adm0_a3_us":"LKA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":9,"long_len":9,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1254]],[[1255]],[[1256]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Lesotho","sov_a3":"LSO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lesotho","adm0_a3":"LSO","geou_dif":0,"geounit":"Lesotho","gu_a3":"LSO","su_dif":0,"subunit":"Lesotho","su_a3":"LSO","brk_diff":0,"name":"Lesotho","name_long":"Lesotho","brk_a3":"LSO","brk_name":"Lesotho","brk_group":null,"abbrev":"Les.","postal":"LS","formal_en":"Kingdom of Lesotho","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lesotho","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":8,"pop_est":2130819,"gdp_md_est":3293,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LS","iso_a3":"LSO","iso_n3":"426","un_a3":"426","wb_a2":"LS","wb_a3":"LSO","woe_id":-99,"adm0_a3_is":"LSO","adm0_a3_us":"LSO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1257]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Lithuania","sov_a3":"LTU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lithuania","adm0_a3":"LTU","geou_dif":0,"geounit":"Lithuania","gu_a3":"LTU","su_dif":0,"subunit":"Lithuania","su_a3":"LTU","brk_diff":0,"name":"Lithuania","name_long":"Lithuania","brk_a3":"LTU","brk_name":"Lithuania","brk_group":null,"abbrev":"Lith.","postal":"LT","formal_en":"Republic of Lithuania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lithuania","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":3,"mapcolor13":9,"pop_est":3555179,"gdp_md_est":63330,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LT","iso_a3":"LTU","iso_n3":"440","un_a3":"440","wb_a2":"LT","wb_a3":"LTU","woe_id":-99,"adm0_a3_is":"LTU","adm0_a3_us":"LTU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1258,1259]],[[-285,1260,1261,1262,1263]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Luxembourg","sov_a3":"LUX","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Luxembourg","adm0_a3":"LUX","geou_dif":0,"geounit":"Luxembourg","gu_a3":"LUX","su_dif":0,"subunit":"Luxembourg","su_a3":"LUX","brk_diff":0,"name":"Luxembourg","name_long":"Luxembourg","brk_a3":"LUX","brk_name":"Luxembourg","brk_group":null,"abbrev":"Lux.","postal":"L","formal_en":"Grand Duchy of Luxembourg","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Luxembourg","name_alt":null,"mapcolor7":1,"mapcolor8":7,"mapcolor9":3,"mapcolor13":7,"pop_est":491775,"gdp_md_est":39370,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"LU","iso_a3":"LUX","iso_n3":"442","un_a3":"442","wb_a2":"LU","wb_a3":"LUX","woe_id":-99,"adm0_a3_is":"LUX","adm0_a3_us":"LUX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[-634,-760,-230]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Latvia","sov_a3":"LVA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Latvia","adm0_a3":"LVA","geou_dif":0,"geounit":"Latvia","gu_a3":"LVA","su_dif":0,"subunit":"Latvia","su_a3":"LVA","brk_diff":0,"name":"Latvia","name_long":"Latvia","brk_a3":"LVA","brk_name":"Latvia","brk_group":null,"abbrev":"Lat.","postal":"LV","formal_en":"Republic of Latvia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Latvia","name_alt":null,"mapcolor7":4,"mapcolor8":7,"mapcolor9":6,"mapcolor13":13,"pop_est":2231503,"gdp_md_est":38860,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LV","iso_a3":"LVA","iso_n3":"428","un_a3":"428","wb_a2":"LV","wb_a3":"LVA","woe_id":-99,"adm0_a3_is":"LVA","adm0_a3_us":"LVA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1264,-286,-1264,1265,-707]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"Macao S.A.R","adm0_a3":"MAC","geou_dif":0,"geounit":"Macao S.A.R","gu_a3":"MAC","su_dif":0,"subunit":"Macao S.A.R","su_a3":"MAC","brk_diff":0,"name":"Macao","name_long":"Macao","brk_a3":"MAC","brk_name":"Macao","brk_group":null,"abbrev":"Mac.","postal":"MO","formal_en":"Macao Special Administrative Region, PRC","formal_fr":null,"note_adm0":"China","note_brk":null,"name_sort":"Macao SAR, China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":559846,"gdp_md_est":18140,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MO","iso_a3":"MAC","iso_n3":"446","un_a3":"446","wb_a2":"MO","wb_a3":"MAC","woe_id":-99,"adm0_a3_is":"MAC","adm0_a3_us":"MAC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[-536,1266]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Martin","adm0_a3":"MAF","geou_dif":0,"geounit":"Saint Martin","gu_a3":"MAF","su_dif":0,"subunit":"Saint Martin","su_a3":"MAF","brk_diff":0,"name":"St-Martin","name_long":"Saint-Martin","brk_a3":"MAF","brk_name":"Saint-Martin","brk_group":null,"abbrev":"St. M.","postal":"MF","formal_en":"Saint-Martin (French part)","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St. Martin (French part)","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":36661,"gdp_md_est":449,"pop_year":2008,"lastcensus":-99,"gdp_year":1999,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":0,"fips_10":null,"iso_a2":"MF","iso_a3":"MAF","iso_n3":"663","un_a3":"663","wb_a2":"MF","wb_a3":"MAF","woe_id":-99,"adm0_a3_is":"MAF","adm0_a3_us":"MAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":9,"long_len":12,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[1267,1268]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Morocco","sov_a3":"MAR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Morocco","adm0_a3":"MAR","geou_dif":0,"geounit":"Morocco","gu_a3":"MAR","su_dif":0,"subunit":"Morocco","su_a3":"MAR","brk_diff":0,"name":"Morocco","name_long":"Morocco","brk_a3":"MAR","brk_name":"Morocco","brk_group":null,"abbrev":"Mor.","postal":"MA","formal_en":"Kingdom of Morocco","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Morocco","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":9,"pop_est":34859364,"gdp_md_est":136600,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MA","iso_a3":"MAR","iso_n3":"504","un_a3":"504","wb_a2":"MA","wb_a3":"MAR","woe_id":-99,"adm0_a3_is":"MAR","adm0_a3_us":"MAR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-664,1269,1270]]},{"type":"Polygon","properties":{"scalerank":6,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Monaco","sov_a3":"MCO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Monaco","adm0_a3":"MCO","geou_dif":0,"geounit":"Monaco","gu_a3":"MCO","su_dif":0,"subunit":"Monaco","su_a3":"MCO","brk_diff":0,"name":"Monaco","name_long":"Monaco","brk_a3":"MCO","brk_name":"Monaco","brk_group":null,"abbrev":"Mco.","postal":"MC","formal_en":"Principality of Monaco","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Monaco","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":12,"pop_est":32965,"gdp_md_est":976.3,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MC","iso_a3":"MCO","iso_n3":"492","un_a3":"492","wb_a2":"MC","wb_a3":"MCO","woe_id":-99,"adm0_a3_is":"MCO","adm0_a3_us":"MCO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[1271,-763]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Moldova","sov_a3":"MDA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Moldova","adm0_a3":"MDA","geou_dif":0,"geounit":"Moldova","gu_a3":"MDA","su_dif":0,"subunit":"Moldova","su_a3":"MDA","brk_diff":0,"name":"Moldova","name_long":"Moldova","brk_a3":"MDA","brk_name":"Moldova","brk_group":null,"abbrev":"Mda.","postal":"MD","formal_en":"Republic of Moldova","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Moldova","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":4,"mapcolor13":12,"pop_est":4320748,"gdp_md_est":10670,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MD","iso_a3":"MDA","iso_n3":"498","un_a3":"498","wb_a2":"MD","wb_a3":"MDA","woe_id":-99,"adm0_a3_is":"MDA","adm0_a3_us":"MDA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1272,1273]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Madagascar","sov_a3":"MDG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Madagascar","adm0_a3":"MDG","geou_dif":0,"geounit":"Madagascar","gu_a3":"MDG","su_dif":0,"subunit":"Madagascar","su_a3":"MDG","brk_diff":0,"name":"Madagascar","name_long":"Madagascar","brk_a3":"MDG","brk_name":"Madagascar","brk_group":null,"abbrev":"Mad.","postal":"MG","formal_en":"Republic of Madagascar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Madagascar","name_alt":null,"mapcolor7":6,"mapcolor8":5,"mapcolor9":2,"mapcolor13":3,"pop_est":20653556,"gdp_md_est":20130,"pop_year":-99,"lastcensus":1993,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MG","iso_a3":"MDG","iso_n3":"450","un_a3":"450","wb_a2":"MG","wb_a3":"MDG","woe_id":-99,"adm0_a3_is":"MDG","adm0_a3_us":"MDG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1274]],[[1275]],[[1276]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Maldives","sov_a3":"MDV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Maldives","adm0_a3":"MDV","geou_dif":0,"geounit":"Maldives","gu_a3":"MDV","su_dif":0,"subunit":"Maldives","su_a3":"MDV","brk_diff":0,"name":"Maldives","name_long":"Maldives","brk_a3":"MDV","brk_name":"Maldives","brk_group":null,"abbrev":"Mald.","postal":"MV","formal_en":"Republic of Maldives","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Maldives","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":1,"mapcolor13":7,"pop_est":396334,"gdp_md_est":1716,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MV","iso_a3":"MDV","iso_n3":"462","un_a3":"462","wb_a2":"MV","wb_a3":"MDV","woe_id":-99,"adm0_a3_is":"MDV","adm0_a3_us":"B13","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1277]],[[1278]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Mexico","sov_a3":"MEX","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mexico","adm0_a3":"MEX","geou_dif":0,"geounit":"Mexico","gu_a3":"MEX","su_dif":0,"subunit":"Mexico","su_a3":"MEX","brk_diff":0,"name":"Mexico","name_long":"Mexico","brk_a3":"MEX","brk_name":"Mexico","brk_group":null,"abbrev":"Mex.","postal":"MX","formal_en":"United Mexican States","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mexico","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":7,"mapcolor13":3,"pop_est":111211789,"gdp_md_est":1563000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MX","iso_a3":"MEX","iso_n3":"484","un_a3":"484","wb_a2":"MX","wb_a3":"MEX","woe_id":-99,"adm0_a3_is":"MEX","adm0_a3_us":"MEX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1279]],[[1280]],[[1281]],[[1282]],[[1283]],[[1284]],[[1285]],[[1286]],[[1287]],[[1288]],[[1289]],[[1290]],[[1291]],[[1292]],[[1293]],[[1294,-290,-891,1295,1296]]]},{"type":"MultiPolygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Marshall Islands","sov_a3":"MHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Marshall Islands","adm0_a3":"MHL","geou_dif":0,"geounit":"Marshall Islands","gu_a3":"MHL","su_dif":0,"subunit":"Marshall Islands","su_a3":"MHL","brk_diff":0,"name":"Marshall Is.","name_long":"Marshall Islands","brk_a3":"MHL","brk_name":"Marshall Is.","brk_group":null,"abbrev":"M. Is.","postal":"MH","formal_en":"Republic of the Marshall Islands","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Marshall Islands","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":5,"mapcolor13":3,"pop_est":64522,"gdp_md_est":133.5,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MH","iso_a3":"MHL","iso_n3":"584","un_a3":"584","wb_a2":"MH","wb_a3":"MHL","woe_id":-99,"adm0_a3_is":"MHL","adm0_a3_us":"MHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":12,"long_len":16,"abbrev_len":6,"tiny":2,"homepart":1},"arcs":[[[1297]],[[1298]],[[1299]],[[1300]],[[1301]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Macedonia","sov_a3":"MKD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Macedonia","adm0_a3":"MKD","geou_dif":0,"geounit":"Macedonia","gu_a3":"MKD","su_dif":0,"subunit":"Macedonia","su_a3":"MKD","brk_diff":0,"name":"Macedonia","name_long":"Macedonia","brk_a3":"MKD","brk_name":"Macedonia","brk_group":null,"abbrev":"Mkd.","postal":"MK","formal_en":"Former Yugoslav Republic of Macedonia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Macedonia, FYR","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":2066718,"gdp_md_est":18780,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MK","iso_a3":"MKD","iso_n3":"807","un_a3":"807","wb_a2":"MK","wb_a3":"MKD","woe_id":-99,"adm0_a3_is":"MKD","adm0_a3_us":"MKD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-257,-867,-18,-1234,1302]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mali","sov_a3":"MLI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mali","adm0_a3":"MLI","geou_dif":0,"geounit":"Mali","gu_a3":"MLI","su_dif":0,"subunit":"Mali","su_a3":"MLI","brk_diff":0,"name":"Mali","name_long":"Mali","brk_a3":"MLI","brk_name":"Mali","brk_group":null,"abbrev":"Mali","postal":"ML","formal_en":"Republic of Mali","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mali","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":7,"pop_est":12666987,"gdp_md_est":14590,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ML","iso_a3":"MLI","iso_n3":"466","un_a3":"466","wb_a2":"ML","wb_a3":"MLI","woe_id":-99,"adm0_a3_is":"MLI","adm0_a3_us":"MLI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1303,-244,-570,-809,1304,1305,-661]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Malta","sov_a3":"MLT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malta","adm0_a3":"MLT","geou_dif":0,"geounit":"Malta","gu_a3":"MLT","su_dif":0,"subunit":"Malta","su_a3":"MLT","brk_diff":0,"name":"Malta","name_long":"Malta","brk_a3":"MLT","brk_name":"Malta","brk_group":null,"abbrev":"Malta","postal":"M","formal_en":"Republic of Malta","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malta","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":405165,"gdp_md_est":9962,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MT","iso_a3":"MLT","iso_n3":"470","un_a3":"470","wb_a2":"MT","wb_a3":"MLT","woe_id":-99,"adm0_a3_is":"MLT","adm0_a3_us":"MLT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[[1306]],[[1307]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Myanmar","sov_a3":"MMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Myanmar","adm0_a3":"MMR","geou_dif":0,"geounit":"Myanmar","gu_a3":"MMR","su_dif":0,"subunit":"Myanmar","su_a3":"MMR","brk_diff":0,"name":"Myanmar","name_long":"Myanmar","brk_a3":"MMR","brk_name":"Myanmar","brk_group":null,"abbrev":"Myan.","postal":"MM","formal_en":"Republic of the Union of Myanmar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Myanmar","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":13,"pop_est":48137741,"gdp_md_est":55130,"pop_year":-99,"lastcensus":1983,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MM","iso_a3":"MMR","iso_n3":"104","un_a3":"104","wb_a2":"MM","wb_a3":"MMR","woe_id":-99,"adm0_a3_is":"MMR","adm0_a3_us":"MMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1308]],[[1309]],[[1310]],[[1311]],[[1312]],[[1313]],[[1314]],[[1315]],[[1316]],[[1317]],[[1318]],[[1319]],[[1320]],[[1321]],[[1322]],[[1323]],[[1324]],[[1325]],[[-1244,1326,1327,-251,-1089,-540]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Montenegro","sov_a3":"MNE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Montenegro","adm0_a3":"MNE","geou_dif":0,"geounit":"Montenegro","gu_a3":"MNE","su_dif":0,"subunit":"Montenegro","su_a3":"MNE","brk_diff":0,"name":"Montenegro","name_long":"Montenegro","brk_a3":"MNE","brk_name":"Montenegro","brk_group":null,"abbrev":"Mont.","postal":"ME","formal_en":"Montenegro","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Montenegro","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":5,"pop_est":672180,"gdp_md_est":6816,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ME","iso_a3":"MNE","iso_n3":"499","un_a3":"499","wb_a2":"ME","wb_a3":"MNE","woe_id":-99,"adm0_a3_is":"MNE","adm0_a3_us":"MNE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1328,-1235,-21,1329,-908,-277]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mongolia","sov_a3":"MNG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mongolia","adm0_a3":"MNG","geou_dif":0,"geounit":"Mongolia","gu_a3":"MNG","su_dif":0,"subunit":"Mongolia","su_a3":"MNG","brk_diff":0,"name":"Mongolia","name_long":"Mongolia","brk_a3":"MNG","brk_name":"Mongolia","brk_group":null,"abbrev":"Mong.","postal":"MN","formal_en":"Mongolia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mongolia","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":5,"mapcolor13":6,"pop_est":3041142,"gdp_md_est":9476,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MN","iso_a3":"MNG","iso_n3":"496","un_a3":"496","wb_a2":"MN","wb_a3":"MNG","woe_id":-99,"adm0_a3_is":"MNG","adm0_a3_us":"MNG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-562,1330]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Northern Mariana Islands","adm0_a3":"MNP","geou_dif":0,"geounit":"Northern Mariana Islands","gu_a3":"MNP","su_dif":0,"subunit":"Northern Mariana Islands","su_a3":"MNP","brk_diff":0,"name":"N. Mariana Is.","name_long":"Northern Mariana Islands","brk_a3":"MNP","brk_name":"N. Mariana Is.","brk_group":null,"abbrev":"N.M.I.","postal":"MP","formal_en":"Commonwealth of the Northern Mariana Islands","formal_fr":null,"note_adm0":"Commonwealth of U.S.A.","note_brk":null,"name_sort":"Northern Mariana Islands","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":88662,"gdp_md_est":900,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MP","iso_a3":"MNP","iso_n3":"580","un_a3":"580","wb_a2":"MP","wb_a3":"MNP","woe_id":-99,"adm0_a3_is":"MNP","adm0_a3_us":"MNP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":14,"long_len":24,"abbrev_len":6,"tiny":3,"homepart":-99},"arcs":[[[1331]],[[1332]],[[1333]],[[1334]],[[1335]],[[1336]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mozambique","sov_a3":"MOZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mozambique","adm0_a3":"MOZ","geou_dif":0,"geounit":"Mozambique","gu_a3":"MOZ","su_dif":0,"subunit":"Mozambique","su_a3":"MOZ","brk_diff":0,"name":"Mozambique","name_long":"Mozambique","brk_a3":"MOZ","brk_name":"Mozambique","brk_group":null,"abbrev":"Moz.","postal":"MZ","formal_en":"Republic of Mozambique","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mozambique","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":1,"mapcolor13":4,"pop_est":21669278,"gdp_md_est":18940,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MZ","iso_a3":"MOZ","iso_n3":"508","un_a3":"508","wb_a2":"MZ","wb_a3":"MOZ","woe_id":-99,"adm0_a3_is":"MOZ","adm0_a3_us":"MOZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1337,1338,1339,1340,1341,1342,1343,1344],[1345],[1346]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mauritania","sov_a3":"MRT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mauritania","adm0_a3":"MRT","geou_dif":0,"geounit":"Mauritania","gu_a3":"MRT","su_dif":0,"subunit":"Mauritania","su_a3":"MRT","brk_diff":0,"name":"Mauritania","name_long":"Mauritania","brk_a3":"MRT","brk_name":"Mauritania","brk_group":null,"abbrev":"Mrt.","postal":"MR","formal_en":"Islamic Republic of Mauritania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mauritania","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":2,"mapcolor13":1,"pop_est":3129486,"gdp_md_est":6308,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MR","iso_a3":"MRT","iso_n3":"478","un_a3":"478","wb_a2":"MR","wb_a3":"MRT","woe_id":-99,"adm0_a3_is":"MRT","adm0_a3_us":"MRT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1347]],[[1348,1349,1350,-662,-1306]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Montserrat","adm0_a3":"MSR","geou_dif":0,"geounit":"Montserrat","gu_a3":"MSR","su_dif":0,"subunit":"Montserrat","su_a3":"MSR","brk_diff":0,"name":"Montserrat","name_long":"Montserrat","brk_a3":"MSR","brk_name":"Montserrat","brk_group":null,"abbrev":"Monts.","postal":"MS","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Montserrat","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":5097,"gdp_md_est":29,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MS","iso_a3":"MSR","iso_n3":"500","un_a3":"500","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"MSR","adm0_a3_us":"MSR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":10,"long_len":10,"abbrev_len":6,"tiny":6,"homepart":-99},"arcs":[[1351]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Mauritius","sov_a3":"MUS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mauritius","adm0_a3":"MUS","geou_dif":0,"geounit":"Mauritius","gu_a3":"MUS","su_dif":0,"subunit":"Mauritius","su_a3":"MUS","brk_diff":0,"name":"Mauritius","name_long":"Mauritius","brk_a3":"MUS","brk_name":"Mauritius","brk_group":null,"abbrev":"Mus.","postal":"MU","formal_en":"Republic of Mauritius","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mauritius","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":5,"mapcolor13":7,"pop_est":1284264,"gdp_md_est":15270,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MU","iso_a3":"MUS","iso_n3":"480","un_a3":"480","wb_a2":"MU","wb_a3":"MUS","woe_id":-99,"adm0_a3_is":"MUS","adm0_a3_us":"MUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[1352]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Malawi","sov_a3":"MWI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malawi","adm0_a3":"MWI","geou_dif":0,"geounit":"Malawi","gu_a3":"MWI","su_dif":0,"subunit":"Malawi","su_a3":"MWI","brk_diff":0,"name":"Malawi","name_long":"Malawi","brk_a3":"MWI","brk_name":"Malawi","brk_group":null,"abbrev":"Mal.","postal":"MW","formal_en":"Republic of Malawi","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malawi","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":4,"mapcolor13":5,"pop_est":14268711,"gdp_md_est":11810,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MW","iso_a3":"MWI","iso_n3":"454","un_a3":"454","wb_a2":"MW","wb_a3":"MWI","woe_id":-99,"adm0_a3_is":"MWI","adm0_a3_us":"MWI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[-1347]],[[-1346]],[[-1343,1353,1354]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Malaysia","sov_a3":"MYS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malaysia","adm0_a3":"MYS","geou_dif":0,"geounit":"Malaysia","gu_a3":"MYS","su_dif":0,"subunit":"Malaysia","su_a3":"MYS","brk_diff":0,"name":"Malaysia","name_long":"Malaysia","brk_a3":"MYS","brk_name":"Malaysia","brk_group":null,"abbrev":"Malay.","postal":"MY","formal_en":"Malaysia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malaysia","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":3,"mapcolor13":6,"pop_est":25715819,"gdp_md_est":384300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MY","iso_a3":"MYS","iso_n3":"458","un_a3":"458","wb_a2":"MY","wb_a3":"MYS","woe_id":-99,"adm0_a3_is":"MYS","adm0_a3_us":"MYS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1355]],[[1356]],[[1357]],[[-1064,1358]],[[1359]],[[1360]],[[1361,1362]],[[-1067,1363,-325,-324,1364]],[[1365]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Namibia","sov_a3":"NAM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Namibia","adm0_a3":"NAM","geou_dif":0,"geounit":"Namibia","gu_a3":"NAM","su_dif":0,"subunit":"Namibia","su_a3":"NAM","brk_diff":0,"name":"Namibia","name_long":"Namibia","brk_a3":"NAM","brk_name":"Namibia","brk_group":null,"abbrev":"Nam.","postal":"NA","formal_en":"Republic of Namibia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Namibia","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":1,"mapcolor13":7,"pop_est":2108665,"gdp_md_est":13250,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NA","iso_a3":"NAM","iso_n3":"516","un_a3":"516","wb_a2":"NA","wb_a3":"NAM","woe_id":-99,"adm0_a3_is":"NAM","adm0_a3_us":"NAM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1366,-331,1367,1368,-10]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"New Caledonia","adm0_a3":"NCL","geou_dif":0,"geounit":"New Caledonia","gu_a3":"NCL","su_dif":0,"subunit":"New Caledonia","su_a3":"NCL","brk_diff":0,"name":"New Caledonia","name_long":"New Caledonia","brk_a3":"NCL","brk_name":"New Caledonia","brk_group":null,"abbrev":"New C.","postal":"NC","formal_en":"New Caledonia","formal_fr":"Nouvelle-Calédonie","note_adm0":"Fr.","note_brk":null,"name_sort":"New Caledonia","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":227436,"gdp_md_est":3158,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"NC","iso_a3":"NCL","iso_n3":"540","un_a3":"540","wb_a2":"NC","wb_a3":"NCL","woe_id":-99,"adm0_a3_is":"NCL","adm0_a3_us":"NCL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":13,"long_len":13,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[[1369]],[[1370]],[[1371]],[[1372]],[[1373]],[[1374]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Niger","sov_a3":"NER","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Niger","adm0_a3":"NER","geou_dif":0,"geounit":"Niger","gu_a3":"NER","su_dif":0,"subunit":"Niger","su_a3":"NER","brk_diff":0,"name":"Niger","name_long":"Niger","brk_a3":"NER","brk_name":"Niger","brk_group":null,"abbrev":"Niger","postal":"NE","formal_en":"Republic of Niger","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Niger","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":3,"mapcolor13":13,"pop_est":15306252,"gdp_md_est":10040,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"NE","iso_a3":"NER","iso_n3":"562","un_a3":"562","wb_a2":"NE","wb_a3":"NER","woe_id":-99,"adm0_a3_is":"NER","adm0_a3_us":"NER","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1375,1376,-239,-240,-1304,-660,-1251]]},{"type":"Polygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Norfolk Island","adm0_a3":"NFK","geou_dif":0,"geounit":"Norfolk Island","gu_a3":"NFK","su_dif":0,"subunit":"Norfolk Island","su_a3":"NFK","brk_diff":0,"name":"Norfolk Island","name_long":"Norfolk Island","brk_a3":"NFK","brk_name":"Norfolk Island","brk_group":null,"abbrev":"Nfk. I.","postal":"NF","formal_en":"Territory of Norfolk Island","formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Norfolk Island","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":2141,"gdp_md_est":32.115,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NF","iso_a3":"NFK","iso_n3":"574","un_a3":"574","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NFK","adm0_a3_us":"NFK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":14,"long_len":14,"abbrev_len":7,"tiny":-99,"homepart":-99},"arcs":[[1377]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Nigeria","sov_a3":"NGA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nigeria","adm0_a3":"NGA","geou_dif":0,"geounit":"Nigeria","gu_a3":"NGA","su_dif":0,"subunit":"Nigeria","su_a3":"NGA","brk_diff":0,"name":"Nigeria","name_long":"Nigeria","brk_a3":"NGA","brk_name":"Nigeria","brk_group":null,"abbrev":"Nigeria","postal":"NG","formal_en":"Federal Republic of Nigeria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nigeria","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":2,"pop_est":149229090,"gdp_md_est":335400,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NG","iso_a3":"NGA","iso_n3":"566","un_a3":"566","wb_a2":"NG","wb_a3":"NGA","woe_id":-99,"adm0_a3_is":"NGA","adm0_a3_us":"NGA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[[1378]],[[1379,-575,1380,-235,-1377]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Nicaragua","sov_a3":"NIC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nicaragua","adm0_a3":"NIC","geou_dif":0,"geounit":"Nicaragua","gu_a3":"NIC","su_dif":0,"subunit":"Nicaragua","su_a3":"NIC","brk_diff":0,"name":"Nicaragua","name_long":"Nicaragua","brk_a3":"NIC","brk_name":"Nicaragua","brk_group":null,"abbrev":"Nic.","postal":"NI","formal_en":"Republic of Nicaragua","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nicaragua","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":9,"pop_est":5891199,"gdp_md_est":16790,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NI","iso_a3":"NIC","iso_n3":"558","un_a3":"558","wb_a2":"NI","wb_a3":"NIC","woe_id":-99,"adm0_a3_is":"NIC","adm0_a3_us":"NIC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1381,-608,1382,-900]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Niue","adm0_a3":"NIU","geou_dif":0,"geounit":"Niue","gu_a3":"NIU","su_dif":0,"subunit":"Niue","su_a3":"NIU","brk_diff":0,"name":"Niue","name_long":"Niue","brk_a3":"NIU","brk_name":"Niue","brk_group":null,"abbrev":"Niue","postal":"NU","formal_en":null,"formal_fr":null,"note_adm0":"Assoc. with N.Z.","note_brk":null,"name_sort":"Niue","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":1398,"gdp_md_est":10.01,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NU","iso_a3":"NIU","iso_n3":"570","un_a3":"570","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NIU","adm0_a3_us":"NIU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":3,"homepart":-99},"arcs":[[1383]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Netherlands","adm0_a3":"NLD","geou_dif":0,"geounit":"Netherlands","gu_a3":"NLD","su_dif":0,"subunit":"Netherlands","su_a3":"NLD","brk_diff":0,"name":"Netherlands","name_long":"Netherlands","brk_a3":"NLD","brk_name":"Netherlands","brk_group":null,"abbrev":"Neth.","postal":"NL","formal_en":"Kingdom of the Netherlands","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Netherlands","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":16715999,"gdp_md_est":672000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NL","iso_a3":"NLD","iso_n3":"528","un_a3":"528","wb_a2":"NL","wb_a3":"NLD","woe_id":-99,"adm0_a3_is":"NLD","adm0_a3_us":"NLD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1384]],[[1385]],[[-233,1386]],[[1387]],[[1388]],[[1389]],[[1390,-635,1391,-234]],[[1392]],[[1393]],[[1394]],[[1395]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Norway","sov_a3":"NOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Norway","adm0_a3":"NOR","geou_dif":0,"geounit":"Norway","gu_a3":"NOR","su_dif":0,"subunit":"Norway","su_a3":"NOR","brk_diff":0,"name":"Norway","name_long":"Norway","brk_a3":"NOR","brk_name":"Norway","brk_group":null,"abbrev":"Nor.","postal":"N","formal_en":"Kingdom of Norway","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Norway","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":8,"mapcolor13":12,"pop_est":4676305,"gdp_md_est":276400,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NO","iso_a3":"NOR","iso_n3":"578","un_a3":"578","wb_a2":"NO","wb_a3":"NOR","woe_id":-99,"adm0_a3_is":"NOR","adm0_a3_us":"NOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1396]],[[1397]],[[1398]],[[1399]],[[1400]],[[1401]],[[1402]],[[1403]],[[1404]],[[1405]],[[1406]],[[1407]],[[1408]],[[1409]],[[1410]],[[1411]],[[1412]],[[1413]],[[1414]],[[1415]],[[1416,-724,1417,1418]],[[1419]],[[1420]],[[1421]],[[1422]],[[1423]],[[1424]],[[1425]],[[1426]],[[1427]],[[1428]],[[1429]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Nepal","sov_a3":"NPL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nepal","adm0_a3":"NPL","geou_dif":0,"geounit":"Nepal","gu_a3":"NPL","su_dif":0,"subunit":"Nepal","su_a3":"NPL","brk_diff":0,"name":"Nepal","name_long":"Nepal","brk_a3":"NPL","brk_name":"Nepal","brk_group":null,"abbrev":"Nepal","postal":"NP","formal_en":"Nepal","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nepal","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":12,"pop_est":28563377,"gdp_md_est":31080,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"NP","iso_a3":"NPL","iso_n3":"524","un_a3":"524","wb_a2":"NP","wb_a3":"NPL","woe_id":-99,"adm0_a3_is":"NPL","adm0_a3_us":"NPL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1088,-543]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Nauru","sov_a3":"NRU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nauru","adm0_a3":"NRU","geou_dif":0,"geounit":"Nauru","gu_a3":"NRU","su_dif":0,"subunit":"Nauru","su_a3":"NRU","brk_diff":0,"name":"Nauru","name_long":"Nauru","brk_a3":"NRU","brk_name":"Nauru","brk_group":null,"abbrev":"Nauru","postal":"NR","formal_en":"Republic of Nauru","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nauru","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":6,"mapcolor13":9,"pop_est":14019,"gdp_md_est":60,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NR","iso_a3":"NRU","iso_n3":"520","un_a3":"520","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NRU","adm0_a3_us":"NRU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[1430]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Country","admin":"New Zealand","adm0_a3":"NZL","geou_dif":0,"geounit":"New Zealand","gu_a3":"NZL","su_dif":0,"subunit":"New Zealand","su_a3":"NZL","brk_diff":0,"name":"New Zealand","name_long":"New Zealand","brk_a3":"NZL","brk_name":"New Zealand","brk_group":null,"abbrev":"N.Z.","postal":"NZ","formal_en":"New Zealand","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"New Zealand","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":4213418,"gdp_md_est":116700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NZ","iso_a3":"NZL","iso_n3":"554","un_a3":"554","wb_a2":"NZ","wb_a3":"NZL","woe_id":-99,"adm0_a3_is":"NZL","adm0_a3_us":"NZL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1431]],[[1432]],[[1433]],[[1434]],[[1435]],[[1436]],[[1437]],[[1438]],[[1439]],[[1440]],[[1441]],[[1442]],[[1443]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Oman","sov_a3":"OMN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Oman","adm0_a3":"OMN","geou_dif":0,"geounit":"Oman","gu_a3":"OMN","su_dif":0,"subunit":"Oman","su_a3":"OMN","brk_diff":0,"name":"Oman","name_long":"Oman","brk_a3":"OMN","brk_name":"Oman","brk_group":null,"abbrev":"Oman","postal":"OM","formal_en":"Sultanate of Oman","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Oman","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":3418085,"gdp_md_est":66980,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"OM","iso_a3":"OMN","iso_n3":"512","un_a3":"512","wb_a2":"OM","wb_a3":"OMN","woe_id":-99,"adm0_a3_is":"OMN","adm0_a3_us":"OMN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1444]],[[1445,1446,1447,-32]],[[-36]],[[-35,1448]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Pakistan","sov_a3":"PAK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Pakistan","adm0_a3":"PAK","geou_dif":0,"geounit":"Pakistan","gu_a3":"PAK","su_dif":0,"subunit":"Pakistan","su_a3":"PAK","brk_diff":0,"name":"Pakistan","name_long":"Pakistan","brk_a3":"PAK","brk_name":"Pakistan","brk_group":null,"abbrev":"Pak.","postal":"PK","formal_en":"Islamic Republic of Pakistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Pakistan","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":11,"pop_est":176242949,"gdp_md_est":427300,"pop_year":-99,"lastcensus":1998,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PK","iso_a3":"PAK","iso_n3":"586","un_a3":"586","wb_a2":"PK","wb_a3":"PAK","woe_id":-99,"adm0_a3_is":"PAK","adm0_a3_us":"PAK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1175,-1091,1449,-1106,-3,-557]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Panama","sov_a3":"PAN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Panama","adm0_a3":"PAN","geou_dif":0,"geounit":"Panama","gu_a3":"PAN","su_dif":0,"subunit":"Panama","su_a3":"PAN","brk_diff":0,"name":"Panama","name_long":"Panama","brk_a3":"PAN","brk_name":"Panama","brk_group":null,"abbrev":"Pan.","postal":"PA","formal_en":"Republic of Panama","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Panama","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":6,"mapcolor13":3,"pop_est":3360474,"gdp_md_est":38830,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PA","iso_a3":"PAN","iso_n3":"591","un_a3":"591","wb_a2":"PA","wb_a3":"PAN","woe_id":-99,"adm0_a3_is":"PAN","adm0_a3_us":"PAN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1450]],[[1451]],[[1452]],[[1453]],[[-592,1454,-606,1455]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Pitcairn Islands","adm0_a3":"PCN","geou_dif":0,"geounit":"Pitcairn Islands","gu_a3":"PCN","su_dif":0,"subunit":"Pitcairn Islands","su_a3":"PCN","brk_diff":0,"name":"Pitcairn Is.","name_long":"Pitcairn Islands","brk_a3":"PCN","brk_name":"Pitcairn Is.","brk_group":null,"abbrev":"Pit. Is.","postal":"PN","formal_en":"Pitcairn, Henderson, Ducie and Oeno Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Pitcairn Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":48,"gdp_md_est":0.72,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"PN","iso_a3":"PCN","iso_n3":"612","un_a3":"612","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"PCN","adm0_a3_us":"PCN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":12,"long_len":16,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[1456]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Peru","sov_a3":"PER","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Peru","adm0_a3":"PER","geou_dif":0,"geounit":"Peru","gu_a3":"PER","su_dif":0,"subunit":"Peru","su_a3":"PER","brk_diff":0,"name":"Peru","name_long":"Peru","brk_a3":"PER","brk_name":"Peru","brk_group":null,"abbrev":"Peru","postal":"PE","formal_en":"Republic of Peru","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Peru","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":11,"pop_est":29546963,"gdp_md_est":247300,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PE","iso_a3":"PER","iso_n3":"604","un_a3":"604","wb_a2":"PE","wb_a3":"PER","woe_id":-99,"adm0_a3_is":"PER","adm0_a3_us":"PER","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-318,-295,-519,1457,-674,-589]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Philippines","sov_a3":"PHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Philippines","adm0_a3":"PHL","geou_dif":0,"geounit":"Philippines","gu_a3":"PHL","su_dif":0,"subunit":"Philippines","su_a3":"PHL","brk_diff":0,"name":"Philippines","name_long":"Philippines","brk_a3":"PHL","brk_name":"Philippines","brk_group":null,"abbrev":"Phil.","postal":"PH","formal_en":"Republic of the Philippines","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Philippines","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":2,"mapcolor13":8,"pop_est":97976603,"gdp_md_est":317500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PH","iso_a3":"PHL","iso_n3":"608","un_a3":"608","wb_a2":"PH","wb_a3":"PHL","woe_id":-99,"adm0_a3_is":"PHL","adm0_a3_us":"PHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1458]],[[1459]],[[1460]],[[1461]],[[1462]],[[1463]],[[1464]],[[1465]],[[1466]],[[1467]],[[1468]],[[1469]],[[1470]],[[1471]],[[1472]],[[1473]],[[1474]],[[1475]],[[1476]],[[1477]],[[1478]],[[1479]],[[1480]],[[1481]],[[1482]],[[1483]],[[1484]],[[1485]],[[1486]],[[1487]],[[1488]],[[1489]],[[1490]],[[1491]],[[1492]],[[1493]],[[1494]],[[1495]],[[1496]],[[1497]],[[1498]],[[1499]],[[1500]],[[1501]],[[1502]],[[1503]],[[1504]],[[1505]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Palau","sov_a3":"PLW","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Palau","adm0_a3":"PLW","geou_dif":0,"geounit":"Palau","gu_a3":"PLW","su_dif":0,"subunit":"Palau","su_a3":"PLW","brk_diff":0,"name":"Palau","name_long":"Palau","brk_a3":"PLW","brk_name":"Palau","brk_group":null,"abbrev":"Palau","postal":"PW","formal_en":"Republic of Palau","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Palau","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":1,"mapcolor13":12,"pop_est":20796,"gdp_md_est":164,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PW","iso_a3":"PLW","iso_n3":"585","un_a3":"585","wb_a2":"PW","wb_a3":"PLW","woe_id":-99,"adm0_a3_is":"PLW","adm0_a3_us":"PLW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1506]],[[1507]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Papua New Guinea","sov_a3":"PNG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Papua New Guinea","adm0_a3":"PNG","geou_dif":0,"geounit":"Papua New Guinea","gu_a3":"PNG","su_dif":1,"subunit":"Papua New Guinea","su_a3":"PN1","brk_diff":0,"name":"Papua New Guinea","name_long":"Papua New Guinea","brk_a3":"PN1","brk_name":"Papua New Guinea","brk_group":null,"abbrev":"P.N.G.","postal":"PG","formal_en":"Independent State of Papua New Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Papua New Guinea","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":3,"mapcolor13":1,"pop_est":6057263,"gdp_md_est":13210,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PG","iso_a3":"PNG","iso_n3":"598","un_a3":"598","wb_a2":"PG","wb_a3":"PNG","woe_id":-99,"adm0_a3_is":"PNG","adm0_a3_us":"PNG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":16,"long_len":16,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1508]],[[1509]],[[1510]],[[1511]],[[1512]],[[1513]],[[1514]],[[1515]],[[1516]],[[1517]],[[1518]],[[1519]],[[1520]],[[1521]],[[1522]],[[1523]],[[1524]],[[1525]],[[1526]],[[1527]],[[-1023,1528,1529]],[[1530]],[[1531]],[[1532]],[[1533]],[[1534]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Poland","sov_a3":"POL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Poland","adm0_a3":"POL","geou_dif":0,"geounit":"Poland","gu_a3":"POL","su_dif":0,"subunit":"Poland","su_a3":"POL","brk_diff":0,"name":"Poland","name_long":"Poland","brk_a3":"POL","brk_name":"Poland","brk_group":null,"abbrev":"Pol.","postal":"PL","formal_en":"Republic of Poland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Poland","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":1,"mapcolor13":2,"pop_est":38482919,"gdp_md_est":667900,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"PL","iso_a3":"POL","iso_n3":"616","un_a3":"616","wb_a2":"PL","wb_a3":"POL","woe_id":-99,"adm0_a3_is":"POL","adm0_a3_us":"POL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1535,-1261,-284,1536,1537,-623,-632,1538,-627,1539]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Puerto Rico","adm0_a3":"PRI","geou_dif":0,"geounit":"Puerto Rico","gu_a3":"PRI","su_dif":0,"subunit":"Puerto Rico","su_a3":"PRI","brk_diff":0,"name":"Puerto Rico","name_long":"Puerto Rico","brk_a3":"PRI","brk_name":"Puerto Rico","brk_group":null,"abbrev":"P.R.","postal":"PR","formal_en":"Commonwealth of Puerto Rico","formal_fr":null,"note_adm0":"Commonwealth of U.S.A.","note_brk":null,"name_sort":"Puerto Rico","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":3971020,"gdp_md_est":70230,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"PR","iso_a3":"PRI","iso_n3":"630","un_a3":"630","wb_a2":"PR","wb_a3":"PRI","woe_id":-99,"adm0_a3_is":"PRI","adm0_a3_us":"PRI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[1540]],[[1541]],[[1542]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"North Korea","sov_a3":"PRK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"North Korea","adm0_a3":"PRK","geou_dif":0,"geounit":"North Korea","gu_a3":"PRK","su_dif":0,"subunit":"North Korea","su_a3":"PRK","brk_diff":0,"name":"Dem. Rep. Korea","name_long":"Dem. Rep. Korea","brk_a3":"PRK","brk_name":"Dem. Rep. Korea","brk_group":null,"abbrev":"N.K.","postal":"KP","formal_en":"Democratic People's Republic of Korea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Korea, Dem. Rep.","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":9,"pop_est":22665345,"gdp_md_est":40000,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KP","iso_a3":"PRK","iso_n3":"408","un_a3":"408","wb_a2":"KP","wb_a3":"PRK","woe_id":-99,"adm0_a3_is":"PRK","adm0_a3_us":"PRK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":15,"long_len":15,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1543]],[[1544,1545,-1233,1546,-532]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Portugal","sov_a3":"PRT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Portugal","adm0_a3":"PRT","geou_dif":0,"geounit":"Portugal","gu_a3":"PRT","su_dif":1,"subunit":"Portugal","su_a3":"PR1","brk_diff":0,"name":"Portugal","name_long":"Portugal","brk_a3":"PR1","brk_name":"Portugal","brk_group":null,"abbrev":"Port.","postal":"P","formal_en":"Portuguese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Portugal","name_alt":null,"mapcolor7":1,"mapcolor8":7,"mapcolor9":1,"mapcolor13":4,"pop_est":10707924,"gdp_md_est":208627,"pop_year":-99,"lastcensus":2011,"gdp_year":0,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"PT","iso_a3":"PRT","iso_n3":"620","un_a3":"620","wb_a2":"PT","wb_a3":"PRT","woe_id":-99,"adm0_a3_is":"PRT","adm0_a3_us":"PRT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1547]],[[1548]],[[1549]],[[1550]],[[1551]],[[1552]],[[1553]],[[1554]],[[1555,-701]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Paraguay","sov_a3":"PRY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Paraguay","adm0_a3":"PRY","geou_dif":0,"geounit":"Paraguay","gu_a3":"PRY","su_dif":0,"subunit":"Paraguay","su_a3":"PRY","brk_diff":0,"name":"Paraguay","name_long":"Paraguay","brk_a3":"PRY","brk_name":"Paraguay","brk_group":null,"abbrev":"Para.","postal":"PY","formal_en":"Republic of Paraguay","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Paraguay","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":2,"pop_est":6995655,"gdp_md_est":28890,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PY","iso_a3":"PRY","iso_n3":"600","un_a3":"600","wb_a2":"PY","wb_a3":"PRY","woe_id":-99,"adm0_a3_is":"PRY","adm0_a3_us":"PRY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-317,-41,-293]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Israel","sov_a3":"ISR","adm0_dif":1,"level":2,"type":"Disputed","admin":"Palestine","adm0_a3":"PSX","geou_dif":0,"geounit":"Palestine","gu_a3":"PSX","su_dif":0,"subunit":"Palestine","su_a3":"PSX","brk_diff":0,"name":"Palestine","name_long":"Palestine","brk_a3":"PSX","brk_name":"Palestine","brk_group":null,"abbrev":"Pal.","postal":"PAL","formal_en":"West Bank and Gaza","formal_fr":null,"note_adm0":"Partial self-admin.","note_brk":"Partial self-admin.","name_sort":"Palestine (West Bank and Gaza)","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":8,"pop_est":4119083,"gdp_md_est":11950.77,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PS","iso_a3":"PSE","iso_n3":"275","un_a3":"275","wb_a2":"GZ","wb_a3":"WBG","woe_id":-99,"adm0_a3_is":"PSE","adm0_a3_us":"PSX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[-676,1556,-1121]],[[-1118,-1139]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"French Polynesia","adm0_a3":"PYF","geou_dif":0,"geounit":"French Polynesia","gu_a3":"PYF","su_dif":0,"subunit":"French Polynesia","su_a3":"PYF","brk_diff":0,"name":"Fr. Polynesia","name_long":"French Polynesia","brk_a3":"PYF","brk_name":"Fr. Polynesia","brk_group":null,"abbrev":"Fr. Poly.","postal":"PF","formal_en":"French Polynesia","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"French Polynesia","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":287032,"gdp_md_est":4718,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"PF","iso_a3":"PYF","iso_n3":"258","un_a3":"258","wb_a2":"PF","wb_a3":"PYF","woe_id":-99,"adm0_a3_is":"PYF","adm0_a3_us":"PYF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":13,"long_len":16,"abbrev_len":9,"tiny":2,"homepart":-99},"arcs":[[[1557]],[[1558]],[[1559]],[[1560]],[[1561]],[[1562]],[[1563]],[[1564]],[[1565]],[[1566]],[[1567]],[[1568]],[[1569]],[[1570]],[[1571]],[[1572]],[[1573]],[[1574]],[[1575]],[[1576]],[[1577]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Qatar","sov_a3":"QAT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Qatar","adm0_a3":"QAT","geou_dif":0,"geounit":"Qatar","gu_a3":"QAT","su_dif":0,"subunit":"Qatar","su_a3":"QAT","brk_diff":0,"name":"Qatar","name_long":"Qatar","brk_a3":"QAT","brk_name":"Qatar","brk_group":null,"abbrev":"Qatar","postal":"QA","formal_en":"State of Qatar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Qatar","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":4,"pop_est":833285,"gdp_md_est":91330,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"QA","iso_a3":"QAT","iso_n3":"634","un_a3":"634","wb_a2":"QA","wb_a3":"QAT","woe_id":-99,"adm0_a3_is":"QAT","adm0_a3_us":"QAT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1578,1579]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Romania","sov_a3":"ROU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Romania","adm0_a3":"ROU","geou_dif":0,"geounit":"Romania","gu_a3":"ROU","su_dif":0,"subunit":"Romania","su_a3":"ROU","brk_diff":0,"name":"Romania","name_long":"Romania","brk_a3":"ROU","brk_name":"Romania","brk_group":null,"abbrev":"Rom.","postal":"RO","formal_en":"Romania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Romania","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":3,"mapcolor13":13,"pop_est":22215421,"gdp_md_est":271400,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RO","iso_a3":"ROU","iso_n3":"642","un_a3":"642","wb_a2":"RO","wb_a3":"ROM","woe_id":-99,"adm0_a3_is":"ROU","adm0_a3_us":"ROU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1580,1581,-259,1582,-927,1583,-1273]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Russia","sov_a3":"RUS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Russia","adm0_a3":"RUS","geou_dif":0,"geounit":"Russia","gu_a3":"RUS","su_dif":0,"subunit":"Russia","su_a3":"RUS","brk_diff":0,"name":"Russia","name_long":"Russian Federation","brk_a3":"RUS","brk_name":"Russia","brk_group":null,"abbrev":"Rus.","postal":"RUS","formal_en":"Russian Federation","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Russian Federation","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":7,"mapcolor13":7,"pop_est":140041247,"gdp_md_est":2266000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RU","iso_a3":"RUS","iso_n3":"643","un_a3":"643","wb_a2":"RU","wb_a3":"RUS","woe_id":-99,"adm0_a3_is":"RUS","adm0_a3_us":"RUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":18,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1584]],[[1585]],[[1586]],[[1587]],[[1588]],[[1589]],[[1590]],[[1591]],[[1592]],[[1593]],[[1594]],[[1595]],[[1596]],[[1597]],[[1598]],[[1599]],[[1600]],[[1601]],[[1602]],[[-1262,-1536,1603,-1259,1604]],[[1605]],[[1606]],[[1607]],[[1608]],[[1609]],[[1610]],[[1611]],[[1612]],[[1613]],[[1614]],[[1615]],[[1616]],[[1617]],[[1618]],[[1619]],[[1620]],[[1621]],[[1622]],[[1623]],[[1624]],[[1625]],[[1626]],[[1627]],[[1628]],[[1629]],[[1630]],[[1631]],[[1632]],[[1633]],[[1634]],[[1635]],[[1636]],[[1637]],[[1638]],[[1639]],[[1640]],[[1641]],[[1642]],[[1643]],[[1644]],[[1645]],[[1646]],[[1647]],[[1648]],[[1649]],[[1650]],[[1651]],[[-1545,-563,-1331,-561,-1183,1652,-224,-804,1653,1654,-282,-1265,-706,1655,-721,-1417,1656]],[[1657]],[[1658]],[[1659]],[[1660]],[[1661]],[[1662]],[[1663]],[[1664]],[[1665]],[[1666]],[[1667]],[[1668]],[[1669]],[[1670]],[[1671]],[[1672]],[[1673]],[[1674]],[[1675]],[[1676]],[[1677]],[[1678]],[[1679]],[[1680]],[[1681]],[[1682]],[[1683]],[[1684]],[[1685]],[[1686]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Rwanda","sov_a3":"RWA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Rwanda","adm0_a3":"RWA","geou_dif":0,"geounit":"Rwanda","gu_a3":"RWA","su_dif":0,"subunit":"Rwanda","su_a3":"RWA","brk_diff":0,"name":"Rwanda","name_long":"Rwanda","brk_a3":"RWA","brk_name":"Rwanda","brk_group":null,"abbrev":"Rwa.","postal":"RW","formal_en":"Republic of Rwanda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Rwanda","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":3,"mapcolor13":10,"pop_est":10473282,"gdp_md_est":9706,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"RW","iso_a3":"RWA","iso_n3":"646","un_a3":"646","wb_a2":"RW","wb_a3":"RWA","woe_id":-99,"adm0_a3_is":"RWA","adm0_a3_us":"RWA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1687,-227,-579,1688]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":7,"sovereignt":"Western Sahara","sov_a3":"SAH","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Western Sahara","adm0_a3":"SAH","geou_dif":0,"geounit":"Western Sahara","gu_a3":"SAH","su_dif":0,"subunit":"Western Sahara","su_a3":"SAH","brk_diff":1,"name":"W. Sahara","name_long":"Western Sahara","brk_a3":"B28","brk_name":"W. Sahara","brk_group":null,"abbrev":"W. Sah.","postal":"WS","formal_en":"Sahrawi Arab Democratic Republic","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Morocco","name_sort":"Western Sahara","name_alt":null,"mapcolor7":4,"mapcolor8":7,"mapcolor9":4,"mapcolor13":4,"pop_est":-99,"gdp_md_est":-99,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"EH","iso_a3":"ESH","iso_n3":"732","un_a3":"732","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"MAR","adm0_a3_us":"SAH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":9,"long_len":14,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-1351,1689,-1270,-663]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Saudi Arabia","sov_a3":"SAU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saudi Arabia","adm0_a3":"SAU","geou_dif":0,"geounit":"Saudi Arabia","gu_a3":"SAU","su_dif":0,"subunit":"Saudi Arabia","su_a3":"SAU","brk_diff":0,"name":"Saudi Arabia","name_long":"Saudi Arabia","brk_a3":"SAU","brk_name":"Saudi Arabia","brk_group":null,"abbrev":"Saud.","postal":"SA","formal_en":"Kingdom of Saudi Arabia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Saudi Arabia","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":6,"mapcolor13":7,"pop_est":28686633,"gdp_md_est":576500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SA","iso_a3":"SAU","iso_n3":"682","un_a3":"682","wb_a2":"SA","wb_a3":"SAU","woe_id":-99,"adm0_a3_is":"SAU","adm0_a3_us":"SAU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1690]],[[1691]],[[1692]],[[-1238,1693,-1579,1694,-33,-1448,1695,1696,-1137,-1112]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sudan","sov_a3":"SDN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sudan","adm0_a3":"SDN","geou_dif":0,"geounit":"Sudan","gu_a3":"SDN","su_dif":0,"subunit":"Sudan","su_a3":"SDN","brk_diff":0,"name":"Sudan","name_long":"Sudan","brk_a3":"SDN","brk_name":"Sudan","brk_group":null,"abbrev":"Sudan","postal":"SD","formal_en":"Republic of the Sudan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sudan","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":4,"mapcolor13":1,"pop_est":25946220,"gdp_md_est":88080,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SD","iso_a3":"SDN","iso_n3":"729","un_a3":"729","wb_a2":"SD","wb_a3":"SDN","woe_id":-99,"adm0_a3_is":"SDN","adm0_a3_us":"SDN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1697,-686,-713,1698,-332,1699,-1249,-679]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"South Sudan","sov_a3":"SDS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Sudan","adm0_a3":"SDS","geou_dif":0,"geounit":"South Sudan","gu_a3":"SDS","su_dif":0,"subunit":"South Sudan","su_a3":"SDS","brk_diff":0,"name":"S. Sudan","name_long":"South Sudan","brk_a3":"SDS","brk_name":"S. Sudan","brk_group":null,"abbrev":"S. Sud.","postal":"SS","formal_en":"Republic of South Sudan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"South Sudan","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":3,"mapcolor13":5,"pop_est":10625176,"gdp_md_est":13227,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SS","iso_a3":"SSD","iso_n3":"728","un_a3":"728","wb_a2":"SS","wb_a3":"SSD","woe_id":-99,"adm0_a3_is":"SSD","adm0_a3_us":"SDS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":11,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-712,-1189,1700,-577,-333,-1699]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Senegal","sov_a3":"SEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Senegal","adm0_a3":"SEN","geou_dif":0,"geounit":"Senegal","gu_a3":"SEN","su_dif":0,"subunit":"Senegal","su_a3":"SEN","brk_diff":0,"name":"Senegal","name_long":"Senegal","brk_a3":"SEN","brk_name":"Senegal","brk_group":null,"abbrev":"Sen.","postal":"SN","formal_en":"Republic of Senegal","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Senegal","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":5,"mapcolor13":5,"pop_est":13711597,"gdp_md_est":21980,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SN","iso_a3":"SEN","iso_n3":"686","un_a3":"686","wb_a2":"SN","wb_a3":"SEN","woe_id":-99,"adm0_a3_is":"SEN","adm0_a3_us":"SEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1305,-814,-824,1701,-816,1702,-1349]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Singapore","sov_a3":"SGP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Singapore","adm0_a3":"SGP","geou_dif":0,"geounit":"Singapore","gu_a3":"SGP","su_dif":0,"subunit":"Singapore","su_a3":"SGP","brk_diff":0,"name":"Singapore","name_long":"Singapore","brk_a3":"SGP","brk_name":"Singapore","brk_group":null,"abbrev":"Sing.","postal":"SG","formal_en":"Republic of Singapore","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Singapore","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":4657542,"gdp_md_est":237300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SG","iso_a3":"SGP","iso_n3":"702","un_a3":"702","wb_a2":"SG","wb_a3":"SGP","woe_id":-99,"adm0_a3_is":"SGP","adm0_a3_us":"SGP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[1703]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"South Georgia and South Sandwich Islands","adm0_a3":"SGS","geou_dif":0,"geounit":"South Georgia and South Sandwich Islands","gu_a3":"SGS","su_dif":0,"subunit":"South Georgia and South Sandwich Islands","su_a3":"SGS","brk_diff":0,"name":"S. Geo. and S. Sandw. Is.","name_long":"South Georgia and South Sandwich Islands","brk_a3":"SGS","brk_name":"S. Geo. and S. Sandw. Is.","brk_group":null,"abbrev":"S.G. S.S. Is.","postal":"GS","formal_en":"South Georgia and South Sandwich Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"South Georgia and the Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":30,"gdp_md_est":0.3,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GS","iso_a3":"SGS","iso_n3":"239","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SGS","adm0_a3_us":"SGS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Antarctica","name_len":25,"long_len":40,"abbrev_len":13,"tiny":3,"homepart":-99},"arcs":[[[1704]],[[1705]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Helena","adm0_a3":"SHN","geou_dif":0,"geounit":"Saint Helena","gu_a3":"SHN","su_dif":0,"subunit":"Saint Helena","su_a3":"SHN","brk_diff":0,"name":"Saint Helena","name_long":"Saint Helena","brk_a3":"SHN","brk_name":"Saint Helena","brk_group":null,"abbrev":"St.H.","postal":"SH","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"St. Helena","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":7637,"gdp_md_est":18,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SH","iso_a3":"SHN","iso_n3":"654","un_a3":"654","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SHN","adm0_a3_us":"SHN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":-99},"arcs":[[[1706]],[[1707]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Solomon Islands","sov_a3":"SLB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Solomon Islands","adm0_a3":"SLB","geou_dif":0,"geounit":"Solomon Islands","gu_a3":"SLB","su_dif":0,"subunit":"Solomon Islands","su_a3":"SLB","brk_diff":0,"name":"Solomon Is.","name_long":"Solomon Islands","brk_a3":"SLB","brk_name":"Solomon Is.","brk_group":null,"abbrev":"S. Is.","postal":"SB","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Solomon Islands","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":595613,"gdp_md_est":1078,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SB","iso_a3":"SLB","iso_n3":"090","un_a3":"090","wb_a2":"SB","wb_a3":"SLB","woe_id":-99,"adm0_a3_is":"SLB","adm0_a3_us":"SLB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":11,"long_len":15,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1708]],[[1709]],[[1710]],[[1711]],[[1712]],[[1713]],[[1714]],[[1715]],[[1716]],[[1717]],[[1718]],[[1719]],[[1720]],[[1721]],[[1722]],[[1723]],[[1724]],[[1725]],[[1726]],[[1727]],[[1728]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Sierra Leone","sov_a3":"SLE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sierra Leone","adm0_a3":"SLE","geou_dif":0,"geounit":"Sierra Leone","gu_a3":"SLE","su_dif":0,"subunit":"Sierra Leone","su_a3":"SLE","brk_diff":0,"name":"Sierra Leone","name_long":"Sierra Leone","brk_a3":"SLE","brk_name":"Sierra Leone","brk_group":null,"abbrev":"S.L.","postal":"SL","formal_en":"Republic of Sierra Leone","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sierra Leone","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":7,"pop_est":6440053,"gdp_md_est":4285,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SL","iso_a3":"SLE","iso_n3":"694","un_a3":"694","wb_a2":"SL","wb_a3":"SLE","woe_id":-99,"adm0_a3_is":"SLE","adm0_a3_us":"SLE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1729]],[[-1248,1730,-811]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"El Salvador","sov_a3":"SLV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"El Salvador","adm0_a3":"SLV","geou_dif":0,"geounit":"El Salvador","gu_a3":"SLV","su_dif":0,"subunit":"El Salvador","su_a3":"SLV","brk_diff":0,"name":"El Salvador","name_long":"El Salvador","brk_a3":"SLV","brk_name":"El Salvador","brk_group":null,"abbrev":"El. S.","postal":"SV","formal_en":"Republic of El Salvador","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"El Salvador","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":6,"mapcolor13":8,"pop_est":7185218,"gdp_md_est":43630,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SV","iso_a3":"SLV","iso_n3":"222","un_a3":"222","wb_a2":"SV","wb_a3":"SLV","woe_id":-99,"adm0_a3_is":"SLV","adm0_a3_us":"SLV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-902,1731,-889]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"San Marino","sov_a3":"SMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"San Marino","adm0_a3":"SMR","geou_dif":0,"geounit":"San Marino","gu_a3":"SMR","su_dif":0,"subunit":"San Marino","su_a3":"SMR","brk_diff":0,"name":"San Marino","name_long":"San Marino","brk_a3":"SMR","brk_name":"San Marino","brk_group":null,"abbrev":"S.M.","postal":"RSM","formal_en":"Republic of San Marino","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"San Marino","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":1,"mapcolor13":6,"pop_est":30324,"gdp_md_est":1662,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SM","iso_a3":"SMR","iso_n3":"674","un_a3":"674","wb_a2":"SM","wb_a3":"SMR","woe_id":-99,"adm0_a3_is":"SMR","adm0_a3_us":"SMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[-1134]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Somaliland","sov_a3":"SOL","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Somaliland","adm0_a3":"SOL","geou_dif":0,"geounit":"Somaliland","gu_a3":"SOL","su_dif":0,"subunit":"Somaliland","su_a3":"SOL","brk_diff":1,"name":"Somaliland","name_long":"Somaliland","brk_a3":"B30","brk_name":"Somaliland","brk_group":null,"abbrev":"Solnd.","postal":"SL","formal_en":"Republic of Somaliland","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Somalia","name_sort":"Somaliland","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":5,"mapcolor13":2,"pop_est":3500000,"gdp_md_est":12250,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SOM","adm0_a3_us":"SOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[1732,-709,-639,1733]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Somalia","sov_a3":"SOM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Somalia","adm0_a3":"SOM","geou_dif":0,"geounit":"Somalia","gu_a3":"SOM","su_dif":0,"subunit":"Somalia","su_a3":"SOM","brk_diff":0,"name":"Somalia","name_long":"Somalia","brk_a3":"SOM","brk_name":"Somalia","brk_group":null,"abbrev":"Som.","postal":"SO","formal_en":"Federal Republic of Somalia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Somalia","name_alt":null,"mapcolor7":2,"mapcolor8":8,"mapcolor9":6,"mapcolor13":7,"pop_est":9832017,"gdp_md_est":5524,"pop_year":-99,"lastcensus":1987,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SO","iso_a3":"SOM","iso_n3":"706","un_a3":"706","wb_a2":"SO","wb_a3":"SOM","woe_id":-99,"adm0_a3_is":"SOM","adm0_a3_us":"SOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1185,-710,-1733,1734]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Pierre and Miquelon","adm0_a3":"SPM","geou_dif":0,"geounit":"Saint Pierre and Miquelon","gu_a3":"SPM","su_dif":0,"subunit":"Saint Pierre and Miquelon","su_a3":"SPM","brk_diff":0,"name":"St. Pierre and Miquelon","name_long":"Saint Pierre and Miquelon","brk_a3":"SPM","brk_name":"St. Pierre and Miquelon","brk_group":null,"abbrev":"St. P.M.","postal":"PM","formal_en":"Saint Pierre and Miquelon","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St. Pierre and Miquelon","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":7051,"gdp_md_est":48.3,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PM","iso_a3":"SPM","iso_n3":"666","un_a3":"666","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SPM","adm0_a3_us":"SPM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":23,"long_len":25,"abbrev_len":8,"tiny":3,"homepart":-99},"arcs":[[[1735]],[[1736]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Republic of Serbia","sov_a3":"SRB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Republic of Serbia","adm0_a3":"SRB","geou_dif":0,"geounit":"Republic of Serbia","gu_a3":"SRB","su_dif":0,"subunit":"Republic of Serbia","su_a3":"SRB","brk_diff":0,"name":"Serbia","name_long":"Serbia","brk_a3":"SRB","brk_name":"Serbia","brk_group":null,"abbrev":"Serb.","postal":"RS","formal_en":"Republic of Serbia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Serbia","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":2,"mapcolor13":10,"pop_est":7379339,"gdp_md_est":80340,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RS","iso_a3":"SRB","iso_n3":"688","un_a3":"688","wb_a2":"YF","wb_a3":"SRB","woe_id":-99,"adm0_a3_is":"SRB","adm0_a3_us":"SRB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1583,-258,-1303,-1236,-1329,-276,-919,-928]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Sao Tome and Principe","sov_a3":"STP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sao Tome and Principe","adm0_a3":"STP","geou_dif":0,"geounit":"Sao Tome and Principe","gu_a3":"STP","su_dif":0,"subunit":"Sao Tome and Principe","su_a3":"STP","brk_diff":0,"name":"São Tomé and Principe","name_long":"São Tomé and Principe","brk_a3":"STP","brk_name":"Sao Tome and Principe","brk_group":null,"abbrev":"S.T.P.","postal":"ST","formal_en":"Democratic Republic of São Tomé and Principe","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"São Tomé and Principe","name_alt":null,"mapcolor7":1,"mapcolor8":6,"mapcolor9":1,"mapcolor13":7,"pop_est":212679,"gdp_md_est":276.5,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ST","iso_a3":"STP","iso_n3":"678","un_a3":"678","wb_a2":"ST","wb_a3":"STP","woe_id":-99,"adm0_a3_is":"STP","adm0_a3_us":"STP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":21,"long_len":21,"abbrev_len":6,"tiny":3,"homepart":1},"arcs":[[[1737]],[[1738]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Suriname","sov_a3":"SUR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Suriname","adm0_a3":"SUR","geou_dif":0,"geounit":"Suriname","gu_a3":"SUR","su_dif":0,"subunit":"Suriname","su_a3":"SUR","brk_diff":0,"name":"Suriname","name_long":"Suriname","brk_a3":"SUR","brk_name":"Suriname","brk_group":null,"abbrev":"Sur.","postal":"SR","formal_en":"Republic of Suriname","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Suriname","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":7,"mapcolor13":6,"pop_est":481267,"gdp_md_est":4254,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SR","iso_a3":"SUR","iso_n3":"740","un_a3":"740","wb_a2":"SR","wb_a3":"SUR","woe_id":-99,"adm0_a3_is":"SUR","adm0_a3_us":"SUR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-752,-313,-893,1739]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Slovakia","sov_a3":"SVK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Slovakia","adm0_a3":"SVK","geou_dif":0,"geounit":"Slovakia","gu_a3":"SVK","su_dif":0,"subunit":"Slovakia","su_a3":"SVK","brk_diff":0,"name":"Slovakia","name_long":"Slovakia","brk_a3":"SVK","brk_name":"Slovakia","brk_group":null,"abbrev":"Svk.","postal":"SK","formal_en":"Slovak Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Slovak Republic","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":4,"mapcolor13":9,"pop_est":5463046,"gdp_md_est":119500,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SK","iso_a3":"SVK","iso_n3":"703","un_a3":"703","wb_a2":"SK","wb_a3":"SVK","woe_id":-99,"adm0_a3_is":"SVK","adm0_a3_us":"SVK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1740,-930,-210,-624,-1538]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Slovenia","sov_a3":"SVN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Slovenia","adm0_a3":"SVN","geou_dif":0,"geounit":"Slovenia","gu_a3":"SVN","su_dif":0,"subunit":"Slovenia","su_a3":"SVN","brk_diff":0,"name":"Slovenia","name_long":"Slovenia","brk_a3":"SVN","brk_name":"Slovenia","brk_group":null,"abbrev":"Slo.","postal":"SLO","formal_en":"Republic of Slovenia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Slovenia","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":2,"mapcolor13":12,"pop_est":2005692,"gdp_md_est":59340,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SI","iso_a3":"SVN","iso_n3":"705","un_a3":"705","wb_a2":"SI","wb_a3":"SVN","woe_id":-99,"adm0_a3_is":"SVN","adm0_a3_us":"SVN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-921,1741,-1132,-212,-929]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sweden","sov_a3":"SWE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sweden","adm0_a3":"SWE","geou_dif":0,"geounit":"Sweden","gu_a3":"SWE","su_dif":0,"subunit":"Sweden","su_a3":"SWE","brk_diff":0,"name":"Sweden","name_long":"Sweden","brk_a3":"SWE","brk_name":"Sweden","brk_group":null,"abbrev":"Swe.","postal":"S","formal_en":"Kingdom of Sweden","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sweden","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":2,"mapcolor13":4,"pop_est":9059651,"gdp_md_est":344300,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SE","iso_a3":"SWE","iso_n3":"752","un_a3":"752","wb_a2":"SE","wb_a3":"SWE","woe_id":-99,"adm0_a3_is":"SWE","adm0_a3_us":"SWE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1742]],[[1743]],[[1744]],[[1745]],[[1746]],[[1747,-1418,-723]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Swaziland","sov_a3":"SWZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Swaziland","adm0_a3":"SWZ","geou_dif":0,"geounit":"Swaziland","gu_a3":"SWZ","su_dif":0,"subunit":"Swaziland","su_a3":"SWZ","brk_diff":0,"name":"Swaziland","name_long":"Swaziland","brk_a3":"SWZ","brk_name":"Swaziland","brk_group":null,"abbrev":"Swz.","postal":"SW","formal_en":"Kingdom of Swaziland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Swaziland","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":1123913,"gdp_md_est":5702,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SZ","iso_a3":"SWZ","iso_n3":"748","un_a3":"748","wb_a2":"SZ","wb_a3":"SWZ","woe_id":-99,"adm0_a3_is":"SWZ","adm0_a3_us":"SWZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1339,1748]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Sint Maarten","adm0_a3":"SXM","geou_dif":0,"geounit":"Sint Maarten","gu_a3":"SXM","su_dif":0,"subunit":"Sint Maarten","su_a3":"SXM","brk_diff":0,"name":"Sint Maarten","name_long":"Sint Maarten","brk_a3":"SXM","brk_name":"Sint Maarten","brk_group":null,"abbrev":"St. M.","postal":"SX","formal_en":"Sint Maarten (Dutch part)","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"St. Maarten (Dutch part)","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":37429,"gdp_md_est":400,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SX","iso_a3":"SXM","iso_n3":"534","un_a3":"534","wb_a2":"SX","wb_a3":"SXM","woe_id":-99,"adm0_a3_is":"SXM","adm0_a3_us":"SXM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":12,"long_len":12,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[-1268,1749]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Seychelles","sov_a3":"SYC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Seychelles","adm0_a3":"SYC","geou_dif":0,"geounit":"Seychelles","gu_a3":"SYC","su_dif":0,"subunit":"Seychelles","su_a3":"SYC","brk_diff":0,"name":"Seychelles","name_long":"Seychelles","brk_a3":"SYC","brk_name":"Seychelles","brk_group":null,"abbrev":"Syc.","postal":"SC","formal_en":"Republic of Seychelles","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Seychelles","name_alt":null,"mapcolor7":5,"mapcolor8":8,"mapcolor9":3,"mapcolor13":1,"pop_est":87476,"gdp_md_est":1715,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SC","iso_a3":"SYC","iso_n3":"690","un_a3":"690","wb_a2":"SC","wb_a3":"SYC","woe_id":-99,"adm0_a3_is":"SYC","adm0_a3_us":"SYC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[1750]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Syria","sov_a3":"SYR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Syria","adm0_a3":"SYR","geou_dif":0,"geounit":"Syria","gu_a3":"SYR","su_dif":0,"subunit":"Syria","su_a3":"SYR","brk_diff":0,"name":"Syria","name_long":"Syria","brk_a3":"SYR","brk_name":"Syria","brk_group":null,"abbrev":"Syria","postal":"SYR","formal_en":"Syrian Arab Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Syrian Arab Republic","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":2,"mapcolor13":6,"pop_est":20178485,"gdp_md_est":98830,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SY","iso_a3":"SYR","iso_n3":"760","un_a3":"760","wb_a2":"SY","wb_a3":"SYR","woe_id":-99,"adm0_a3_is":"SYR","adm0_a3_us":"SYR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1114,-1140,-1124,-1246,1751,1752]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Turks and Caicos Islands","adm0_a3":"TCA","geou_dif":0,"geounit":"Turks and Caicos Islands","gu_a3":"TCA","su_dif":0,"subunit":"Turks and Caicos Islands","su_a3":"TCA","brk_diff":0,"name":"Turks and Caicos Is.","name_long":"Turks and Caicos Islands","brk_a3":"TCA","brk_name":"Turks and Caicos Is.","brk_group":null,"abbrev":"T.C. Is.","postal":"TC","formal_en":"Turks and Caicos Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Turks and Caicos Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":22942,"gdp_md_est":216,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TC","iso_a3":"TCA","iso_n3":"796","un_a3":"796","wb_a2":"TC","wb_a3":"TCA","woe_id":-99,"adm0_a3_is":"TCA","adm0_a3_us":"TCA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":20,"long_len":24,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[[1753]],[[1754]],[[1755]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Chad","sov_a3":"TCD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Chad","adm0_a3":"TCD","geou_dif":0,"geounit":"Chad","gu_a3":"TCD","su_dif":0,"subunit":"Chad","su_a3":"TCD","brk_diff":0,"name":"Chad","name_long":"Chad","brk_a3":"TCD","brk_name":"Chad","brk_group":null,"abbrev":"Chad","postal":"TD","formal_en":"Republic of Chad","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Chad","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":8,"mapcolor13":6,"pop_est":10329208,"gdp_md_est":15860,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TD","iso_a3":"TCD","iso_n3":"148","un_a3":"148","wb_a2":"TD","wb_a3":"TCD","woe_id":-99,"adm0_a3_is":"TCD","adm0_a3_us":"TCD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1700,-337,-576,-1380,-1376,-1250]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Togo","sov_a3":"TGO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Togo","adm0_a3":"TGO","geou_dif":0,"geounit":"Togo","gu_a3":"TGO","su_dif":0,"subunit":"Togo","su_a3":"TGO","brk_diff":0,"name":"Togo","name_long":"Togo","brk_a3":"TGO","brk_name":"Togo","brk_group":null,"abbrev":"Togo","postal":"TG","formal_en":"Togolese Republic","formal_fr":"République Togolaise","note_adm0":null,"note_brk":null,"name_sort":"Togo","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":5,"pop_est":6019877,"gdp_md_est":5118,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TG","iso_a3":"TGO","iso_n3":"768","un_a3":"768","wb_a2":"TG","wb_a3":"TGO","woe_id":-99,"adm0_a3_is":"TGO","adm0_a3_us":"TGO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-237,1756,-806,-241]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Thailand","sov_a3":"THA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Thailand","adm0_a3":"THA","geou_dif":0,"geounit":"Thailand","gu_a3":"THA","su_dif":0,"subunit":"Thailand","su_a3":"THA","brk_diff":0,"name":"Thailand","name_long":"Thailand","brk_a3":"THA","brk_name":"Thailand","brk_group":null,"abbrev":"Thai.","postal":"TH","formal_en":"Kingdom of Thailand","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Thailand","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":8,"mapcolor13":1,"pop_est":65905410,"gdp_md_est":547400,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TH","iso_a3":"THA","iso_n3":"764","un_a3":"764","wb_a2":"TH","wb_a3":"THA","woe_id":-99,"adm0_a3_is":"THA","adm0_a3_us":"THA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1757]],[[1758]],[[1759]],[[1760]],[[1761]],[[1762]],[[1763]],[[1764]],[[1765]],[[-1243,-1198,1766,-1363,1767,-1327]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Tajikistan","sov_a3":"TJK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tajikistan","adm0_a3":"TJK","geou_dif":0,"geounit":"Tajikistan","gu_a3":"TJK","su_dif":0,"subunit":"Tajikistan","su_a3":"TJK","brk_diff":0,"name":"Tajikistan","name_long":"Tajikistan","brk_a3":"TJK","brk_name":"Tajikistan","brk_group":null,"abbrev":"Tjk.","postal":"TJ","formal_en":"Republic of Tajikistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tajikistan","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":7349145,"gdp_md_est":13160,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TJ","iso_a3":"TJK","iso_n3":"762","un_a3":"762","wb_a2":"TJ","wb_a3":"TJK","woe_id":-99,"adm0_a3_is":"TJK","adm0_a3_us":"TJK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[-1192]],[[1768]],[[-1190,-558,-8,1769]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Turkmenistan","sov_a3":"TKM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Turkmenistan","adm0_a3":"TKM","geou_dif":0,"geounit":"Turkmenistan","gu_a3":"TKM","su_dif":0,"subunit":"Turkmenistan","su_a3":"TKM","brk_diff":0,"name":"Turkmenistan","name_long":"Turkmenistan","brk_a3":"TKM","brk_name":"Turkmenistan","brk_group":null,"abbrev":"Turkm.","postal":"TM","formal_en":"Turkmenistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Turkmenistan","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":9,"pop_est":4884887,"gdp_md_est":29780,"pop_year":-99,"lastcensus":1995,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TM","iso_a3":"TKM","iso_n3":"795","un_a3":"795","wb_a2":"TM","wb_a3":"TKM","woe_id":-99,"adm0_a3_is":"TKM","adm0_a3_us":"TKM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":12,"long_len":12,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1770]],[[-6,-1104,1771,-1181,1772]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"East Timor","sov_a3":"TLS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"East Timor","adm0_a3":"TLS","geou_dif":0,"geounit":"East Timor","gu_a3":"TLS","su_dif":0,"subunit":"East Timor","su_a3":"TLS","brk_diff":0,"name":"Timor-Leste","name_long":"Timor-Leste","brk_a3":"TLS","brk_name":"Timor-Leste","brk_group":null,"abbrev":"T.L.","postal":"TL","formal_en":"Democratic Republic of Timor-Leste","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Timor-Leste","name_alt":"East Timor","mapcolor7":2,"mapcolor8":2,"mapcolor9":4,"mapcolor13":3,"pop_est":1131612,"gdp_md_est":2520,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TL","iso_a3":"TLS","iso_n3":"626","un_a3":"626","wb_a2":"TP","wb_a3":"TMP","woe_id":-99,"adm0_a3_is":"TLS","adm0_a3_us":"TLS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1773,-936]],[[-938,1774]],[[1775]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Tonga","sov_a3":"TON","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tonga","adm0_a3":"TON","geou_dif":0,"geounit":"Tonga","gu_a3":"TON","su_dif":0,"subunit":"Tonga","su_a3":"TON","brk_diff":0,"name":"Tonga","name_long":"Tonga","brk_a3":"TON","brk_name":"Tonga","brk_group":null,"abbrev":"Tongo","postal":"TO","formal_en":"Kingdom of Tonga","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tonga","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":1,"mapcolor13":8,"pop_est":120898,"gdp_md_est":549,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TO","iso_a3":"TON","iso_n3":"776","un_a3":"776","wb_a2":"TO","wb_a3":"TON","woe_id":-99,"adm0_a3_is":"TON","adm0_a3_us":"TON","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[[1776]],[[1777]],[[1778]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Trinidad and Tobago","sov_a3":"TTO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Trinidad and Tobago","adm0_a3":"TTO","geou_dif":0,"geounit":"Trinidad and Tobago","gu_a3":"TTO","su_dif":0,"subunit":"Trinidad and Tobago","su_a3":"TTO","brk_diff":0,"name":"Trinidad and Tobago","name_long":"Trinidad and Tobago","brk_a3":"TTO","brk_name":"Trinidad and Tobago","brk_group":null,"abbrev":"Tr.T.","postal":"TT","formal_en":"Republic of Trinidad and Tobago","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Trinidad and Tobago","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":1310000,"gdp_md_est":29010,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TT","iso_a3":"TTO","iso_n3":"780","un_a3":"780","wb_a2":"TT","wb_a3":"TTO","woe_id":-99,"adm0_a3_is":"TTO","adm0_a3_us":"TTO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":19,"long_len":19,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1779]],[[1780]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Tunisia","sov_a3":"TUN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tunisia","adm0_a3":"TUN","geou_dif":0,"geounit":"Tunisia","gu_a3":"TUN","su_dif":0,"subunit":"Tunisia","su_a3":"TUN","brk_diff":0,"name":"Tunisia","name_long":"Tunisia","brk_a3":"TUN","brk_name":"Tunisia","brk_group":null,"abbrev":"Tun.","postal":"TN","formal_en":"Republic of Tunisia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tunisia","name_alt":null,"mapcolor7":4,"mapcolor8":3,"mapcolor9":3,"mapcolor13":2,"pop_est":10486339,"gdp_md_est":81710,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TN","iso_a3":"TUN","iso_n3":"788","un_a3":"788","wb_a2":"TN","wb_a3":"TUN","woe_id":-99,"adm0_a3_is":"TUN","adm0_a3_us":"TUN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1781]],[[1782]],[[-1252,-658,1783]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Turkey","sov_a3":"TUR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Turkey","adm0_a3":"TUR","geou_dif":0,"geounit":"Turkey","gu_a3":"TUR","su_dif":0,"subunit":"Turkey","su_a3":"TUR","brk_diff":0,"name":"Turkey","name_long":"Turkey","brk_a3":"TUR","brk_name":"Turkey","brk_group":null,"abbrev":"Tur.","postal":"TR","formal_en":"Republic of Turkey","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Turkey","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":8,"mapcolor13":4,"pop_est":76805524,"gdp_md_est":902700,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TR","iso_a3":"TUR","iso_n3":"792","un_a3":"792","wb_a2":"TR","wb_a3":"TUR","woe_id":-99,"adm0_a3_is":"TUR","adm0_a3_us":"TUR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1784]],[[-802,-50,-220,-1109,-1115,-1753,1785]],[[1786,-868,-255]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Taiwan","sov_a3":"TWN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Taiwan","adm0_a3":"TWN","geou_dif":0,"geounit":"Taiwan","gu_a3":"TWN","su_dif":0,"subunit":"Taiwan","su_a3":"TWN","brk_diff":1,"name":"Taiwan","name_long":"Taiwan","brk_a3":"B77","brk_name":"Taiwan","brk_group":null,"abbrev":"Taiwan","postal":"TW","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Self admin.; Claimed by China","name_sort":"Taiwan","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":7,"mapcolor13":2,"pop_est":22974347,"gdp_md_est":712000,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TW","iso_a3":"TWN","iso_n3":"158","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"TWN","adm0_a3_us":"TWN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1787]],[[1788]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"United Republic of Tanzania","sov_a3":"TZA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"United Republic of Tanzania","adm0_a3":"TZA","geou_dif":0,"geounit":"Tanzania","gu_a3":"TZA","su_dif":0,"subunit":"Tanzania","su_a3":"TZA","brk_diff":0,"name":"Tanzania","name_long":"Tanzania","brk_a3":"TZA","brk_name":"Tanzania","brk_group":null,"abbrev":"Tanz.","postal":"TZ","formal_en":"United Republic of Tanzania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tanzania","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":2,"pop_est":41048532,"gdp_md_est":54250,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TZ","iso_a3":"TZA","iso_n3":"834","un_a3":"834","wb_a2":"TZ","wb_a3":"TZA","woe_id":-99,"adm0_a3_is":"TZA","adm0_a3_us":"TZA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1789]],[[1790]],[[1791]],[[-1187,1792,-1344,-1355,1793,-580,-225,-1688,1794]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Uganda","sov_a3":"UGA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uganda","adm0_a3":"UGA","geou_dif":0,"geounit":"Uganda","gu_a3":"UGA","su_dif":0,"subunit":"Uganda","su_a3":"UGA","brk_diff":0,"name":"Uganda","name_long":"Uganda","brk_a3":"UGA","brk_name":"Uganda","brk_group":null,"abbrev":"Uga.","postal":"UG","formal_en":"Republic of Uganda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uganda","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":4,"pop_est":32369558,"gdp_md_est":39380,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"UG","iso_a3":"UGA","iso_n3":"800","un_a3":"800","wb_a2":"UG","wb_a3":"UGA","woe_id":-99,"adm0_a3_is":"UGA","adm0_a3_us":"UGA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1795,-1689,-578,-1701,-1188]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ukraine","sov_a3":"UKR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ukraine","adm0_a3":"UKR","geou_dif":0,"geounit":"Ukraine","gu_a3":"UKR","su_dif":0,"subunit":"Ukraine","su_a3":"UKR","brk_diff":0,"name":"Ukraine","name_long":"Ukraine","brk_a3":"UKR","brk_name":"Ukraine","brk_group":null,"abbrev":"Ukr.","postal":"UA","formal_en":"Ukraine","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ukraine","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":6,"mapcolor13":3,"pop_est":45700395,"gdp_md_est":339800,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UA","iso_a3":"UKR","iso_n3":"804","un_a3":"804","wb_a2":"UA","wb_a3":"UKR","woe_id":-99,"adm0_a3_is":"UKR","adm0_a3_us":"UKR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1795]],[[1796,-1581,-1274,-1584,-926,-1741,-1537,-283,-1655]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Uruguay","sov_a3":"URY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uruguay","adm0_a3":"URY","geou_dif":0,"geounit":"Uruguay","gu_a3":"URY","su_dif":0,"subunit":"Uruguay","su_a3":"URY","brk_diff":0,"name":"Uruguay","name_long":"Uruguay","brk_a3":"URY","brk_name":"Uruguay","brk_group":null,"abbrev":"Ury.","postal":"UY","formal_en":"Oriental Republic of Uruguay","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uruguay","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":10,"pop_est":3494382,"gdp_md_est":43160,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UY","iso_a3":"URY","iso_n3":"858","un_a3":"858","wb_a2":"UY","wb_a3":"URY","woe_id":-99,"adm0_a3_is":"URY","adm0_a3_us":"URY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1797,-43,-316]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Country","admin":"United States of America","adm0_a3":"USA","geou_dif":0,"geounit":"United States of America","gu_a3":"USA","su_dif":0,"subunit":"United States of America","su_a3":"USA","brk_diff":0,"name":"United States","name_long":"United States","brk_a3":"USA","brk_name":"United States","brk_group":null,"abbrev":"U.S.A.","postal":"US","formal_en":"United States of America","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United States of America","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":313973000,"gdp_md_est":15094000,"pop_year":0,"lastcensus":2010,"gdp_year":0,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":0,"fips_10":null,"iso_a2":"US","iso_a3":"USA","iso_n3":"840","un_a3":"840","wb_a2":"US","wb_a3":"USA","woe_id":-99,"adm0_a3_is":"USA","adm0_a3_us":"USA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":13,"long_len":13,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1798]],[[1799]],[[1800]],[[1801]],[[1802]],[[1803]],[[1804]],[[1805]],[[1806]],[[1807]],[[1808]],[[1809]],[[1810]],[[1811]],[[1812]],[[1813]],[[1814]],[[1815]],[[1816]],[[1817]],[[1818]],[[1819]],[[1820]],[[1821]],[[1822]],[[1823]],[[1824]],[[1825]],[[1826]],[[1827]],[[1828]],[[1829]],[[1830]],[[1831]],[[1832]],[[1833]],[[1834]],[[1835]],[[1836]],[[1837]],[[1838]],[[1839]],[[1840]],[[1841]],[[1842]],[[1843]],[[1844]],[[1845]],[[1846]],[[1847]],[[1848]],[[1849]],[[1850]],[[1851]],[[1852]],[[1853]],[[1854]],[[1855]],[[-354,1856,-1297,1857,-440]],[[1858]],[[1859]],[[1860]],[[1861]],[[1862]],[[1863]],[[1864]],[[1865]],[[1866]],[[1867]],[[1868]],[[1869]],[[1870]],[[1871]],[[1872]],[[1873]],[[1874]],[[1875]],[[1876]],[[1877]],[[1878]],[[1879]],[[1880]],[[1881]],[[1882]],[[1883]],[[1884]],[[1885]],[[1886]],[[1887]],[[1888]],[[1889]],[[1890]],[[1891]],[[1892]],[[1893]],[[1894]],[[1895]],[[1896]],[[1897]],[[1898]],[[1899]],[[1900]],[[1901]],[[1902]],[[1903]],[[1904]],[[1905]],[[1906]],[[1907]],[[1908]],[[1909]],[[1910]],[[1911]],[[1912]],[[1913]],[[1914]],[[1915]],[[1916]],[[1917]],[[1918]],[[1919]],[[1920]],[[1921]],[[1922]],[[1923]],[[1924]],[[-442,1925,-382,1926]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Uzbekistan","sov_a3":"UZB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uzbekistan","adm0_a3":"UZB","geou_dif":0,"geounit":"Uzbekistan","gu_a3":"UZB","su_dif":0,"subunit":"Uzbekistan","su_a3":"UZB","brk_diff":0,"name":"Uzbekistan","name_long":"Uzbekistan","brk_a3":"UZB","brk_name":"Uzbekistan","brk_group":null,"abbrev":"Uzb.","postal":"UZ","formal_en":"Republic of Uzbekistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uzbekistan","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":5,"mapcolor13":4,"pop_est":27606007,"gdp_md_est":71670,"pop_year":-99,"lastcensus":1989,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UZ","iso_a3":"UZB","iso_n3":"860","un_a3":"860","wb_a2":"UZ","wb_a3":"UZB","woe_id":-99,"adm0_a3_is":"UZB","adm0_a3_us":"UZB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[[-1193]],[[-1194]],[[-1191,-1770,-7,-1773,-1180],[-1769]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Vincent and the Grenadines","sov_a3":"VCT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Vincent and the Grenadines","adm0_a3":"VCT","geou_dif":0,"geounit":"Saint Vincent and the Grenadines","gu_a3":"VCT","su_dif":0,"subunit":"Saint Vincent and the Grenadines","su_a3":"VCT","brk_diff":0,"name":"St. Vin. and Gren.","name_long":"Saint Vincent and the Grenadines","brk_a3":"VCT","brk_name":"St. Vin. and Gren.","brk_group":null,"abbrev":"St.V.G.","postal":"VC","formal_en":"Saint Vincent and the Grenadines","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Vincent and the Grenadines","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":5,"mapcolor13":7,"pop_est":104574,"gdp_md_est":1070,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VC","iso_a3":"VCT","iso_n3":"670","un_a3":"670","wb_a2":"VC","wb_a3":"VCT","woe_id":-99,"adm0_a3_is":"VCT","adm0_a3_us":"VCT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":18,"long_len":32,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[[1927]],[[1928]],[[1929]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Venezuela","sov_a3":"VEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Venezuela","adm0_a3":"VEN","geou_dif":0,"geounit":"Venezuela","gu_a3":"VEN","su_dif":0,"subunit":"Venezuela","su_a3":"VEN","brk_diff":0,"name":"Venezuela","name_long":"Venezuela","brk_a3":"VEN","brk_name":"Venezuela","brk_group":null,"abbrev":"Ven.","postal":"VE","formal_en":"Bolivarian Republic of Venezuela","formal_fr":"República Bolivariana de Venezuela","note_adm0":null,"note_brk":null,"name_sort":"Venezuela, RB","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":1,"mapcolor13":4,"pop_est":26814843,"gdp_md_est":357400,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VE","iso_a3":"VEN","iso_n3":"862","un_a3":"862","wb_a2":"VE","wb_a3":"VEN","woe_id":-99,"adm0_a3_is":"VEN","adm0_a3_us":"VEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1930]],[[1931]],[[1932]],[[1933]],[[-894,-320,-588,1934]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"British Virgin Islands","adm0_a3":"VGB","geou_dif":0,"geounit":"British Virgin Islands","gu_a3":"VGB","su_dif":0,"subunit":"British Virgin Islands","su_a3":"VGB","brk_diff":0,"name":"British Virgin Is.","name_long":"British Virgin Islands","brk_a3":"VGB","brk_name":"British Virgin Is.","brk_group":null,"abbrev":"V.I. (Br.)","postal":"VG","formal_en":"British Virgin Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"British Virgin Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":24491,"gdp_md_est":853.4,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"VG","iso_a3":"VGB","iso_n3":"092","un_a3":"092","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"VGB","adm0_a3_us":"VGB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":18,"long_len":22,"abbrev_len":10,"tiny":3,"homepart":-99},"arcs":[[[1935]],[[1936]],[[1937]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"United States Virgin Islands","adm0_a3":"VIR","geou_dif":0,"geounit":"United States Virgin Islands","gu_a3":"VIR","su_dif":0,"subunit":"United States Virgin Islands","su_a3":"VIR","brk_diff":0,"name":"U.S. Virgin Is.","name_long":"United States Virgin Islands","brk_a3":"VIR","brk_name":"U.S. Virgin Is.","brk_group":null,"abbrev":"V.I. (U.S.)","postal":"VI","formal_en":"Virgin Islands of the United States","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"Virgin Islands (U.S.)","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":109825,"gdp_md_est":1577,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"VI","iso_a3":"VIR","iso_n3":"850","un_a3":"850","wb_a2":"VI","wb_a3":"VIR","woe_id":-99,"adm0_a3_is":"VIR","adm0_a3_us":"VIR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":15,"long_len":28,"abbrev_len":11,"tiny":3,"homepart":-99},"arcs":[[[1938]],[[1939]],[[1940]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Vietnam","sov_a3":"VNM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Vietnam","adm0_a3":"VNM","geou_dif":0,"geounit":"Vietnam","gu_a3":"VNM","su_dif":0,"subunit":"Vietnam","su_a3":"VNM","brk_diff":0,"name":"Vietnam","name_long":"Vietnam","brk_a3":"VNM","brk_name":"Vietnam","brk_group":null,"abbrev":"Viet.","postal":"VN","formal_en":"Socialist Republic of Vietnam","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Vietnam","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":5,"mapcolor13":4,"pop_est":86967524,"gdp_md_est":241700,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VN","iso_a3":"VNM","iso_n3":"704","un_a3":"704","wb_a2":"VN","wb_a3":"VNM","woe_id":-99,"adm0_a3_is":"VNM","adm0_a3_us":"VNM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1941]],[[1942]],[[1943]],[[1944]],[[1945]],[[1946]],[[1947]],[[1948,-1200,-1242,1949,-1240,-538]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Vanuatu","sov_a3":"VUT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Vanuatu","adm0_a3":"VUT","geou_dif":0,"geounit":"Vanuatu","gu_a3":"VUT","su_dif":0,"subunit":"Vanuatu","su_a3":"VUT","brk_diff":0,"name":"Vanuatu","name_long":"Vanuatu","brk_a3":"VUT","brk_name":"Vanuatu","brk_group":null,"abbrev":"Van.","postal":"VU","formal_en":"Republic of Vanuatu","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Vanuatu","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":218519,"gdp_md_est":988.5,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VU","iso_a3":"VUT","iso_n3":"548","un_a3":"548","wb_a2":"VU","wb_a3":"VUT","woe_id":-99,"adm0_a3_is":"VUT","adm0_a3_us":"VUT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[1950]],[[1951]],[[1952]],[[1953]],[[1954]],[[1955]],[[1956]],[[1957]],[[1958]],[[1959]],[[1960]],[[1961]],[[1962]],[[1963]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Wallis and Futuna","adm0_a3":"WLF","geou_dif":0,"geounit":"Wallis and Futuna","gu_a3":"WLF","su_dif":0,"subunit":"Wallis and Futuna","su_a3":"WLF","brk_diff":0,"name":"Wallis and Futuna Is.","name_long":"Wallis and Futuna Islands","brk_a3":"WLF","brk_name":"Wallis and Futuna Islands","brk_group":null,"abbrev":"Wlf.","postal":"WF","formal_en":"Wallis and Futuna Islands","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"Wallis and Futuna","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":15289,"gdp_md_est":60,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"WF","iso_a3":"WLF","iso_n3":"876","un_a3":"876","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"WLF","adm0_a3_us":"WLF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":21,"long_len":25,"abbrev_len":4,"tiny":3,"homepart":-99},"arcs":[[[1964]],[[1965]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Samoa","sov_a3":"WSM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Samoa","adm0_a3":"WSM","geou_dif":0,"geounit":"Samoa","gu_a3":"WSM","su_dif":0,"subunit":"Samoa","su_a3":"WSM","brk_diff":0,"name":"Samoa","name_long":"Samoa","brk_a3":"WSM","brk_name":"Samoa","brk_group":null,"abbrev":"Samoa","postal":"WS","formal_en":"Independent State of Samoa","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Samoa","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":6,"pop_est":219998,"gdp_md_est":1049,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"WS","iso_a3":"WSM","iso_n3":"882","un_a3":"882","wb_a2":"WS","wb_a3":"WSM","woe_id":-99,"adm0_a3_is":"WSM","adm0_a3_us":"WSM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1966]],[[1967]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Yemen","sov_a3":"YEM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Yemen","adm0_a3":"YEM","geou_dif":0,"geounit":"Yemen","gu_a3":"YEM","su_dif":0,"subunit":"Yemen","su_a3":"YEM","brk_diff":0,"name":"Yemen","name_long":"Yemen","brk_a3":"YEM","brk_name":"Yemen","brk_group":null,"abbrev":"Yem.","postal":"YE","formal_en":"Republic of Yemen","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Yemen, Rep.","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":3,"mapcolor13":11,"pop_est":23822783,"gdp_md_est":55280,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"YE","iso_a3":"YEM","iso_n3":"887","un_a3":"887","wb_a2":"RY","wb_a3":"YEM","woe_id":-99,"adm0_a3_is":"YEM","adm0_a3_us":"YEM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1968]],[[1969]],[[1970]],[[1971]],[[1972,-1696,-1447]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"South Africa","sov_a3":"ZAF","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Africa","adm0_a3":"ZAF","geou_dif":0,"geounit":"South Africa","gu_a3":"ZAF","su_dif":0,"subunit":"South Africa","su_a3":"ZAF","brk_diff":0,"name":"South Africa","name_long":"South Africa","brk_a3":"ZAF","brk_name":"South Africa","brk_group":null,"abbrev":"S.Af.","postal":"ZA","formal_en":"Republic of South Africa","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"South Africa","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":4,"mapcolor13":2,"pop_est":49052489,"gdp_md_est":491000,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ZA","iso_a3":"ZAF","iso_n3":"710","un_a3":"710","wb_a2":"ZA","wb_a3":"ZAF","woe_id":-99,"adm0_a3_is":"ZAF","adm0_a3_us":"ZAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1973]],[[-1340,-1749,-1338,1974,-1368,-330,1975],[-1258]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Zambia","sov_a3":"ZMB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Zambia","adm0_a3":"ZMB","geou_dif":0,"geounit":"Zambia","gu_a3":"ZMB","su_dif":0,"subunit":"Zambia","su_a3":"ZMB","brk_diff":0,"name":"Zambia","name_long":"Zambia","brk_a3":"ZMB","brk_name":"Zambia","brk_group":null,"abbrev":"Zambia","postal":"ZM","formal_en":"Republic of Zambia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Zambia","name_alt":null,"mapcolor7":5,"mapcolor8":8,"mapcolor9":5,"mapcolor13":13,"pop_est":11862740,"gdp_md_est":17500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ZM","iso_a3":"ZMB","iso_n3":"894","un_a3":"894","wb_a2":"ZM","wb_a3":"ZMB","woe_id":-99,"adm0_a3_is":"ZMB","adm0_a3_us":"ZMB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-1354,-1342,1976,-1367,-9,-581,-1794]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Zimbabwe","sov_a3":"ZWE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Zimbabwe","adm0_a3":"ZWE","geou_dif":0,"geounit":"Zimbabwe","gu_a3":"ZWE","su_dif":0,"subunit":"Zimbabwe","su_a3":"ZWE","brk_diff":0,"name":"Zimbabwe","name_long":"Zimbabwe","brk_a3":"ZWE","brk_name":"Zimbabwe","brk_group":null,"abbrev":"Zimb.","postal":"ZW","formal_en":"Republic of Zimbabwe","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Zimbabwe","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":3,"mapcolor13":9,"pop_est":12619600,"gdp_md_est":9323,"pop_year":0,"lastcensus":2002,"gdp_year":0,"economy":"5. Emerging region: G20","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ZW","iso_a3":"ZWE","iso_n3":"716","un_a3":"716","wb_a2":"ZW","wb_a3":"ZWE","woe_id":-99,"adm0_a3_is":"ZWE","adm0_a3_us":"ZWE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1976,-329,-1977,-1341]]}]}},"arcs":[[[3058,5901],[0,-2],[-1,1],[-2,4],[-2,2],[1,3],[0,1],[2,-2],[2,-5],[0,-2]],[[7080,7328],[-2,0],[-2,1],[-1,2],[0,1],[-2,-2],[-3,-1],[-5,-5],[0,-1],[4,-5],[0,-1],[1,-1]],[[7070,7316],[-3,-2],[-7,-5],[-4,-4],[-1,0],[-3,1],[-4,3],[-1,-1],[-9,0],[-8,-1],[-3,-1],[-6,-1],[-4,0],[-3,-1],[-3,-3],[-3,-1],[-2,0],[-2,-2],[-2,-4],[-5,-6],[-3,-3],[-1,-3],[-2,0],[-2,0],[-2,-3],[-3,-5],[-4,-7],[-2,-3],[-1,-4],[1,-3],[3,-3],[2,-4],[0,-2],[2,-7],[1,-7],[1,-3],[1,-5],[0,-3],[-1,-2],[0,-2],[0,-3],[1,-2],[0,-2],[1,-2],[-1,-2],[-1,-2],[-1,-3],[-2,-5],[-3,-3],[-1,-3],[-2,-5],[-3,-6],[-2,-4],[-1,-3],[-1,-1],[0,-3],[1,-3],[2,-4],[0,-5],[0,-4],[0,-5],[-1,-4],[-6,-4],[-5,-2],[-7,0],[-2,1],[-2,1],[-7,4],[-3,-2],[-1,-7],[5,-10],[2,-6],[3,-9],[2,-5],[-1,-5],[-5,-5],[-4,-5],[-6,-1],[-4,-2],[-2,-2],[-1,-11],[-2,-4],[0,-5],[-1,-5],[-2,-3],[-1,-6],[0,-11],[1,-18],[-3,-5],[-3,-6],[-3,-4],[-3,-2],[-2,1],[-2,3],[-1,3],[-2,3],[-2,-1],[-2,-2],[-4,1],[-3,2],[-1,0],[-1,-3],[-3,-5],[-8,-7],[-3,-1],[-2,-1],[1,-4],[1,-2],[3,-2],[0,-2],[-2,-2],[-2,-2],[-4,-2],[-5,-1],[-4,1],[-3,4],[-3,0],[-2,-2],[-3,-4],[-3,-9],[-1,-1],[-1,-2],[-2,-2],[-2,-3],[-2,-6],[-1,-11],[0,-6],[0,-11],[-1,-7],[-1,-5],[1,-4],[1,-4],[0,-3],[-2,-3],[-1,-2],[-6,-3],[-9,-4],[-5,-3],[-8,-5],[-2,-1],[-5,0],[-3,1],[-3,0],[-5,0],[-4,-1],[-4,-3],[-2,-2],[-2,-3],[0,-1],[-4,2],[-11,4],[-30,-5],[-3,1],[-10,6],[-14,7],[-8,5],[-11,7]],[[6689,6904],[8,15]],[[6697,6919],[6,14],[6,13],[7,14],[0,4],[0,10],[-1,12],[-3,5],[-9,3],[-6,1],[-7,2],[-1,1],[-1,9],[0,5],[0,8],[0,6],[1,11],[0,4],[-3,21],[-2,11],[-2,11],[0,4],[0,4],[4,11],[1,3],[3,5],[1,3],[0,2],[-3,1],[-4,0],[-2,1],[-2,3],[0,5],[1,7],[-2,15],[3,7],[2,5],[7,1],[-3,5],[-1,4],[-1,0],[0,2],[1,2],[1,0],[1,2],[2,3],[1,1],[1,3],[1,2],[1,3],[1,3],[0,4],[1,5],[0,3],[1,2],[-1,4],[0,3],[0,3],[1,1],[1,2],[0,3],[1,3],[1,3],[1,2],[0,3],[-1,3]],[[6701,7235],[2,1],[1,-2],[1,-3],[4,-5],[2,-1],[3,-1],[3,1],[3,1],[1,-1],[3,-3],[3,-6],[2,-2],[0,-3],[1,-1],[2,3],[2,1],[2,0],[3,-1],[2,1],[1,1],[3,5],[4,3],[2,2],[1,7],[1,4],[1,3],[0,3],[-1,2],[-1,3],[1,1],[1,1],[4,0],[6,3],[5,3],[4,3],[2,0],[2,0],[1,1],[1,2],[1,3],[2,2],[5,4],[4,7],[2,5],[1,7],[2,12],[2,12],[1,5],[1,5],[4,3],[3,3],[6,0],[7,0],[2,7],[1,6],[1,3],[2,2],[0,1],[4,-4],[6,-5],[6,-3],[4,-1],[1,0]],[[6847,7335],[9,1],[6,-2],[4,-6],[3,-1],[4,3],[2,0],[1,-1],[1,-1],[3,0],[1,-2],[1,-1]],[[6882,7325],[0,-2],[2,-4],[3,-6],[3,-1],[4,4],[1,0],[1,1],[1,3],[2,3],[4,3],[3,2],[1,2],[1,0],[2,0],[1,1],[0,1],[1,1],[1,1],[1,0],[1,0],[2,-4],[4,-6],[2,-3],[1,1],[2,2],[1,3],[1,5],[-1,6],[1,5],[2,4],[3,2],[6,1],[3,0],[1,-2],[2,-2],[2,0],[2,2],[2,5],[0,6],[-2,7],[1,2],[0,1],[2,3],[3,5],[3,7],[3,8],[3,5],[4,2],[5,-2],[6,-7],[2,-8],[-2,-9],[0,-5],[1,-1],[2,0],[3,2],[2,0],[1,-2],[0,-2],[-1,-4],[-1,-11],[-1,-10],[-1,-9],[0,-9],[1,-6],[1,-10],[2,-6],[2,-3],[2,0],[2,0],[4,4],[6,8],[5,5],[9,3],[2,8],[4,5],[9,8],[5,4],[2,0],[4,-1],[1,-1],[2,-1],[0,-2],[0,-3],[-2,-2],[0,-2],[0,-1],[3,-1],[5,3],[4,2],[2,1],[2,2],[1,3],[3,0],[2,-1],[2,-1],[4,1],[2,-2],[3,-5],[1,-2],[1,-1]],[[5665,4558],[1,-8],[0,-10],[1,-8],[0,-3],[0,-2],[0,-2],[0,-5],[-1,-4],[-1,-2],[1,-6],[-1,-7],[0,-8],[0,-7],[1,-14],[0,-4],[-1,-7],[-1,-5],[-1,-6],[0,-3],[2,-9],[0,-2],[-2,-1],[-1,0],[-6,0],[-8,0],[-9,0],[-8,0],[-7,0],[-8,0],[-6,0],[0,-9],[0,-18],[0,-19],[0,-18],[0,-19],[0,-18],[0,-19],[0,-18],[0,-19],[0,-13],[2,-18],[3,-19],[1,-2],[3,-3],[4,-8],[3,-5],[5,-10],[6,-12],[6,-11],[6,-9]],[[5649,4168],[-9,-4],[-12,-4],[-8,-4],[-11,-4],[-6,-2],[-9,-3],[-1,0],[-2,2],[-5,1],[-6,-3],[-4,-1],[-4,1],[-3,3],[-3,4],[-6,1],[-7,-1],[-8,1],[-7,2],[-6,1],[-3,0],[-3,0],[-4,2],[-3,4],[-3,8],[-3,7],[-1,1],[-1,1],[-1,1],[-8,0],[-7,0],[-4,0],[-11,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-6,0],[-5,0],[-6,-1],[-1,0],[-1,1],[-1,2],[-3,4],[-3,3],[-4,5],[-2,6],[-2,2],[-4,1],[-2,1],[-3,0],[-3,-2],[-3,-3],[-2,-3],[-4,-3],[-3,-3],[-5,1],[-1,-1],[-3,1],[-3,2],[-3,0],[-3,-3],[-4,-2]],[[5326,4190],[1,22],[1,10],[0,11],[-1,30],[-1,4],[0,5],[3,4],[1,2],[2,5],[1,7],[2,16],[6,35],[2,34],[4,17],[1,18],[10,23],[2,15],[5,7],[7,8],[5,13],[3,9],[2,18],[0,19],[2,25],[0,7],[-3,10],[0,7],[-3,7],[-2,6],[-2,9],[-4,15],[-1,10],[-3,7],[0,9],[-1,9],[-2,9],[-2,11],[0,3],[1,4],[1,1],[0,-2],[-1,-2],[0,-2],[9,18],[0,4],[0,4],[0,5],[0,6],[-8,34],[-6,31],[-1,16],[-9,21],[-3,14],[-2,9],[-1,4],[0,2],[2,0],[5,3],[7,2],[6,6],[1,2]],[[5362,4846],[4,0],[3,-1],[1,1],[1,0],[8,0],[3,1],[6,-1],[4,0],[2,-1],[5,-1],[8,1],[2,0],[10,0],[9,1],[8,0],[10,0],[7,0],[3,-2],[3,-4],[1,-3],[1,-2],[1,-3],[1,-3],[1,-5],[-1,-6],[1,-7],[1,-8],[1,-9],[3,-10],[2,-7],[-1,-5],[1,-6],[2,-6],[2,-4],[1,-2],[2,-9],[5,-15],[4,-11],[1,-2],[2,1],[3,1],[4,0],[3,-2],[1,0],[4,5],[4,1],[4,2],[2,2],[3,0],[6,-4],[2,0],[5,0],[6,2],[1,15],[0,3],[1,6],[2,4],[0,5],[0,7],[1,7],[4,6],[6,3],[3,1],[5,2],[8,1],[3,0],[1,-1],[-2,-10],[0,-4],[1,-3],[1,-2],[8,-1],[8,0],[9,0],[7,-1],[0,-1],[1,0],[1,-6],[0,-10],[-2,-15],[1,-14],[3,-14],[0,-20],[-1,-12],[-1,-15],[-1,-18],[2,-7],[2,-7],[4,-8],[3,-11],[2,-12],[1,-8],[-1,-3],[0,-6],[1,-8],[-1,-5],[-2,-3],[-1,-4],[2,-7],[0,-6],[1,-2],[0,-2],[1,0],[2,2],[3,4],[2,2],[3,0],[4,-1],[7,-1],[3,1],[6,6],[2,0],[3,-1],[4,-1],[3,-1],[2,2],[1,2],[0,3],[1,2]],[[5339,4852],[-1,2],[-1,5],[1,6],[1,4],[-1,8],[-2,7],[-2,10],[-1,2]],[[5333,4896],[2,3],[2,6],[1,4],[3,0],[1,3],[1,4],[0,2],[4,2],[4,3],[2,3],[2,3],[1,0],[1,-1],[3,-6],[2,-4],[1,-1]],[[5363,4917],[-1,-1],[-3,-3],[-3,-2],[-4,-10],[-3,-4],[0,-1],[-2,-2],[-2,-2],[0,-1],[1,-2],[1,-2],[0,-16],[0,-15],[-1,-2],[-2,0],[-4,-1],[-1,-1]],[[3250,6233],[-5,-3],[0,2],[4,4],[1,0],[0,-3]],[[5557,7634],[1,-1],[2,-6],[2,-5],[3,-1],[1,-2],[2,-3],[2,-3],[1,-9],[0,-6],[0,-2]],[[5571,7596],[-1,-1],[-1,-9],[0,-5],[0,-3],[-1,-1],[-1,-2],[2,-7],[0,-3],[0,-4],[2,-8],[1,-3],[1,-1],[2,-8],[1,-1],[3,1],[2,-1],[1,-2],[0,-1]],[[5582,7537],[0,-5],[0,-3],[2,-3],[0,-2],[-1,-4],[-2,-4],[-2,-1],[-2,-2],[-1,-3],[0,-3],[-1,-2],[-1,-3],[-1,-6],[0,-2],[-1,-2],[-2,0],[-2,0],[-2,-1],[0,-2],[-2,-2],[0,-2],[1,-4],[1,-2],[0,-3],[-1,0],[-1,0],[-1,-1],[0,-2],[0,-2],[-1,-2],[-1,-1],[-2,0],[-2,2],[-1,1],[-1,0]],[[5555,7471],[0,5],[-1,4],[-3,10],[-10,10],[-3,4],[-1,4],[-1,3],[1,0],[1,-1],[1,-1],[1,2],[-1,4],[-2,9],[0,2],[1,7],[2,8],[0,10],[1,8],[-1,5],[-1,6],[2,8],[1,2],[1,2],[0,9],[-3,4],[-3,0]],[[5537,7595],[0,3],[0,5],[0,1],[0,3],[-1,3],[-1,3],[1,4],[2,6],[2,4],[2,4],[2,5],[1,3],[2,1],[0,-1],[1,-1],[0,-5],[0,-1],[1,-2],[2,1],[2,1],[3,3],[1,-1]],[[5572,8642],[0,-1],[-3,-1],[0,2],[-3,-1],[0,1],[1,1],[2,1],[2,0],[1,-2]],[[5546,8650],[0,-1],[-1,1],[-1,-1],[-1,-2],[-1,1],[0,2],[1,4],[2,0],[1,-4]],[[5555,8660],[1,0],[1,0],[3,-2],[0,-1],[2,-1],[0,-1],[-2,-4],[-1,0],[-1,0],[-1,0],[-1,-1],[0,-2],[0,-3],[-7,-1],[-1,1],[-2,8],[0,2],[2,1],[1,0],[0,-4],[2,0],[0,3],[0,2],[0,1],[-1,1],[-1,1],[1,2],[2,1],[1,-3],[2,0]],[[5047,7632],[-1,0],[-2,-3],[-2,-1],[-1,0],[-1,0],[-1,2],[0,2],[0,2],[0,1],[0,2]],[[5039,7637],[1,2],[1,1],[2,0],[4,-2],[1,-2],[0,-1],[-1,-2],[0,-1]],[[6497,6576],[0,-2],[-2,1],[-1,-1],[-3,1],[-2,1],[2,2],[4,3],[1,-2],[1,-3]],[[6461,6583],[-1,-1],[0,3],[0,1],[1,2],[1,-3],[-1,-2]],[[6481,6581],[-2,0],[-2,2],[4,3],[1,1],[1,3],[1,-2],[-1,-4],[-1,-2],[-1,-1]],[[6512,6592],[0,-1],[-1,0],[-2,1],[0,1],[1,2],[1,-2],[1,-1]],[[6563,6661],[2,-4],[0,-32],[1,-2]],[[6566,6623],[-1,-1],[-1,-2],[-2,-4],[-1,-2],[-2,-2],[-1,-3],[-1,0],[-2,3],[-1,4],[1,1],[0,1],[0,3],[-1,1],[-1,0],[-2,-1],[-1,-2],[-1,-3],[0,-5],[0,-5],[0,-3],[0,-4],[-1,-5],[1,-3],[0,-3],[1,-2],[-2,-6],[1,-1],[4,0],[1,-5],[1,-2],[-1,-2],[-2,-1],[-3,-2],[-3,1],[-4,-2],[-2,-3],[1,-2],[1,-1],[0,-4],[-1,-6],[-1,-5],[-1,-7],[-2,-7],[-2,-11],[-2,-9],[-1,-7],[1,-4],[-1,-8]],[[6532,6492],[-2,-5],[-2,0],[-1,1],[-2,0],[-3,1],[-5,1],[-5,1],[-5,2],[-6,1],[-6,2],[-6,1],[-6,2],[-6,1],[-5,1],[-4,2],[-4,0],[-2,1],[-3,1],[-1,3],[-2,4],[-1,3],[-2,4],[-1,4],[-2,4],[-1,3],[-2,4],[-1,4],[-2,4],[-1,4],[-2,3],[-1,4],[-2,4],[-1,4],[-2,3],[-1,4],[-2,3],[0,3],[0,7],[0,2]],[[6432,6583],[1,3],[0,-2],[1,-3],[2,0],[1,0],[1,-11],[1,-3],[2,-2],[6,-1],[4,2],[7,7],[4,2],[10,0],[9,-3],[13,-2],[2,1],[7,5],[5,5],[2,1],[2,5],[1,6],[1,4],[1,2],[2,3],[1,5],[2,6],[10,13],[6,11],[0,4],[3,5],[3,6],[11,17],[3,8],[1,7],[0,1]],[[6557,6685],[1,0],[2,-1],[0,-6],[-1,-5],[0,-6],[0,-3],[1,-3],[2,-1],[1,0],[0,1]],[[6561,6636],[1,0],[1,1],[0,3],[0,1],[-2,0],[0,-2],[0,-3]],[[3207,2032],[3,-1],[6,1],[3,0],[1,-1],[1,0],[4,1],[2,0],[0,-3],[-4,-2],[-2,1],[-8,0],[-4,-3],[-1,0],[-4,-3],[-2,2],[-1,2],[2,3],[2,0],[1,1],[1,2]],[[3093,2024],[0,13],[0,18],[0,15],[0,16],[0,15],[0,16],[0,17],[0,17]],[[3093,2151],[2,-2],[6,-12],[2,-5],[1,-6],[-2,4],[-3,-2],[-2,-3],[-1,-4],[0,-3],[1,-2],[3,-2],[6,-1],[1,0],[4,-14],[1,-4],[3,-2],[5,-7],[5,-8],[5,-7],[7,-6],[5,-4],[6,-6],[6,-7],[6,-5],[7,-4],[6,-3],[11,1],[3,0],[2,-3],[-2,-6],[-2,-5],[-4,-2],[-4,-1],[-3,0],[-3,1],[-3,0],[-3,-3],[-3,-1],[-4,0],[-3,-2],[-3,-1],[-3,1],[-8,5],[-6,1],[-18,2],[-6,2],[-6,1],[-3,0],[-5,-1],[-3,0],[-1,-1]],[[3281,2928],[0,-4],[-1,0],[-4,4],[-1,3],[0,1],[3,-1],[2,-1],[1,-2]],[[3259,3903],[1,-1],[0,-2],[2,-4],[5,-5],[5,-10],[4,-14],[3,-11],[4,-7],[3,-5],[3,-3],[2,-3],[0,-2],[3,-3],[5,-6],[4,-6],[1,-5],[6,-6],[9,-6],[7,-3],[4,0],[6,-5],[8,-10],[5,-7],[1,-4],[6,-6],[12,-13],[6,-3],[3,-3],[1,-4],[2,-1],[2,2],[3,-2],[5,-4],[4,-5],[4,-11],[2,-4],[1,-4],[-1,-4],[-1,-4],[-3,-4],[-1,-1],[0,-2],[0,-3],[-3,-7],[0,-4],[0,-2],[-2,-3],[-4,-5],[-1,-2],[0,-3],[0,-1],[-1,-1],[0,-2],[-1,-5],[0,-5],[0,-7],[0,-2],[-1,-1],[0,-2],[0,-3],[-1,-2],[-1,-2],[-1,-1],[1,-2],[-1,-2],[-3,-2],[-1,-3],[0,-3],[-2,-3],[-2,-3],[0,-4],[1,-6],[12,2],[10,-3],[11,-6],[8,-2],[4,2],[3,-1],[2,-2],[2,-1],[3,2],[3,-1],[2,-4],[2,1],[1,5],[2,5],[3,2],[2,1],[3,-1],[3,-2],[2,-3],[2,0],[2,3],[1,4],[0,5],[1,3],[2,2],[1,3],[1,3],[2,2],[4,1],[2,2],[0,2],[1,3],[3,2],[1,3],[1,3],[1,2],[2,1],[2,7],[2,12],[1,18],[1,25]],[[3483,3711],[2,0],[1,-2],[1,-1],[2,2],[1,1],[3,0],[1,2],[1,1],[1,-2],[1,-1],[2,0],[2,-4],[2,-2],[0,-4],[2,-12],[2,-8],[2,-8],[0,-3],[-1,-4],[-1,-5],[0,-13],[0,-5],[0,-3],[1,-5],[-2,-5],[-2,-8],[-2,-3],[-1,0],[-2,-4],[-3,-2],[-1,1],[-1,-2],[-2,-5],[-1,-3],[-4,-1],[-1,-1],[-2,0],[-1,-1],[-2,-3],[-1,-1],[-2,1],[-1,-1],[-2,-3],[0,-3],[-1,-3],[-1,-2],[-2,-2],[-1,-1],[0,-3],[-1,-1],[-4,-2],[-3,-3],[-2,-5],[-1,-3],[-3,-2],[-4,-5],[-1,-3],[2,-2],[0,-3],[0,-2],[-1,0],[-3,1],[-1,1],[-1,-1],[0,-2],[0,-2],[-1,-2],[-1,-1],[-1,-2],[-1,-3],[-2,-4],[-3,-5],[-3,-7],[-2,-8],[-2,-6],[-3,-3],[-2,-3],[-1,-5],[-2,-8],[-5,-10],[-4,-7],[-4,-4],[-2,-4],[0,-5],[-3,-5],[-4,-6],[-2,-3]],[[3399,3445],[-1,-2],[0,-4],[-1,-5],[-4,-7],[-1,-5],[2,-7],[0,-9],[-1,-3],[-1,-1],[-1,-2],[1,-4],[0,-4],[0,-5],[-2,-6],[-2,-7],[-1,-4],[1,-3],[1,-2],[0,-2],[-1,-4],[-1,-5],[-1,-4],[-2,-2],[-1,-3],[1,-4],[0,-3],[0,-4],[0,-4],[1,-4],[0,-4],[-2,-9]],[[3383,3313],[-1,-5],[2,-23],[-1,-3],[-1,-3],[-2,-1],[-2,1],[-1,-2],[-1,-10],[-3,-22],[1,-5],[2,-9],[1,-5],[0,-4],[1,-8],[-2,-3],[-1,-1],[-1,-2],[2,-9],[1,-4],[4,-9],[14,-12],[6,-7],[7,-10],[4,-10],[0,-8],[-5,-13],[-1,-10],[1,-7],[2,-7],[5,-9],[4,-3],[5,0],[1,-2],[1,-2],[1,-18],[-1,-7],[-1,-6],[-10,-28],[-9,-17],[-3,-10],[-1,-10],[-3,-5],[-14,-15],[-23,-14],[-19,-7],[-4,-2],[-30,-8],[-6,-1],[-7,1],[-7,-1],[-6,2],[-6,2],[-4,6],[-4,1],[-1,-3],[2,-8],[-1,-9],[1,-6],[3,-1],[2,-2],[2,-4],[-4,0],[2,-3],[1,-2],[0,-6],[-1,-15],[-4,-3],[-1,-1],[-1,-3],[-2,-14],[0,-10],[1,-6],[4,-12],[-2,-8],[-3,-4],[-11,-9],[-4,-4],[-7,-3],[-12,0],[-4,1],[-10,8],[-7,5],[-6,4],[-7,2],[1,1],[1,2],[-2,1],[-2,1],[-4,-5],[-2,-4],[0,-4],[0,-9],[1,-7],[3,-19],[0,-11],[-2,-13],[3,-7],[2,-4],[5,-3],[3,-2],[2,0],[1,-1],[-1,-2],[-1,-3],[0,-3],[4,-1],[5,0],[4,2],[1,2],[0,5],[-5,1],[1,2],[4,2],[5,3],[3,1],[1,-2],[2,-2],[1,-6],[1,-7],[0,-8],[0,-8],[-1,-3],[-2,-4],[-9,-4],[-3,1],[-2,6],[-1,6],[-2,5],[-5,3],[-4,-1],[-5,-6],[-4,-2],[-2,-5],[11,-9],[6,-2],[1,0],[2,-1],[-2,-3],[-1,-2],[-8,-5],[-3,-3],[-4,-6],[-6,-13],[-2,-3],[-1,-3],[0,-9],[2,-15],[-2,-7],[1,-7],[-1,-4],[-2,-7],[-8,-11],[-1,-7],[2,-5],[0,-4],[-1,-4],[-3,0],[-12,3],[-4,-4],[-4,-5],[-1,-2],[-2,-2],[-8,-2],[-2,-2],[-9,-18],[-3,-12],[-5,-11],[-1,-5],[0,-6],[0,-6],[1,-5],[2,-5],[3,-7],[17,-26],[3,-2],[18,-3],[4,-3],[3,-6],[1,-5],[-1,-13],[-1,-4],[-2,-4],[-5,-4],[-5,-3],[2,-2],[2,1],[4,1],[2,-1],[2,-6],[-3,-2],[-1,-2],[-2,-4],[-11,-15],[-5,-4],[-5,-6],[-7,-6],[-3,-4],[-4,-7],[-5,-8],[-6,-17],[-1,-3],[1,-2],[-3,-30],[-1,-3],[-3,-4],[-6,-6],[-3,-1],[-4,3],[-3,4],[-2,7],[-3,6],[0,-2],[1,-4],[-1,-4],[-7,-2],[-1,-2],[6,1],[4,-2],[2,-1],[2,-3],[1,-4],[-1,-2],[-4,-2],[-4,-3],[-5,-6],[-3,-7],[-1,-5],[-2,-9],[0,-7],[-3,-5],[-3,-4],[0,-1],[3,2],[1,1],[2,-6],[2,-12],[1,-8],[0,-3],[-1,-3],[-4,-1],[-4,0],[-3,-1],[2,-2],[2,1],[4,-4],[4,2],[2,-3],[1,-2],[7,-17],[5,-11],[3,-6],[-2,-3]],[[3098,2168],[0,4],[-4,1],[-3,1],[-6,3],[-8,4],[-8,0],[-6,3],[-7,4],[-14,1],[-13,0],[-13,0],[-8,0],[-6,0],[-1,2],[0,5],[-2,3],[-3,4],[-4,3],[-2,5],[-2,4],[2,4],[1,10],[0,4],[-1,3],[-1,5],[1,2],[1,1],[1,7],[-1,7],[-1,7],[-1,2],[-2,2],[-1,0],[-4,-2],[-5,0],[-1,-1],[-3,-2],[-3,-4],[-2,1],[-1,4],[-1,4],[-1,3],[-1,5],[-1,6],[-2,8],[-3,6],[0,5],[-1,7],[2,7],[-1,5],[-2,7],[1,7],[1,4],[1,4],[9,1],[0,7],[1,5],[2,5],[1,2],[4,2],[3,2],[3,4],[1,2],[0,4],[0,4],[0,8],[1,3],[2,3],[4,3],[2,8],[-1,7],[-3,5],[-2,3],[-1,5],[2,6],[1,5],[2,7],[0,4],[2,3],[5,6],[2,6],[1,1],[2,1],[0,3],[-1,4],[0,4],[0,4],[0,6],[3,3],[3,5],[1,3],[0,4],[-1,9],[-1,6],[0,2],[-2,4],[-1,3],[2,3],[3,4],[2,5],[-1,4],[-2,3],[-1,6],[1,9],[1,2],[5,1],[1,5],[4,6],[0,6],[-3,3],[-2,6],[-2,5],[-6,3],[-6,1],[-1,5],[0,3],[3,-1],[5,1],[3,0],[3,1],[3,0],[3,-2],[2,2],[1,7],[2,4],[0,4],[-1,3],[-4,1],[-13,2],[-1,3],[0,6],[1,5],[0,2],[1,3],[2,4],[1,4],[-1,4],[-3,6],[2,2],[0,4],[0,3],[-3,4],[-2,5],[0,5],[3,1],[1,2],[1,3],[-1,4],[-3,2],[-5,2],[-1,2],[-1,5],[1,12],[-1,7],[0,4],[1,4],[1,2],[0,7],[-2,3],[1,3],[1,3],[1,3],[1,1],[1,-2],[3,1],[2,3],[1,3],[-1,4],[-2,12],[-2,7],[1,2],[0,3],[0,10],[0,5],[0,18],[0,5],[-2,6],[1,6],[1,4],[1,6],[1,5],[1,2],[2,1],[0,3],[-1,2],[-2,3],[0,4],[0,3],[1,1],[2,0],[1,5],[1,5],[0,2],[-1,3],[-1,8],[-1,4],[1,2],[1,0],[2,-1],[1,1],[1,2],[0,2],[0,2],[2,5],[1,7],[0,5],[0,12],[0,3],[2,3],[2,2],[2,2],[3,3],[4,2],[1,3],[1,4],[1,4],[-2,2],[-2,3],[-1,8],[0,7],[0,9],[-2,7],[-2,9],[-1,7],[1,4],[1,7],[-1,3],[-1,5],[1,5],[1,6],[0,3],[-1,8],[-1,5],[1,4],[1,5],[2,2],[-1,4],[1,3],[2,2],[2,4],[2,1],[1,0],[1,1],[1,3],[0,3],[3,4],[2,4],[3,1],[1,4],[0,5],[0,5],[1,6],[-1,10],[0,5],[-1,4],[0,4],[-1,3],[-2,1],[0,4],[1,1],[1,2],[2,2],[2,13],[1,4],[0,5],[0,2],[1,4],[1,5],[2,5],[1,4],[2,4],[0,3],[1,2],[2,0],[2,1],[0,2],[0,2],[0,6],[0,8],[-1,12],[1,7],[1,8],[1,4],[0,3],[-1,4],[-2,2],[-2,-2],[-1,0],[-2,4],[-1,5],[1,6],[1,3],[1,5],[-1,1],[-2,3],[-2,11],[1,8],[-2,3],[-1,7],[-2,2],[0,5],[-1,6],[0,2],[2,1],[1,4],[-1,2],[-1,3],[-2,-1],[-1,3],[-2,10],[-2,5],[1,9],[0,6],[1,5],[0,5],[1,2],[1,-1],[1,0],[2,4],[1,2],[0,2],[-1,2],[0,3],[0,4],[2,9],[2,10],[1,3],[0,4],[0,1],[1,-2],[4,2],[2,5],[0,4],[2,2],[-1,3],[-2,1],[-1,1],[1,4],[0,8],[0,6],[-1,13],[-1,13],[0,4],[3,6],[2,3],[0,3],[2,15],[1,8],[1,5],[1,8],[3,8],[1,4],[2,1],[1,2],[2,5],[2,6],[2,2],[1,5],[1,6],[2,10],[1,7],[2,2],[1,9],[1,6],[2,2],[2,1],[2,-3],[1,1],[2,3],[4,2],[1,1],[1,3],[0,6],[-2,4],[-3,8],[-2,8],[-1,3],[0,3],[1,4],[1,4],[3,7],[0,5],[-2,19],[-1,5],[-2,10],[0,4],[2,10],[1,4],[2,1],[1,2],[0,2],[-1,2],[-1,3],[0,4],[-2,2],[-1,3],[0,5],[2,7],[1,2],[1,3],[2,3],[1,2],[2,4],[5,5],[5,3],[9,8],[6,4],[0,4],[1,2],[2,18],[4,22],[2,14],[-5,10]],[[3133,3869],[1,3],[3,7],[1,6],[1,2],[5,6],[1,4],[1,4],[1,3],[2,1],[3,3],[4,2],[1,4],[2,6],[0,6],[1,2],[2,0],[2,-2],[1,-2],[5,-9],[3,-4],[2,-1],[5,1],[1,0],[12,0],[1,-1],[4,-2],[3,-1],[1,-1],[3,-3],[2,-8],[2,-6],[1,-6],[2,-10],[1,-4],[0,2],[2,11],[1,6],[2,8],[5,16],[1,3],[2,1],[1,0],[1,-1],[2,0],[1,1],[11,1],[12,0],[1,-3],[2,-7],[2,-3],[0,-1]],[[6265,7523],[-1,-1],[-1,1],[0,2],[0,1],[1,0],[1,-1],[0,-2]],[[6291,7425],[-5,0],[-4,-2],[-2,0]],[[6280,7423],[-1,5],[-1,3],[-2,9],[1,4],[-2,2],[-3,4],[-1,2],[0,2],[1,4],[-1,4],[-1,1],[-2,0],[-2,-1],[-4,-3],[-3,2],[-2,2],[-1,1],[-2,-1],[0,1],[0,4],[-1,2],[-1,3],[-2,1],[-4,-2],[-3,-1]],[[6243,7471],[-1,2],[-5,8],[-4,6],[-3,3],[-3,0],[-5,-1],[-2,0],[-4,3],[-4,3],[1,1],[1,1],[-1,5],[-2,6],[0,2],[-1,3],[0,3],[2,5],[2,4],[0,4],[-1,4],[-2,8],[-1,3],[-2,2],[-2,3],[0,3]],[[6206,7552],[1,0],[5,0],[4,1],[3,1],[5,2],[2,1],[2,1],[7,-2],[2,1],[8,1],[-1,2],[5,1],[0,1]],[[6249,7562],[1,-3],[2,-2],[2,-2],[1,-1],[0,-1],[-4,-2],[0,-1],[1,-1],[5,-3],[3,0],[1,-1],[1,-3],[2,-3],[2,-2],[0,-1],[-1,-2],[-4,-6],[-1,-1],[0,-3],[2,-6],[3,-6],[5,-5],[6,-6],[0,-3],[-1,-4],[-1,-3],[0,-2],[-1,-1],[-6,1],[-1,-1],[0,-1],[-1,-1],[3,-1],[3,-4],[2,-4],[2,-2],[3,-3],[2,-4],[3,-4],[3,2],[5,-4],[0,-2],[-1,-2],[-2,-3],[-1,-1],[0,-1],[1,-1],[1,-2],[2,-3],[2,-4],[-1,-1],[-2,0],[-1,0],[-1,-1],[0,-1],[2,-3],[1,-3],[0,-4],[0,-5]],[[6249,7547],[0,-1],[1,1],[0,1],[0,2],[-1,0],[-1,0],[0,-2],[1,-1]],[[258,4357],[-2,0],[-1,2],[3,3],[1,1],[3,-1],[-2,-1],[-2,-4]],[[500,396],[-9,-1],[-20,3],[-6,2],[-2,2],[-6,2],[-2,1],[0,2],[0,2],[-2,1],[-1,1],[-2,1],[28,-1],[11,-2],[2,-1],[19,-6],[-5,-1],[-5,-5]],[[611,455],[-2,-1],[-2,3],[-11,7],[-6,4],[-5,3],[-1,2],[2,0],[15,-7],[3,-2],[12,-5],[-5,-4]],[[543,484],[-3,0],[-75,7],[-14,2],[-4,1],[-1,1],[0,1],[0,2],[2,2],[19,2],[20,-2],[25,-5],[17,-3],[9,-4],[4,-2],[1,-2]],[[724,574],[-5,0],[-7,0],[-5,2],[-11,2],[-3,4],[-13,3],[-6,1],[2,3],[14,-4],[17,-5],[14,-3],[3,-3]],[[3340,556],[-1,-12],[0,-6],[-1,-4],[-3,-3],[-5,-3],[-4,-3],[-9,-4],[-40,4],[-18,3],[-8,4],[-1,2],[-2,6],[-2,2],[-16,-2],[-10,-2],[-2,-1],[-2,-3],[-2,-1],[-26,8],[-27,9],[-11,5],[-4,3],[-1,1],[2,2],[3,1],[3,1],[3,0],[2,-1],[2,-1],[2,-5],[1,-1],[4,-1],[96,0],[8,1],[17,1],[9,2],[3,3],[-8,1],[-3,2],[-3,4],[-1,4],[1,3],[11,1],[1,1],[-2,2],[0,3],[6,2],[2,3],[13,4],[20,-2],[4,-6],[-1,-4],[-1,-3],[0,-6],[8,-1],[2,-2],[3,-2],[-3,0],[-3,-1],[-2,-3],[-2,-3],[-2,-2]],[[4135,588],[4,-2],[4,3],[-1,3],[3,4],[3,-5],[22,-5],[7,-5],[-3,-1],[-2,0],[-7,0],[-10,-5],[-12,4],[-21,3],[-6,3],[-5,6],[9,6],[2,-1],[13,-8]],[[4101,595],[-5,-1],[-1,2],[2,3],[3,4],[7,0],[6,-2],[-1,-2],[-1,0],[-10,-4]],[[3162,571],[-3,0],[-2,1],[-1,1],[-1,4],[-14,4],[-1,2],[-1,5],[-3,2],[-17,8],[-2,2],[-1,2],[3,1],[7,-2],[13,0],[3,-1],[3,-1],[14,-1],[7,0],[4,-7],[8,-2],[1,-4],[1,-6],[-11,-5],[-2,-1],[-5,-2]],[[3131,607],[-4,-2],[-21,1],[-7,1],[-3,1],[3,6],[3,2],[2,1],[6,3],[9,1],[6,0],[12,-3],[-3,-2],[-2,-1],[-2,-4],[1,-4]],[[4057,615],[-3,-2],[-68,4],[-3,0],[1,4],[9,1],[5,1],[7,2],[6,3],[2,0],[31,-7],[11,-4],[2,-1],[0,-1]],[[582,587],[-35,-2],[-14,2],[-29,6],[-41,11],[-11,4],[-7,3],[-7,4],[-1,4],[1,7],[1,5],[2,3],[9,4],[4,4],[9,4],[2,4],[4,0],[7,-1],[7,-1],[6,-1],[6,-2],[15,-6],[10,-6],[14,-7],[15,-8],[8,-3],[7,-5],[8,-6],[1,-2],[3,-3],[2,-2],[2,-2],[2,-1],[1,-3],[0,-2],[-1,-2]],[[3046,594],[-6,0],[-12,1],[-12,2],[-3,1],[-5,3],[-1,2],[-1,2],[0,3],[3,11],[6,7],[5,4],[18,9],[2,1],[16,5],[6,2],[10,5],[53,18],[13,3],[5,-2],[3,-2],[-2,-2],[-7,-5],[-3,-4],[-9,-6],[-19,-11],[-13,-8],[-17,-12],[-4,-4],[-8,-9],[1,-4],[-2,-6],[-11,-3],[-6,-1]],[[9656,683],[-4,-4],[-4,-2],[-12,1],[-8,-3],[-10,-2],[-4,2],[-2,4],[-1,5],[0,1],[2,1],[13,-3],[5,-3],[3,0],[8,4],[6,4],[2,3],[2,1],[2,-2],[2,-5],[0,-2]],[[3743,644],[4,0],[15,1],[14,0],[9,-1],[3,-2],[2,-3],[3,-5],[2,-5],[3,-5],[1,-8],[3,-3],[4,-7],[1,-6],[-2,-13],[-2,-5],[-5,-5],[-7,1],[-2,-1],[-3,-1],[-1,0],[-1,-1],[8,-5],[0,-1],[1,-2],[-1,-1],[-1,-1],[-158,-26],[-6,-1],[-6,-3],[-2,-2],[-2,-2],[-122,-5],[-1,0],[-1,1],[-3,5],[-1,8],[1,3],[6,3],[2,2],[11,12],[5,5],[2,5],[2,-1],[5,-2],[3,-1],[7,1],[6,3],[3,2],[3,-1],[1,-2],[1,-1],[16,9],[15,9],[14,11],[8,7],[1,2],[2,3],[-1,3],[-2,2],[-1,1],[-1,0],[-8,2],[3,3],[2,4],[1,4],[1,4],[-1,3],[1,1],[3,2],[2,2],[2,3],[-3,1],[-1,2],[3,5],[2,5],[2,3],[5,6],[17,13],[6,8],[1,2],[39,12],[6,2],[12,1],[6,0],[16,-1],[7,-1],[13,-3],[19,-6],[7,-3],[7,-3],[7,-5],[6,-5],[2,-1],[0,-3],[1,-3],[-1,-3],[-1,-5],[-3,-4],[-31,-4],[-4,-1],[-3,-3],[-1,-3],[3,-2]],[[855,729],[8,-3],[-14,1],[-6,4],[4,2],[4,0],[3,-2],[1,-2]],[[822,727],[-2,0],[-24,5],[-5,1],[8,3],[6,0],[14,-7],[4,0],[-1,-2]],[[9640,730],[11,-4],[27,0],[23,-3],[2,-4],[-6,-3],[-10,-5],[-7,-2],[-5,0],[-12,3],[-14,-1],[-3,-3],[-7,-3],[-9,-5],[-2,4],[-3,4],[-8,9],[-1,2],[5,1],[2,3],[5,4],[-1,2],[-4,3],[-1,2],[2,4],[6,1],[8,-1],[3,-5],[-1,-2],[0,-1]],[[872,748],[-11,0],[-7,1],[-1,5],[1,0],[15,-2],[6,-1],[2,-1],[-1,-1],[-4,-1]],[[855,742],[-2,-1],[-12,0],[-3,1],[-1,1],[-17,1],[-7,4],[-2,2],[3,2],[6,1],[2,2],[15,1],[2,-1],[1,-2],[7,-4],[2,-3],[0,-2],[4,-1],[2,-1]],[[928,751],[-11,-3],[-3,1],[1,4],[-1,2],[-1,1],[1,2],[6,0],[18,-3],[2,-3],[-12,-1]],[[852,765],[11,-1],[7,1],[8,-2],[2,-1],[-1,-1],[-9,-1],[-4,-2],[-5,0],[-7,1],[-6,4],[4,2]],[[827,762],[-12,-1],[-5,1],[-1,2],[1,1],[18,2],[2,-2],[1,-1],[-4,-2]],[[900,769],[1,-1],[-5,1],[-6,3],[-1,1],[3,1],[3,-1],[4,-2],[1,-2]],[[922,770],[-3,-5],[-9,3],[-3,3],[2,3],[4,2],[5,-2],[2,0],[2,-4]],[[925,792],[-5,-1],[-8,4],[-5,3],[-2,2],[0,1],[0,1],[2,1],[11,-2],[7,-9]],[[9526,831],[-5,-7],[-4,0],[-2,1],[4,5],[3,1],[3,1],[1,-1]],[[966,823],[-4,0],[-5,1],[-14,5],[-3,2],[2,2],[5,2],[4,-1],[10,-4],[2,-3],[2,-2],[1,-2]],[[9554,874],[-4,0],[-2,1],[-1,4],[0,2],[8,4],[5,2],[-3,-8],[-1,-1],[-2,-4]],[[1322,896],[-4,-3],[-9,2],[1,2],[8,2],[5,-1],[-1,-2]],[[1359,888],[-3,-1],[-12,3],[-6,0],[-3,2],[-2,1],[-1,2],[-3,2],[6,4],[5,2],[4,0],[1,-3],[9,-2],[8,0],[0,-3],[0,-3],[-3,-4]],[[1462,886],[-4,-1],[-9,3],[-2,2],[-3,3],[-2,1],[0,1],[-1,8],[2,1],[5,-2],[11,-4],[7,-1],[2,-3],[-2,-6],[-4,-2]],[[1757,912],[-14,-2],[-3,2],[-1,2],[0,3],[28,12],[5,-1],[1,-1],[-8,-7],[-4,-2],[2,-1],[0,-1],[-1,-2],[-5,-2]],[[1679,915],[-6,-1],[-2,1],[-1,1],[-1,1],[3,3],[3,1],[1,1],[-4,10],[4,1],[4,1],[8,0],[7,-2],[2,-1],[1,-2],[-3,-6],[-2,-1],[-11,-5],[-3,-2]],[[1651,936],[5,-6],[2,-4],[1,-4],[-20,-10],[-1,0],[-1,-5],[1,-2],[1,0],[0,-2],[-2,-1],[-34,-4],[-16,4],[-2,2],[-1,4],[2,0],[4,1],[-1,2],[-2,2],[-1,3],[5,6],[3,2],[-9,5],[-2,1],[-1,1],[-4,-1],[-4,1],[1,2],[1,4],[4,3],[3,0],[3,0],[13,0],[13,-2],[13,-1],[21,-1],[5,0]],[[4427,928],[-1,-13],[0,-2],[1,-3],[5,-7],[1,-5],[-1,-2],[-2,-3],[-6,1],[-3,1],[0,1],[-4,13],[-2,2],[-3,3],[-13,2],[-12,-1],[3,3],[18,4],[5,3],[3,3],[1,6],[3,6],[5,3],[3,0],[2,-5],[0,-5],[-3,-5]],[[9717,944],[-4,-1],[-5,4],[-1,1],[5,7],[-1,2],[1,2],[2,2],[1,-1],[3,-7],[2,-4],[-3,-3],[0,-2]],[[1491,963],[7,-2],[3,-2],[3,-2],[3,-1],[3,-3],[2,-5],[2,-1],[5,-3],[1,-3],[0,-2],[-9,-1],[-3,1],[-3,-1],[-1,-2],[0,-2],[1,-1],[4,-1],[3,0],[7,1],[2,0],[4,-1],[3,-1],[8,5],[2,1],[2,0],[12,-6],[2,-3],[-1,-1],[-2,-2],[1,-2],[5,-2],[3,-3],[1,-1],[0,-2],[-1,-3],[0,-3],[-3,-2],[-1,0],[-6,2],[-19,1],[-6,1],[-9,6],[-4,1],[-3,1],[-6,5],[-10,4],[-6,4],[0,4],[-1,3],[-1,1],[-1,1],[-4,0],[-3,0],[-2,-1],[-3,-3],[-3,0],[-3,0],[0,1],[0,7],[-3,1],[-2,3],[-1,4],[1,4],[4,5],[4,0],[4,-1],[4,1],[6,1],[8,0]],[[2948,959],[-3,-2],[-2,1],[-3,3],[0,2],[2,2],[1,1],[6,7],[4,0],[4,-1],[-4,-6],[-1,-4],[-4,-3]],[[2096,970],[-3,-3],[-7,1],[-4,4],[-2,6],[-1,2],[2,1],[3,2],[12,-13]],[[2934,973],[-4,-7],[0,-1],[-4,-2],[1,-2],[1,-1],[1,-2],[2,-3],[3,-3],[-2,-5],[-4,-3],[-37,16],[-2,3],[-2,1],[-1,3],[0,3],[1,3],[1,1],[3,2],[4,0],[7,-3],[1,0],[2,3],[4,0],[1,3],[-6,0],[-4,3],[-3,2],[-1,2],[10,3],[25,-4],[4,-1],[1,-2],[2,-3],[-4,-6]],[[2394,984],[-4,0],[-4,2],[0,1],[1,2],[2,0],[5,-3],[1,-2],[-1,0]],[[2468,969],[-6,-2],[-4,1],[1,13],[3,3],[-1,3],[-4,6],[-4,8],[2,2],[9,2],[9,0],[4,-3],[2,-5],[-1,-2],[-3,-6],[3,-1],[1,-4],[-1,-4],[-3,-6],[-3,-3],[-4,-2]],[[2360,998],[-5,0],[-2,1],[2,3],[13,5],[5,3],[1,-1],[0,-1],[3,-5],[0,-2],[-17,-3]],[[4552,998],[-2,-2],[-4,0],[-3,3],[-2,4],[0,3],[1,3],[3,1],[2,-1],[3,-7],[2,-4]],[[6901,1019],[-1,0],[0,3],[4,4],[3,5],[1,1],[4,-5],[-1,-3],[-4,-3],[-6,-2]],[[4652,1027],[-2,-2],[-4,1],[-4,3],[-2,2],[-1,2],[2,3],[1,1],[2,-1],[5,-3],[2,-4],[1,-2]],[[6941,1041],[-3,-7],[-1,0],[-2,5],[1,2],[2,2],[3,-1],[0,-1]],[[2275,1042],[-2,-6],[0,-6],[7,0],[3,11],[6,2],[3,-6],[-3,-6],[2,-3],[2,-2],[3,0],[3,3],[1,2],[1,3],[2,6],[6,5],[13,1],[8,-3],[-5,-9],[-12,-5],[-7,-5],[2,-2],[3,0],[2,0],[7,3],[16,5],[6,3],[2,0],[0,-6],[2,-5],[-1,-9],[-7,-2],[-7,0],[2,-5],[-1,-1],[0,-2],[-18,2],[-3,0],[-3,-2],[-3,1],[-7,3],[-3,0],[-6,-2],[-7,0],[-9,0],[-7,0],[-6,4],[-7,0],[-7,1],[-8,3],[-7,2],[-9,4],[-3,1],[-2,1],[-5,0],[-34,6],[-6,-1],[-3,0],[-3,0],[-7,3],[-1,3],[0,3],[2,1],[3,2],[48,6],[5,2],[4,0],[2,-6],[5,-6],[1,0],[1,1],[5,5],[9,-2],[4,3],[4,4],[9,5],[7,-1],[5,-2],[3,-5]],[[4917,1082],[-3,-1],[-3,0],[-3,2],[-3,3],[0,1],[0,3],[0,1],[4,0],[1,-1],[1,-1],[6,-7]],[[3318,1091],[-3,0],[-4,1],[-3,2],[-1,2],[1,2],[3,1],[5,0],[2,-3],[1,-2],[-1,-2],[0,-1]],[[4929,1108],[3,-2],[5,0],[4,-1],[0,-2],[-3,-3],[-2,-6],[-2,-2],[-7,-6],[-5,-1],[-1,3],[0,3],[1,2],[0,2],[-5,3],[0,3],[-1,2],[-13,7],[-3,1],[1,2],[14,0],[8,-1],[6,-4]],[[2952,1115],[5,-5],[-4,-4],[-15,-7],[-8,-3],[-8,-2],[-38,-7],[-3,0],[-3,1],[-1,1],[-3,6],[1,3],[3,2],[4,2],[6,2],[23,3],[2,2],[2,2],[0,3],[1,3],[2,1],[1,0],[3,-2],[6,-10],[2,2],[1,2],[0,8],[2,1],[5,-2],[3,-3],[0,5],[2,1],[2,0],[3,-1],[4,-4]],[[3312,1111],[-2,0],[-2,1],[-2,4],[0,1],[1,4],[1,1],[10,1],[2,-2],[1,-4],[-2,-2],[-7,-4]],[[4836,1120],[-7,-3],[-1,1],[-3,2],[-4,6],[5,0],[5,3],[3,-1],[0,-1],[2,-7]],[[5084,1118],[-10,-2],[-2,2],[-1,3],[2,2],[12,7],[3,-1],[1,0],[1,-3],[-1,-4],[-1,-2],[-4,-2]],[[4908,1121],[-4,0],[-1,2],[-1,1],[6,8],[3,2],[7,2],[4,-1],[2,-2],[1,-3],[0,-5],[-2,-2],[-15,-2]],[[3008,1137],[1,-2],[6,2],[3,-2],[0,-1],[-3,-5],[-3,-2],[-4,-1],[-2,8],[-1,1],[3,2]],[[6999,1115],[-2,0],[-2,1],[-3,4],[-2,3],[-1,3],[0,7],[2,3],[3,1],[1,-3],[0,-3],[1,-2],[3,-3],[2,-3],[0,-1],[1,-3],[-1,-2],[-2,-2]],[[5125,1124],[-4,-1],[-5,3],[-2,2],[-1,5],[0,2],[1,2],[4,1],[6,-1],[3,-2],[1,-4],[-1,-4],[-2,-3]],[[5745,1130],[-1,-2],[-5,0],[-4,-2],[-3,1],[-10,3],[-1,5],[-1,2],[1,3],[9,8],[3,0],[5,-1],[3,-2],[1,-4],[4,-8],[-1,-3]],[[5036,1137],[-3,-7],[-1,0],[-2,4],[-3,5],[-1,3],[0,4],[2,3],[8,2],[3,-1],[1,-6],[-4,-7]],[[3301,1153],[-4,0],[-2,2],[-1,1],[0,2],[2,2],[5,-1],[1,-5],[-1,-1]],[[2917,1168],[5,-2],[7,-6],[2,-3],[1,-2],[-1,-1],[-3,-2],[-3,-8],[-4,-2],[-12,1],[-13,3],[-1,1],[-1,3],[0,3],[1,4],[2,2],[10,2],[1,1],[1,4],[2,1],[2,0],[4,1]],[[5450,1151],[-2,-3],[-8,5],[-5,1],[-2,1],[-1,4],[0,1],[1,2],[3,3],[5,3],[10,1],[9,-1],[1,-2],[-8,-5],[-3,-10]],[[3000,1169],[-6,-2],[-4,2],[-12,3],[-5,7],[1,4],[2,2],[4,1],[7,-3],[4,-2],[9,-12]],[[3278,1168],[-3,-1],[-2,6],[-2,8],[-7,12],[-2,6],[1,2],[2,0],[6,-2],[3,-2],[4,-5],[5,-4],[0,-4],[0,-4],[-3,-1],[0,-3],[-2,-6],[0,-2]],[[3054,1199],[-1,-7],[5,2],[1,0],[4,-3],[8,-15],[2,-5],[4,-14],[3,-10],[11,-19],[4,-10],[3,-5],[0,-8],[3,-2],[1,-4],[1,-10],[1,-13],[0,-23],[0,-6],[-4,-9],[-2,-6],[-2,-4],[-3,-3],[-14,-13],[-2,-6],[-23,-5],[-14,-3],[-5,3],[-5,0],[-7,0],[-19,-1],[-15,-2],[-1,1],[-2,2],[-1,2],[-4,-1],[-3,1],[-3,2],[-3,4],[-2,2],[0,2],[6,6],[3,2],[4,0],[6,-1],[7,-2],[15,-2],[20,0],[6,0],[6,2],[7,6],[-3,2],[-4,1],[-3,0],[-3,0],[-8,-3],[-6,-2],[-7,-2],[-7,2],[-6,6],[0,2],[22,4],[2,1],[4,2],[1,3],[0,2],[-14,4],[-3,0],[-3,-1],[-7,2],[-7,5],[-5,5],[-3,1],[-2,-2],[-14,-15],[-1,0],[-6,1],[-6,3],[-7,1],[-4,-1],[-1,-1],[4,-3],[3,-3],[1,-3],[-10,-7],[-3,-1],[-4,1],[-2,1],[-3,4],[-3,1],[-6,-1],[-4,0],[-3,2],[-3,2],[-3,2],[-4,3],[-2,2],[-1,3],[0,2],[1,2],[0,2],[0,2],[0,2],[1,2],[6,3],[6,1],[6,-4],[5,-2],[2,0],[0,1],[1,1],[0,2],[-2,4],[0,3],[2,2],[2,1],[2,1],[1,0],[4,-1],[3,-2],[6,-4],[5,-4],[2,0],[1,1],[1,2],[-6,5],[0,2],[0,3],[4,2],[2,0],[10,-3],[6,-1],[5,0],[12,3],[-6,3],[-13,3],[-3,3],[-2,3],[10,3],[10,0],[18,-4],[5,2],[6,6],[3,1],[13,0],[10,2],[1,0],[2,-1],[10,-9],[1,0],[1,2],[0,3],[0,4],[0,3],[-1,2],[-2,0],[-2,-1],[-2,1],[-3,2],[-3,1],[-10,1],[-7,2],[-4,1],[-3,3],[-1,3],[4,7],[14,8],[6,2],[7,1],[3,-1],[8,-3],[1,0],[1,1],[-7,5],[-7,4],[-3,4],[-3,1],[-11,1],[-5,-3],[-3,-1],[-3,1],[-16,7],[-1,1],[-2,3],[-1,2],[-1,3],[0,4],[1,2],[2,9],[2,7],[-1,6],[-3,3],[-3,3],[-4,3],[0,3],[-1,2],[0,4],[1,3],[1,3],[2,2],[3,2],[14,4],[27,5],[3,-3],[4,-5],[1,-2],[2,-11],[0,-2]],[[2485,1221],[-1,0],[-1,0],[-1,0],[0,1],[0,1],[0,1],[0,1],[0,1],[1,0],[1,0],[1,0],[0,-1],[0,-1],[0,-1],[0,-1],[0,-1]],[[3315,1223],[-1,-2],[-4,1],[-2,1],[-3,3],[2,2],[3,-1],[3,-1],[2,-3]],[[3129,1281],[-6,-2],[-4,2],[0,4],[-1,1],[0,1],[5,3],[4,1],[5,-1],[2,-1],[0,-2],[-3,-3],[-1,-2],[-1,-1]],[[9578,1294],[-3,-2],[-1,0],[-2,4],[2,5],[-1,7],[1,2],[4,-4],[0,-2],[2,-3],[0,-2],[-1,-3],[-1,-2]],[[3129,1331],[-2,-1],[-3,1],[-2,1],[3,4],[-1,3],[3,1],[2,-1],[2,-4],[0,-1],[-2,-3]],[[7383,1327],[-5,-1],[0,1],[0,1],[-8,5],[-1,5],[1,3],[6,-1],[7,-2],[3,-7],[-3,-4]],[[6348,1337],[-5,-1],[-2,0],[0,2],[0,1],[0,2],[2,1],[7,0],[4,-1],[0,-1],[1,-2],[-1,-1],[-6,0]],[[9535,1335],[0,-3],[-2,0],[-2,3],[-2,7],[2,1],[2,-2],[1,-3],[1,-2],[0,-1]],[[7403,1338],[-3,-1],[-2,0],[-3,3],[1,2],[3,1],[4,0],[1,-1],[2,-1],[-3,-3]],[[3111,1297],[-3,-3],[-2,-1],[-2,1],[-2,0],[-2,-1],[-1,-6],[-2,-3],[-2,-2],[-1,1],[-2,0],[-2,-1],[-2,-1],[-2,1],[-2,4],[-4,4],[0,1],[-1,4],[0,4],[2,2],[7,10],[2,5],[3,5],[2,4],[4,8],[2,3],[12,8],[3,2],[3,0],[1,-5],[-2,-2],[-5,-5],[-1,-8],[0,-3],[0,-1],[2,-1],[2,-1],[1,-2],[2,-2],[-4,-4],[-3,-2],[-2,-3],[-4,-2],[-2,-2],[3,0],[4,-2],[1,-2],[-1,-2]],[[7370,1347],[-3,-2],[-3,1],[-1,1],[-1,2],[2,3],[1,0],[1,-2],[4,-3]],[[7745,1355],[-3,0],[-2,1],[-2,3],[0,1],[4,1],[6,-3],[-3,-3]],[[9516,1355],[-1,-3],[-2,0],[-6,7],[1,3],[-1,3],[0,2],[1,1],[7,-11],[1,-2]],[[7784,1370],[-3,-1],[-2,2],[3,4],[3,1],[0,-4],[-1,-2]],[[3150,1371],[-6,-7],[-1,1],[-1,0],[0,1],[2,3],[1,7],[4,2],[1,0],[-1,-3],[1,-3],[0,-1]],[[7683,1380],[3,-1],[6,0],[2,-2],[0,-3],[0,-1],[-2,-2],[-15,-2],[-3,3],[3,6],[3,2],[3,0]],[[7572,1393],[-4,0],[-4,0],[-2,3],[0,1],[1,2],[6,0],[3,-1],[1,-2],[0,-1],[-1,-2]],[[3171,1391],[-6,-2],[-4,1],[0,2],[1,3],[3,2],[-1,5],[2,1],[1,4],[4,3],[5,-2],[0,-4],[0,-2],[-4,-1],[0,-1],[-1,-3],[0,-4],[0,-2]],[[7804,1401],[-12,-1],[-1,1],[-4,0],[-2,1],[0,3],[1,5],[2,3],[4,3],[2,1],[8,1],[5,-1],[4,-4],[1,-3],[-1,-3],[-7,-6]],[[7871,1414],[-1,-1],[-5,1],[-1,1],[0,5],[-1,2],[-1,1],[-8,3],[0,4],[1,2],[2,0],[7,-3],[2,-3],[-1,-4],[0,-1],[3,-3],[3,-3],[0,-1]],[[3241,1448],[-4,-3],[-3,0],[3,7],[2,0],[5,3],[1,0],[-2,-3],[-2,-4]],[[3410,1465],[-3,0],[-3,1],[0,3],[0,2],[2,1],[2,0],[8,5],[3,1],[-1,-2],[0,-3],[-1,-2],[-7,-6]],[[3245,1470],[-3,-6],[4,1],[3,2],[3,1],[2,-3],[-5,-3],[-5,-4],[-2,-2],[-2,-1],[-3,1],[-3,-1],[-2,-4],[-3,-2],[-1,2],[-1,1],[-5,1],[-3,2],[-2,2],[-3,0],[2,4],[1,3],[9,4],[-1,1],[-1,2],[7,2],[0,2],[0,3],[2,1],[2,3],[1,0],[4,0],[3,-3],[-1,-3],[3,-6]],[[3268,1473],[-2,-2],[-1,-1],[-2,1],[-2,-3],[-4,1],[-1,1],[1,0],[0,2],[3,3],[3,8],[1,2],[-3,4],[-1,2],[1,2],[1,2],[3,2],[3,0],[2,-2],[0,-3],[6,-2],[-1,-6],[-2,-4],[-1,-4],[-3,-2],[-1,-1]],[[3279,1493],[-3,0],[1,3],[2,2],[4,1],[-2,-3],[-1,-2],[-1,-1]],[[3393,1494],[1,0],[1,0],[1,1],[1,2],[3,2],[3,1],[-1,-3],[7,-5],[0,-4],[1,-3],[-3,-1],[-2,-4],[2,-1],[1,-3],[-2,0],[-6,1],[-3,0],[1,3],[-1,1],[-4,-1],[-1,-6],[-1,0],[-1,1],[1,3],[-2,1],[-1,0],[-4,-3],[-1,0],[-3,3],[8,5],[-3,2],[-1,2],[0,4],[-2,-1],[-3,-1],[-1,0],[-2,1],[1,3],[2,4],[2,4],[4,3],[2,1],[2,1],[2,2],[2,0],[2,-4],[0,-2],[-2,-3],[0,-6]],[[3406,1509],[0,-1],[6,0],[1,-1],[-3,-2],[-1,0],[-2,-1],[-8,2],[-2,2],[7,2],[2,-1]],[[3315,1505],[-4,-2],[-2,1],[-3,2],[5,1],[0,7],[2,3],[4,-2],[-2,-4],[-1,-2],[1,-3],[0,-1]],[[3448,1524],[-3,-2],[-6,4],[-1,2],[0,2],[10,2],[3,-1],[1,-4],[-4,-3]],[[0,325],[45,1],[9,-1],[9,-2],[21,0],[19,-2],[5,-3],[7,-2],[13,2],[11,1],[9,0],[82,-5],[85,-8],[17,-2],[15,-6],[17,0],[95,-4],[15,0],[59,-5],[102,-12],[9,0],[10,0],[-5,6],[-10,6],[-13,4],[9,1],[18,0],[-4,3],[-10,2],[-36,2],[-147,14],[-3,1],[-2,1],[-4,1],[-6,2],[-22,1],[-6,1],[-3,2],[1,0],[2,0],[34,1],[4,2],[0,1],[-2,1],[-5,1],[-14,5],[-5,2],[3,3],[2,1],[11,1],[3,3],[-2,4],[-24,8],[-16,3],[-11,-2],[-20,0],[-25,-2],[-7,2],[-7,3],[-8,5],[-5,2],[-7,5],[-11,4],[-56,11],[-10,3],[-70,18],[-3,3],[-2,3],[32,-7],[7,0],[7,2],[5,-1],[8,2],[8,1],[22,-6],[44,-8],[12,-4],[6,-2],[6,0],[5,-2],[6,1],[4,-1],[9,1],[42,1],[16,-1],[20,-5],[8,-7],[5,-3],[11,3],[9,3],[17,2],[6,-1],[9,-4],[10,-6],[45,2],[19,0],[13,-3],[48,9],[8,2],[11,7],[-9,2],[-7,0],[-2,4],[4,1],[14,2],[28,3],[16,2],[8,7],[37,11],[12,5],[11,8],[-25,16],[-23,13],[8,4],[7,4],[3,2],[3,4],[-7,4],[-7,4],[-12,3],[-44,8],[-15,3],[6,5],[8,4],[17,2],[108,6],[108,7],[3,4],[-14,4],[-13,1],[-4,2],[-2,2],[0,4],[-1,1],[-5,0],[-19,5],[-5,1],[-6,4],[-2,4],[4,8],[6,3],[11,2],[7,1],[23,0],[8,1],[4,1],[-1,4],[-2,2],[0,2],[4,1],[4,0],[2,3],[-3,5],[-7,2],[-17,5],[-40,6],[-16,5],[-9,4],[-7,4],[-8,2],[-5,3],[1,2],[-2,5],[-3,1],[-13,-2],[-22,1],[-28,4],[-19,5],[-26,12],[-9,7],[7,4],[8,3],[33,6],[5,2],[7,6],[-11,3],[-10,-1],[-8,2],[-34,0],[-20,0],[-16,7],[-12,7],[-3,4],[-3,6],[4,9],[4,7],[-1,8],[1,12],[6,3],[4,1],[11,-9],[9,0],[13,1],[8,5],[5,2],[8,0],[15,-2],[8,1],[8,-1],[25,-5],[5,-3],[3,-2],[1,-3],[3,-3],[11,-2],[30,2],[8,-1],[21,-8],[18,-9],[6,-3],[10,-1],[4,1],[3,4],[10,4],[21,5],[5,5],[-2,3],[-9,3],[-5,1],[-3,3],[1,5],[1,5],[6,1],[10,-6],[13,-6],[5,-1],[3,0],[7,2],[8,2],[15,-12],[8,-1],[11,0],[2,1],[-1,4],[-2,3],[-2,1],[0,3],[5,3],[3,1],[-2,2],[-5,4],[-3,0],[-3,2],[1,2],[4,1],[5,3],[-2,4],[0,5],[-2,3],[-11,5],[-17,9],[-16,4],[-35,-3],[-12,2],[-8,2],[-9,3],[10,3],[11,3],[3,2],[4,4],[5,3],[4,0],[13,-1],[29,-11],[6,-1],[20,-5],[5,0],[7,1],[-6,5],[-6,3],[-14,10],[1,4],[10,8],[24,0],[11,3],[14,6],[18,9],[15,2],[19,3],[7,-3],[16,-9],[10,-3],[4,0],[4,0],[-10,11],[6,2],[8,1],[7,3],[5,3],[17,11],[15,3],[42,5],[15,-5],[12,0],[3,1],[2,6],[7,11],[5,4],[19,5],[14,0],[11,-5],[9,-3],[9,-2],[9,0],[14,3],[17,1],[9,1],[9,-2],[24,-1],[18,-4],[12,0],[15,4],[8,0],[30,6],[24,1],[17,-2],[29,1],[29,-1],[11,-2],[66,1],[51,6],[8,2],[11,6],[6,5],[4,2],[9,1],[14,-2],[21,-4],[18,2],[33,-3],[3,2],[4,11],[5,16],[5,5],[8,-1],[23,-10],[0,-4],[-2,-2],[-4,-2],[-1,-8],[3,-2],[5,1],[4,-4],[-8,-6],[-5,-3],[-3,-2],[-2,-11],[-4,-4],[0,-4],[5,0],[5,2],[4,0],[14,3],[26,4],[8,1],[5,1],[3,2],[-4,6],[-1,5],[2,3],[-1,7],[-2,7],[5,5],[5,-1],[7,1],[5,-3],[7,-2],[6,-1],[7,-5],[2,-9],[-2,-10],[-7,-8],[-12,-6],[-13,-11],[3,-5],[7,2],[31,-1],[19,1],[13,-1],[16,-3],[12,-4],[15,0],[9,1],[9,-2],[34,9],[14,4],[8,-2],[12,2],[8,-2],[13,3],[8,0],[10,-1],[30,0],[2,-6],[9,-8],[7,-3],[9,1],[7,3],[11,-1],[15,3],[15,-1],[7,1],[3,2],[2,5],[-5,3],[-13,3],[-12,8],[-6,1],[-9,-1],[-4,2],[-4,2],[6,3],[7,9],[-3,9],[-4,2],[-8,-1],[-9,-3],[-4,2],[-7,2],[-2,7],[-7,15],[-4,4],[-10,4],[-10,2],[-9,2],[-3,6],[2,8],[11,2],[10,-1],[6,-2],[7,0],[8,-2],[5,-2],[4,-1],[7,-1],[26,3],[4,1],[3,3],[5,1],[5,-1],[8,2],[-9,2],[-9,5],[-14,5],[-11,3],[-21,2],[-11,-1],[-6,1],[-24,0],[-7,2],[-4,5],[-7,14],[-2,8],[5,2],[3,3],[7,0],[10,-1],[3,-1],[3,-4],[-3,-5],[-3,-2],[2,-2],[11,-1],[5,-1],[4,-1],[10,2],[14,1],[7,-2],[9,-1],[12,2],[45,-1],[5,-1],[6,-4],[4,-2],[5,1],[15,-5],[7,-3],[8,-2],[7,-1],[7,1],[10,3],[8,1],[6,-1],[12,0],[10,-4],[7,2],[8,4],[24,3],[17,-1],[29,-8],[7,0],[14,4],[4,7],[0,8],[4,2],[3,-1],[6,6],[8,0],[5,-2],[3,4],[3,8],[10,0],[7,-1],[9,-5],[0,-4],[-4,-4],[-6,-11],[4,-6],[6,0],[7,-1],[9,3],[6,0],[10,-9],[7,-1],[5,1],[17,8],[5,1],[6,-4],[9,-9],[8,-5],[12,-3],[9,-1],[12,-4],[6,-4],[15,0],[6,-1],[18,-7],[16,3],[8,4],[4,6],[-2,9],[-1,9],[3,4],[4,1],[19,-11],[-1,6],[-2,5],[-5,8],[1,6],[4,2],[8,-3],[10,-2],[8,-3],[15,-13],[5,-11],[11,-3],[7,1],[8,1],[11,2],[9,0],[8,2],[2,-7],[-7,-8],[-3,-6],[2,-2],[5,2],[4,2],[13,-1],[10,4],[9,1],[8,4],[7,0],[5,-1],[8,-3],[7,2],[4,-1],[5,0],[30,14],[7,0],[8,1],[11,3],[8,2],[7,0],[12,5],[19,-1],[10,3],[19,3],[13,4],[23,10],[9,6],[10,13],[6,12],[7,18],[-3,11],[-4,5],[-3,5],[-7,11],[-2,14],[1,13],[-3,12],[-3,9],[-5,16],[-7,10],[-7,13],[0,12],[-2,9],[-5,7],[-2,6],[4,1],[3,1],[9,2],[21,-3],[2,5],[6,4],[3,5],[-1,8],[-5,3],[-5,7],[2,5],[5,0],[2,5],[-2,6],[2,7],[5,9],[2,3],[-5,6],[-5,7],[2,5],[2,6],[3,8],[4,6],[3,1],[-1,2],[-6,2],[-6,1],[-10,-4],[-2,1],[0,2],[-1,4],[1,9],[2,9],[1,1],[4,2],[4,6],[4,1],[2,-2],[1,-10],[1,-2],[-1,-4],[2,-2],[2,3],[4,2],[2,-3],[2,-2],[0,3],[0,7],[-1,3],[0,5],[0,2],[1,4],[-1,8],[0,3],[4,4],[2,1],[3,0],[7,-3],[3,0],[2,1],[1,3],[1,10],[-2,4],[0,3],[1,2],[3,7],[4,0],[4,-1],[4,2],[-1,2],[-1,5],[4,2],[3,0],[8,-2],[3,-2],[3,4],[-1,3],[-3,2],[-1,3],[1,4],[5,-2],[1,1],[1,3],[-1,2],[0,2],[6,0],[1,1],[1,3],[2,1],[6,0],[1,1],[1,3],[-4,1],[-4,3],[0,8],[1,6],[3,5],[5,3],[7,-3],[6,1],[3,-3],[3,-1],[1,3],[-2,3],[-1,5],[10,6],[3,-1],[4,1],[-2,5],[2,6],[3,0],[2,-4],[3,-2],[3,2],[7,5],[3,1],[4,1],[3,3],[1,4],[2,3],[6,4],[3,2],[5,10],[-1,2],[2,2],[16,9],[8,1],[14,5],[8,6],[5,2],[4,7],[6,1],[13,5],[9,8],[14,5],[6,0],[2,-2],[2,-6],[2,-8],[4,-4],[-1,-3],[-4,0],[-4,-1],[-1,4],[2,3],[-2,3],[-4,-1],[-4,-1],[-4,-2],[-4,-4],[-3,-3],[-12,-6],[-7,-9],[-6,-9],[-3,-6],[-4,-1],[-2,-2],[2,-2],[2,-1],[3,0],[0,-3],[-3,-1],[1,-2],[2,-3],[1,-5],[-3,0],[-5,5],[-5,0],[-3,2],[-3,4],[-2,-1],[-2,-5],[1,-5],[-2,-3],[-3,1],[0,7],[-3,1],[-3,0],[-8,-7],[-2,0],[-2,-4],[-4,-3],[-3,-3],[-7,-11],[-4,-4],[-8,-2],[-3,0],[-2,1],[-3,1],[-2,0],[-1,-3],[4,-9],[-2,-3],[-6,0],[-2,3],[-2,-2],[-2,-3],[-2,-3],[3,-7],[4,-4],[3,0],[1,-3],[-6,-1],[-5,-6],[-2,-5],[-2,-4],[0,-4],[4,-7],[4,-4],[5,-1],[6,2],[1,1],[6,1],[3,4],[2,1],[1,-1],[3,0],[2,3],[2,1],[2,-1],[6,0],[1,-3],[-1,-3],[-4,-4],[-3,3],[-3,-1],[-1,-2],[3,-5],[-1,-4],[-3,-4],[-2,3],[-1,4],[-4,3],[-4,1],[-2,-5],[-5,-1],[0,-5],[-2,-5],[-2,1],[-1,6],[-7,5],[-3,1],[-7,-1],[-3,0],[-2,-1],[-3,-5],[3,-3],[1,-4],[0,-3],[0,-1],[-1,-3],[3,-3],[1,-5],[-3,0],[-2,1],[-8,13],[-5,6],[-2,5],[-6,1],[-4,0],[-4,-2],[2,-2],[1,-4],[-3,-1],[-4,-6],[-2,-5],[-2,-1],[-1,-2],[7,-7],[1,-2],[1,-4],[-3,-2],[-5,-1],[-10,4],[-4,0],[-2,3],[-2,0],[-2,-5],[-1,-5],[-2,-3],[0,-4],[2,-1],[-1,-2],[-4,-2],[-2,-2],[5,-1],[1,-2],[0,-2],[-7,-2],[-5,0],[-3,2],[-2,-1],[-2,-3],[0,-4],[0,-5],[1,-3],[1,-1],[1,-3],[-5,-8],[0,-1],[-1,-4],[2,-3],[2,-4],[-2,-3],[-3,-4],[3,-1],[4,-1],[5,1],[7,4],[2,1],[1,-2],[1,-2],[-2,-3],[-13,-6],[-2,-3],[3,-2],[7,0],[2,-2],[-1,-3],[-3,-2],[-3,-5],[3,-2],[7,-4],[13,-4],[10,-1],[-2,5],[-1,6],[7,4],[4,2],[16,3],[4,0],[4,-1],[-2,-3],[-4,1],[-6,-2],[-10,-5],[-2,-2],[1,-4],[8,-4],[3,-3],[-4,-8],[1,-5],[4,-6],[6,-6],[3,-4],[4,-3],[7,-6],[4,-6],[1,-14],[6,-12],[7,-5],[0,-5],[-2,-4],[-6,2],[-3,-2],[-1,-5],[4,-4],[6,-4],[14,1],[1,-5],[-4,-3],[-2,-3],[-3,-2],[-5,-1],[-2,-4],[3,-6],[7,3],[5,0],[6,-1],[1,-8],[7,-9],[1,-5],[-1,-4],[-4,-1],[-2,-4],[-4,-3],[-4,-1],[-8,-8],[-3,-1],[-1,-2],[6,0],[5,-1],[9,7],[4,-2],[2,-4],[2,-5],[-3,-4],[-17,-2],[-8,-3],[-9,-6],[10,-3],[8,1],[4,-1],[5,-3],[5,1],[5,3],[3,0],[3,-1],[0,-5],[1,-7],[1,-5],[-2,-4],[-9,-2],[-7,0],[0,-8],[10,-6],[6,3],[5,-1],[0,-9],[4,-10],[4,-1],[3,5],[4,0],[1,-6],[-1,-9],[-3,-5],[-8,2],[-5,2],[-3,-3],[-6,-3],[-5,-1],[-4,5],[-6,3],[-8,2],[-8,1],[3,-4],[3,-3],[2,-7],[3,-7],[6,2],[9,-4],[6,-4],[2,-6],[-3,-9],[-5,-3],[-3,-2],[-6,4],[-4,0],[-4,-2],[-1,-4],[-3,-2],[14,-1],[5,-1],[3,-4],[-5,-4],[-10,0],[-4,-2],[-3,-3],[14,-2],[6,1],[9,4],[2,-4],[-3,-4],[-5,-6],[-10,-2],[-8,0],[-9,2],[-3,1],[-4,1],[0,-4],[3,-2],[6,-10],[1,-3],[-2,-5],[-5,-4],[-7,-1],[-5,3],[-4,9],[-5,3],[-5,0],[-3,0],[0,-5],[1,-4],[-2,-4],[-4,2],[-6,-2],[-5,-2],[-5,-3],[10,-2],[6,0],[5,-5],[-2,-2],[-9,-1],[-8,-2],[-12,-5],[9,-2],[8,0],[5,0],[5,-1],[2,-3],[-3,-3],[-20,-7],[-20,-10],[-7,-2],[-8,-2],[-18,-8],[-11,-3],[-32,-6],[-49,-14],[-17,-10],[-5,-7],[-4,-2],[-9,-2],[-10,-1],[-25,-1],[-25,4],[-21,0],[-12,-1],[-38,7],[-5,0],[-6,-2],[-5,0],[-3,1],[-8,1],[-26,-3],[-3,-4],[3,-8],[10,-9],[16,-16],[8,-4],[6,-3],[10,-5],[22,0],[31,-3],[17,-3],[-1,-6],[-10,-12],[-7,-4],[-15,-8],[-21,-4],[-17,1],[-29,7],[-36,6],[-54,5],[-11,3],[-14,2],[-8,-2],[-6,-3],[-13,0],[3,-2],[54,-16],[46,-11],[5,-3],[7,-2],[-1,-7],[-2,-6],[-9,-5],[-24,0],[-29,-4],[-15,0],[-14,4],[-31,11],[-19,8],[-13,10],[-9,8],[-10,7],[0,-5],[2,-4],[5,-6],[7,-6],[1,-3],[-4,0],[-5,3],[-4,-3],[-2,-3],[2,-5],[3,-4],[9,-9],[8,-3],[11,-6],[25,-10],[5,-4],[8,-8],[1,-6],[8,-5],[5,-1],[5,0],[1,5],[0,6],[2,2],[7,1],[20,-2],[82,-1],[8,-4],[3,-4],[2,-10],[-9,-11],[-6,-5],[-10,-2],[-8,-3],[-14,-1],[-27,1],[-27,0],[21,-5],[20,-5],[28,1],[12,1],[9,2],[4,-3],[8,-8],[5,-3],[3,-2],[4,-9],[2,-5],[4,-5],[3,-5],[4,-4],[8,-1],[8,3],[16,1],[15,-5],[10,-1],[13,4],[11,5],[22,5],[4,2],[6,1],[9,0],[4,-1],[4,-5],[5,-7],[6,-4],[7,-2],[3,-1],[13,-2],[16,2],[8,-2],[1,-4],[4,-3],[5,-1],[66,-18],[23,-4],[35,-2],[28,0],[4,-1],[5,-3],[-11,-3],[-11,0],[-17,1],[-6,-1],[-13,1],[-6,0],[-6,1],[-9,-3],[-17,-2],[4,-2],[6,-1],[12,-1],[18,1],[1,-5],[-16,-1],[-33,-1],[-4,0],[-2,-3],[5,-1],[3,-1],[1,-3],[-3,-8],[5,-5],[4,-1],[4,1],[7,-3],[7,-3],[15,0],[17,4],[9,0],[23,3],[20,-1],[29,5],[5,0],[4,-1],[-8,-4],[-35,-11],[-13,-2],[-5,-2],[3,-5],[5,-6],[9,-6],[6,-9],[6,-1],[11,4],[2,-3],[1,-7],[-3,-4],[-4,-3],[-3,-3],[-1,-4],[4,-3],[13,-1],[16,-1],[15,0],[9,-1],[35,19],[13,10],[7,3],[6,3],[28,12],[7,4],[8,5],[14,1],[19,9],[17,6],[7,1],[5,1],[6,1],[15,0],[11,1],[19,4],[14,3],[16,2],[17,1],[46,4],[13,-2],[15,-5],[10,1],[12,1],[9,2],[4,-6],[2,-6],[-5,-7],[-7,-4],[-1,-6],[9,-4],[11,1],[20,4],[17,4],[4,2],[7,0],[11,3],[13,15],[17,14],[15,10],[9,11],[8,6],[8,5],[6,2],[13,1],[19,7],[28,9],[21,-4],[22,-6],[11,5],[9,1],[7,2],[8,2],[5,4],[7,4],[5,5],[27,3],[29,4],[4,1],[3,-1],[10,1],[13,3],[17,1],[9,0],[8,8],[16,2],[18,3],[7,2],[6,1],[141,6],[6,3],[13,3],[4,6],[-19,3],[-5,2],[-7,1],[-4,-1],[-16,1],[-130,9],[-3,1],[-5,6],[1,10],[-4,8],[-9,2],[-9,0],[-12,-1],[-31,-4],[-13,-1],[-33,7],[-22,8],[-15,2],[-10,6],[-10,4],[-1,9],[3,8],[18,25],[12,12],[8,0],[7,6],[7,12],[6,5],[14,7],[5,2],[22,8],[5,0],[10,-1],[11,7],[33,15],[7,6],[9,4],[27,13],[24,6],[11,2],[15,4],[16,6],[14,6],[49,11],[30,3],[21,3],[14,-2],[14,1],[13,2],[5,3],[8,6],[28,-3],[18,4],[7,0],[8,2],[-3,2],[-3,0],[-3,3],[-3,6],[3,7],[3,4],[8,4],[5,7],[4,9],[13,19],[4,2],[9,1],[7,0],[8,0],[21,-5],[4,2],[7,5],[5,7],[12,10],[3,3],[-1,5],[-18,-2],[-14,-3],[-13,1],[-2,3],[3,2],[5,1],[2,3],[-5,3],[-8,2],[-3,2],[0,5],[2,8],[4,2],[4,3],[10,10],[5,4],[17,2],[19,-4],[4,1],[5,6],[-5,9],[-4,4],[0,2],[10,-1],[10,-2],[11,0],[12,9],[19,8],[8,3],[8,2],[4,7],[7,15],[4,7],[0,5],[-1,4],[-5,-1],[-4,-1],[-10,4],[-13,6],[-4,7],[-2,6],[4,3],[4,2],[4,1],[8,-3],[9,-6],[5,-2],[5,-5],[4,0],[4,7],[4,8],[3,3],[5,3],[6,4],[-3,4],[-5,2],[-1,2],[2,3],[5,1],[6,-6],[8,-4],[5,-1],[5,-4],[7,-10],[9,-18],[4,-1],[8,2],[9,1],[5,5],[1,13],[3,5],[-1,6],[-4,6],[-3,5],[0,3],[3,2],[4,1],[6,3],[10,-3],[6,-1],[8,2],[8,3],[9,3],[6,-2],[3,-6],[-3,-7],[-5,-5],[-5,-6],[-2,-6],[1,-3],[4,-1],[42,0],[5,0],[8,0],[7,-2],[14,1],[11,2],[6,0],[10,-2],[7,-5],[14,2],[4,1],[4,6],[4,1],[5,-5],[1,-11],[2,-5],[6,-5],[6,4],[4,5],[10,9],[10,8],[9,4],[20,7],[10,4],[19,6],[25,3],[45,11],[14,1],[24,3],[13,3],[12,2],[8,8],[17,-6],[6,0],[8,4],[9,12],[14,-5],[7,-7],[9,-6],[21,-11],[7,-2],[14,-2],[3,1],[7,7],[6,10],[5,5],[6,3],[7,6],[-2,3],[-4,1],[-4,1],[1,3],[12,1],[7,-10],[6,-4],[8,-3],[19,3],[16,0],[14,-2],[7,0],[6,8],[9,3],[6,-4],[4,-11],[12,-3],[27,-5],[3,1],[3,6],[2,7],[6,1],[7,4],[3,0],[6,-5],[-2,-11],[-3,-11],[3,-8],[4,-5],[4,-1],[6,0],[8,0],[6,0],[26,4],[3,10],[4,10],[10,14],[4,-1],[4,-1],[7,-7],[4,-3],[1,-5],[-5,-5],[1,-3],[5,-3],[15,-4],[4,1],[8,4],[7,9],[4,10],[6,-1],[6,-2],[4,-5],[0,-10],[5,-6],[5,-4],[12,-5],[13,-1],[9,-3],[15,1],[7,3],[4,1],[8,2],[9,6],[5,2],[19,6],[15,5],[15,11],[15,6],[23,3],[6,1],[9,0],[22,7],[8,4],[5,2],[5,5],[3,10],[2,7],[-1,6],[-2,8],[-4,7],[-5,10],[2,12],[4,5],[9,5],[10,1],[11,0],[9,-1],[1,-5],[-4,-6],[-5,-5],[-3,-3],[1,-4],[6,-1],[15,1],[5,-4],[10,-19],[3,-8],[4,-3],[5,1],[13,0],[9,2],[7,0],[3,-1],[4,-4],[7,-5],[8,3],[5,2],[6,0],[10,-6],[10,-13],[11,-7],[0,4],[-1,6],[4,4],[6,8],[7,10],[6,11],[2,15],[3,11],[5,6],[4,4],[8,4],[9,0],[9,9],[6,3],[13,5],[16,5],[12,13],[4,2],[6,2],[10,0],[18,5],[5,0],[9,4],[8,7],[6,3],[10,-1],[9,5],[7,0],[7,2],[1,5],[-3,3],[0,5],[4,5],[3,2],[9,0],[7,-5],[6,0],[1,-3],[-5,-3],[-3,-6],[6,-6],[5,-3],[5,0],[8,4],[7,-3],[3,-5],[0,-7],[1,-4],[5,3],[3,8],[-1,10],[0,6],[12,9],[5,8],[-9,1],[-5,-1],[-4,3],[-3,7],[10,6],[11,0],[7,-5],[14,-8],[8,0],[8,-1],[1,2],[-3,12],[1,7],[-6,4],[-2,9],[2,9],[8,5],[9,2],[21,14],[6,3],[13,3],[16,1],[20,5],[36,-3],[9,-2],[6,-3],[6,-4],[7,-8],[11,-9],[14,-3],[4,-3],[5,-8],[-6,-5],[-4,-1],[-9,3],[-6,4],[-4,-2],[4,-5],[4,-4],[1,-4],[-2,-7],[-17,-13],[10,-4],[6,3],[6,6],[5,2],[4,1],[13,1],[7,2],[6,-2],[5,-3],[8,-4],[12,-4],[14,-14],[11,1],[6,3],[17,2],[15,-7],[8,-2],[24,-2],[15,-5],[9,5],[6,2],[13,1],[6,-1],[18,-5],[32,-6],[21,-2],[19,-1],[9,-2],[17,-2],[6,-3],[16,2],[8,2],[7,5],[4,-1],[2,-6],[-1,-10],[3,-7],[2,-7],[3,-6],[2,-5],[-1,-4],[-5,-3],[-6,-8],[0,-7],[3,-5],[-3,-5],[2,-7],[0,-5],[-2,-3],[-5,-3],[-8,0],[-5,-2],[0,-6],[2,-4],[5,-2],[1,-4],[-1,-7],[-2,-5],[-4,-3],[-5,-1],[-9,2],[-7,3],[-4,-3],[-3,-3],[-10,-8],[-4,-5],[-4,-6],[11,-3],[8,-5],[17,0],[5,3],[8,2],[3,0],[3,-6],[-2,-9],[0,-7],[-9,-19],[-2,-3],[-4,-5],[-5,-4],[-4,-2],[-8,-6],[-4,-11],[-5,-9],[-8,-15],[-4,-17],[-2,-10],[-2,-10],[-7,-18],[-4,-3],[-7,-7],[2,-5],[6,0],[7,-2],[8,-3],[12,7],[6,5],[2,10],[-2,9],[4,6],[9,8],[20,6],[5,0],[6,2],[6,7],[6,7],[9,5],[8,7],[1,5],[3,1],[10,5],[2,4],[3,2],[2,7],[1,12],[2,8],[5,12],[4,9],[4,5],[10,3],[4,3],[6,8],[3,4],[0,9],[2,8],[6,5],[8,10],[10,1],[7,5],[8,-4],[10,-4],[16,1],[7,-2],[6,3],[5,7],[2,8],[7,5],[6,0],[12,9],[12,8],[9,1],[8,7],[5,10],[6,8],[8,7],[2,13],[4,7],[9,6],[7,3],[30,10],[22,7],[24,8],[7,0],[9,4],[15,1],[4,0],[6,9],[11,9],[7,3],[9,7],[7,1],[11,-2],[8,-2],[8,0],[11,7],[18,1],[5,3],[4,2],[25,9],[9,-2],[14,2],[8,-1],[7,-1],[10,0],[16,3],[7,2],[14,8],[14,1],[7,2],[8,2],[6,-3],[5,-3],[3,0],[4,-1],[10,3],[8,0],[10,-4],[6,-2],[4,0],[6,2],[8,6],[7,2],[6,-1],[5,-3],[8,-3],[13,1],[12,1],[10,3],[8,3],[8,-5],[10,-2],[15,8],[5,-1],[4,-2],[3,-2],[4,-6],[15,1],[12,6],[11,4],[10,3],[9,4],[12,15],[0,4],[1,3],[3,1],[19,0],[6,1],[8,4],[14,-3],[13,-5],[4,1],[5,0],[9,-3],[11,-6],[9,-1],[38,-14],[22,-4],[11,-5],[3,-1],[3,-5],[6,0],[5,1],[6,-7],[14,-5],[16,-3],[10,4],[17,13],[5,5],[-1,12],[9,14],[15,7],[19,3],[12,3],[15,3],[7,-3],[4,-2],[6,-3],[7,-7],[10,-17],[8,-7],[7,0],[6,-1],[6,-4],[9,-12],[-5,-11],[-5,-4],[-19,-5],[-9,-3],[-7,-2],[-3,-9],[4,-5],[8,2],[9,1],[8,2],[6,3],[6,4],[14,2],[9,3],[9,2],[5,4],[6,0],[6,-4],[4,0],[13,-1],[6,3],[5,0],[5,-2],[5,-3],[6,0],[7,1],[10,5],[12,4],[12,2],[3,0],[2,-1],[-12,-6],[-18,-7],[-10,-7],[5,-3],[36,8],[16,6],[14,2],[3,2],[12,9],[4,3],[13,3],[16,3],[12,4],[9,4],[6,1],[5,-3],[6,-3],[6,0],[8,3],[5,8],[3,5],[6,2],[7,1],[6,-1],[10,-4],[7,-2],[5,-15],[14,-14],[5,-3],[12,1],[13,-5],[5,1],[5,1],[5,-1],[7,3],[7,17],[7,16],[7,7],[4,4],[5,1],[7,3],[11,1],[7,-1],[17,-1],[14,4],[15,-1],[8,5],[8,1],[11,-5],[3,-2],[6,-5],[2,-4],[1,-7],[3,0],[11,7],[5,1],[11,12],[6,-3],[12,-5],[5,-2],[10,-8],[5,2],[5,4],[12,-1],[12,-3],[4,-3],[6,-5],[4,-1],[3,1],[24,-2],[10,-3],[8,-5],[28,-2],[11,-5],[6,3],[13,-1],[5,-4],[5,-4],[10,-4],[5,1],[8,3],[8,4],[8,0],[3,-4],[2,-9],[5,1],[7,4],[5,-1],[2,-6],[-3,-9],[-7,-11],[-3,-9],[-6,-9],[1,-4],[6,-2],[6,6],[14,4],[6,6],[12,2],[12,-2],[8,-8],[16,-12],[0,-4],[2,-5],[-1,-4],[-2,-5],[8,-5],[7,-1],[6,1],[25,-6],[12,2],[10,0],[13,1],[10,0],[7,-1],[9,2],[8,2],[3,-1],[2,-14],[0,-8],[5,-3],[4,3],[3,4],[20,-2],[7,0],[8,-2],[7,-5],[8,2],[4,3],[6,2],[1,5],[1,9],[0,8],[3,1],[4,-1],[4,-4],[11,-12],[8,-8],[3,-4],[5,-3],[10,-8],[14,-3],[13,-6],[15,0],[13,-7],[8,6],[4,1],[6,-2],[8,-5],[6,-1],[20,-8],[12,-4],[4,-6],[5,-6],[0,-6],[2,-8],[13,-6],[4,-6],[6,-7],[11,-30],[6,-5],[8,1],[7,-8],[3,1],[0,3],[-7,20],[0,11],[5,6],[13,1],[10,-11],[9,-7],[6,-1],[12,0],[11,8],[8,-3],[14,-1],[18,-4],[8,0],[14,-1],[16,-7],[10,-2],[2,-2],[4,-4],[2,-5],[3,-5],[6,-5],[5,-1],[12,-5],[24,-13],[9,-4],[5,-3],[2,4],[1,7],[4,1],[5,-10],[5,-9],[2,-7],[-5,-5],[-7,1],[-6,0],[-5,-10],[-2,-16],[5,0],[3,1],[1,-6],[-2,-5],[-4,-2],[-8,4],[-9,3],[-11,1],[-9,5],[-4,0],[-4,0],[5,-6],[5,-4],[13,-4],[15,-6],[1,-4],[-4,-5],[-4,-10],[-15,-8],[-8,6],[-10,1],[-5,-3],[-9,0],[-20,-1],[-7,7],[-12,5],[0,-4],[10,-13],[11,-3],[11,-3],[3,-4],[-5,-3],[-7,1],[-8,-6],[-16,1],[-7,-1],[-5,-2],[-4,-1],[3,-2],[4,-6],[-5,-5],[-5,-3],[-5,1],[-6,-2],[-3,6],[0,12],[-3,11],[-3,1],[-6,-2],[-2,-9],[4,-16],[3,-5],[-2,-5],[-4,-1],[7,-14],[7,-9],[3,-3],[1,-5],[-3,-2],[-9,2],[-4,-1],[-4,1],[-8,2],[-7,0],[-6,-2],[-6,0],[-5,8],[-4,3],[-4,-3],[-3,-10],[-5,-3],[-6,-5],[-4,-5],[-2,-20],[-4,-4],[-5,0],[-4,-1],[-4,1],[-7,1],[-21,-6],[3,-4],[6,1],[18,-1],[8,-4],[2,-9],[3,-4],[6,-4],[5,-2],[2,-3],[-2,-6],[-3,-6],[-6,-6],[2,-3],[6,-1],[3,-13],[-4,-6],[2,-6],[0,-5],[-4,-4],[-3,-3],[-1,-5],[6,-3],[5,-1],[6,0],[5,-6],[6,-8],[4,-7],[0,-11],[4,-7],[8,-4],[0,-4],[5,-2],[5,0],[2,-4],[-1,-5],[-9,-6],[-4,-5],[9,0],[9,-5],[12,5],[6,6],[4,5],[3,-2],[0,-5],[4,-8],[15,-9],[8,-3],[8,-1],[8,0],[2,-5],[-3,-4],[-5,0],[-9,-1],[-7,4],[-5,3],[-41,-2],[-9,-1],[-11,-5],[-11,-3],[-17,-5],[-7,-3],[-19,12],[-6,9],[-2,0],[-5,-2],[0,-6],[9,-13],[4,-4],[0,-3],[-3,-2],[-3,0],[-6,3],[-9,2],[-9,-4],[-11,-9],[2,-6],[3,-3],[-1,-4],[-12,-7],[-4,-1],[-2,-1],[3,-3],[6,0],[1,-3],[-2,-3],[-11,-3],[1,-4],[6,-2],[7,1],[5,-3],[0,-5],[-5,-2],[-6,-2],[-39,-12],[-5,-3],[0,-4],[14,-2],[41,1],[2,-1],[-1,-3],[-2,-5],[2,-3],[6,-2],[1,-3],[-3,-1],[-7,-2],[-6,0],[0,-4],[9,-3],[3,0],[1,-12],[-1,-5],[-4,-3],[-2,-1],[0,-4],[12,-3],[18,-13],[5,0],[7,-2],[12,-7],[4,-4],[7,-2],[1,-3],[4,-2],[17,-9],[2,-4],[-35,-7],[-35,-6],[3,-4],[38,0],[10,-3],[5,1],[2,3],[21,4],[20,2],[7,-1],[28,-15],[13,-5],[8,-2],[6,0],[4,-2],[4,-5],[-1,-4],[2,-2],[3,-1],[6,-3],[6,1],[7,4],[5,-1],[10,-5],[-4,-3],[-2,-2],[-2,-3],[-3,-1],[-7,-1],[-4,0],[-4,1],[-1,-3],[5,-2],[8,-3],[48,-2],[13,-4],[14,2],[6,-1],[5,-1],[2,-5],[7,-1],[11,-4],[14,-2],[12,0],[15,-5],[7,0],[4,-3],[33,-1],[5,-2],[4,-4],[8,-2],[8,0],[47,-6],[17,-3],[4,0],[4,0],[13,-3],[12,-1],[6,-4],[-9988,-5]],[[3457,1545],[2,-1],[7,0],[2,-1],[1,-2],[1,-5],[-2,-1],[-13,1],[-4,2],[-2,0],[-5,-3],[-2,-2],[-8,-3],[-3,1],[-1,4],[0,1],[1,1],[0,1],[0,1],[2,3],[10,4],[13,2],[1,-2],[0,-1]],[[3442,1551],[-5,-6],[-3,0],[-5,4],[-2,3],[0,1],[4,3],[9,-1],[2,-1],[1,-2],[-1,-1]],[[3319,1557],[-1,-1],[-2,1],[0,-1],[1,-1],[-1,-1],[-2,1],[-2,3],[1,3],[2,0],[4,-4]],[[3260,1551],[-1,0],[1,2],[3,6],[6,3],[-1,-2],[-2,-3],[-6,-6]],[[3316,1580],[1,0],[12,1],[4,-4],[4,0],[-10,-7],[-3,2],[-1,2],[0,3],[-7,-1],[-2,1],[-3,-2],[-6,-1],[-2,0],[-2,2],[0,3],[5,0],[4,3],[1,3],[2,-1],[3,-4]],[[3350,1587],[-4,0],[-2,3],[-2,2],[5,0],[3,0],[1,-3],[-1,-2]],[[3365,1595],[-6,-2],[-3,2],[-1,1],[4,3],[2,-1],[1,0],[2,-1],[1,-2]],[[3389,1618],[4,-2],[3,1],[2,-1],[1,-3],[0,-1],[-5,0],[-4,-4],[-6,1],[0,-3],[1,-2],[-2,-1],[-4,3],[-3,-1],[-2,-5],[-1,-1],[-1,-1],[-1,2],[-3,0],[0,1],[-2,2],[-5,-2],[1,2],[7,7],[1,2],[7,4],[4,-1],[8,3]],[[3498,1653],[-2,0],[-1,2],[-1,1],[2,3],[2,3],[1,1],[0,-7],[-1,-3]],[[3467,1658],[-3,-2],[-2,2],[0,4],[-2,2],[1,2],[20,-2],[-1,-2],[-10,-1],[-3,-3]],[[3730,1698],[6,-2],[3,-2],[1,-2],[3,-1],[1,0],[0,-2],[1,-1],[0,-2],[-6,4],[-9,1],[-2,3],[-4,-2],[-1,1],[0,2],[1,3],[2,-1],[4,1]],[[6924,2358],[-2,0],[0,2],[0,2],[-1,2],[-1,2],[1,2],[2,0],[3,0],[1,-4],[-2,-4],[-1,-2]],[[6921,2355],[2,0],[2,0],[6,8],[1,0],[0,-6],[2,-2],[-2,-1],[-4,0],[-1,-3],[4,-4],[2,-1],[1,0],[3,1],[3,2],[3,3],[2,2],[5,0],[2,3],[1,1],[2,0],[2,-1],[1,-3],[1,-4],[0,-4],[-2,-3],[-2,-3],[0,-2],[-1,-2],[-1,0],[-1,1],[-2,3],[-2,2],[-4,0],[-3,-1],[0,-2],[-1,-2],[-1,-1],[-2,1],[0,-1],[1,-3],[2,-3],[3,-2],[3,0],[0,4],[2,0],[3,-1],[1,-3],[-1,-1],[-1,-2],[0,-2],[-3,-2],[-1,0],[-4,1],[-3,2],[-1,2],[-1,1],[-2,-3],[-2,0],[-4,2],[-3,3],[-2,1],[-4,1],[-2,-7],[-2,-3],[-4,0],[-1,0],[-1,3],[0,3],[1,3],[1,3],[0,3],[0,3],[-1,2],[1,4],[-2,3],[1,2],[2,2],[-1,1],[-1,1],[-1,2],[0,2],[0,4],[1,4],[0,4],[2,4],[2,5],[1,2],[2,0],[0,-1],[1,-3],[-1,-1],[1,-1],[1,-6],[-1,-2],[0,-2],[-2,-5],[0,-3],[4,-2]],[[6439,2509],[-2,-1],[-2,2],[-1,3],[3,2],[1,-1],[1,-2],[0,-3]],[[3285,6165],[-1,-2],[-3,1],[0,3],[0,2],[2,4],[2,-2],[1,-2],[0,-2],[0,-1],[-1,-1]],[[3284,6196],[0,-1],[-2,2],[-1,5],[0,2],[1,0],[0,-1],[2,0],[0,-2],[0,-5]],[[9412,2033],[-1,-3],[0,3],[2,11],[2,2],[-1,-6],[-2,-7]],[[9092,2684],[-1,-6],[-2,1],[-2,-1],[-2,4],[0,1],[2,-1],[1,2],[0,1],[1,1],[0,2],[1,3],[1,0],[1,-4],[0,-3]],[[9095,2693],[-2,0],[-1,1],[0,3],[-1,1],[0,1],[1,1],[0,2],[1,-2],[2,-7]],[[9113,2724],[-1,-1],[-1,0],[0,3],[0,2],[1,3],[2,-2],[1,-2],[-2,-2],[0,-1]],[[9028,2835],[3,-1],[2,2],[2,0],[2,-4],[2,-2],[1,1],[2,-1],[1,-2],[3,-2],[1,-2],[1,-2],[2,-1],[8,-6],[5,-2],[8,1],[2,2],[2,2],[1,-2],[2,-3],[0,3],[0,3],[2,2],[2,2],[3,0],[4,0],[1,2],[1,0],[2,-2],[2,-1],[1,2],[3,5],[1,2],[5,-1],[2,0],[2,5],[2,0],[5,-4],[2,-6],[0,-9],[0,-4],[1,-3],[0,-7],[-1,-7],[0,-5],[0,-5],[0,-10],[1,-6],[0,-5],[0,-2],[0,-2],[1,-2],[-1,-3],[1,-3],[-1,-2],[-1,0],[0,2],[0,3],[0,2],[-1,2],[-2,2],[1,1],[1,1],[-1,3],[-1,-2],[-1,-3],[1,-1],[-1,-1],[-2,-4],[-1,-5],[-1,-5],[0,-5],[-1,-4],[-1,-4],[0,-5],[0,-9],[1,-9],[1,-11],[-1,-1],[-3,-1],[-2,-2],[-2,6],[-2,6],[2,2],[2,-1],[1,1],[0,2],[0,1],[-3,3],[-4,2],[-1,-2],[1,-5],[-1,-2],[-2,-2],[-1,8],[-3,6],[0,-3],[1,-5],[0,-2],[-1,-3],[-1,-1],[0,-2],[0,-3],[-1,-5],[-2,-3],[-5,6],[0,-2],[0,-2],[3,-3],[-2,-2],[0,-3],[-2,-8],[-2,-6],[-1,-1],[-4,1],[-4,6],[-4,-1],[-6,1],[-4,-2],[-1,5],[-1,3],[1,1],[3,2],[3,0],[-1,2],[0,1],[-2,-1],[-4,2],[-3,-1],[-2,3],[-3,10],[-2,4],[-1,2],[-2,1],[-1,1],[-6,22],[-1,5],[-1,13],[5,-6],[2,-4],[1,-5],[2,6],[-1,2],[-4,8],[-1,2],[0,2],[-1,-2],[-2,-1],[1,5],[-1,6],[-5,11],[-3,10],[-4,13],[-1,2],[0,3],[-2,8],[0,7],[-1,5],[2,12],[0,6],[3,-3],[6,-3]],[[9117,2850],[-2,-4],[-1,3],[-1,1],[3,1],[1,-1]],[[9021,2851],[-1,-5],[-1,6],[1,1],[1,2],[0,-4]],[[9119,2862],[3,-3],[1,-4],[-2,-3],[-1,-1],[-1,4],[-3,-1],[-3,0],[-2,3],[-1,1],[2,1],[4,0],[3,3]],[[9110,2894],[5,-11],[3,-1],[0,-1],[0,-5],[-1,-2],[2,-2],[0,-2],[-3,-4],[-3,-1],[-1,1],[0,2],[-1,2],[-4,9],[1,3],[-1,3],[-2,0],[-1,2],[2,3],[2,6],[2,-2]],[[8997,2873],[-1,0],[0,3],[0,5],[-1,4],[0,5],[0,5],[1,2],[1,3],[1,4],[1,0],[3,-3],[0,-9],[0,-5],[1,-4],[-1,-4],[-2,-4],[-3,-2]],[[9036,2967],[1,-3],[0,-1],[-3,2],[-4,0],[3,4],[2,-1],[1,-1]],[[9040,2975],[-4,-4],[-1,2],[0,2],[0,2],[4,0],[1,-2]],[[8821,3125],[7,-1],[2,2],[4,-2],[2,-5],[-2,-3],[-1,0],[-5,2],[-5,-2],[-1,-2],[-1,-5],[-4,-3],[-2,3],[-4,2],[-2,-3],[-4,1],[-3,-1],[-4,0],[-5,6],[-1,3],[1,4],[2,4],[12,5],[7,4],[5,-1],[2,-1],[1,-2],[-1,-4],[0,-1]],[[9264,3604],[-2,-16],[-1,0],[-1,2],[0,10],[1,5],[3,-1]],[[9261,3610],[-1,5],[-1,6],[1,5],[1,1],[1,-1],[-1,-9],[0,-7]],[[8143,3683],[-1,-2],[-5,18],[-1,12],[1,2],[1,1],[3,-17],[1,-4],[0,-4],[0,-1],[1,-5]],[[9251,3701],[0,-2],[-2,3],[-1,10],[1,6],[2,5],[0,3],[-1,7],[4,7],[1,4],[1,4],[-2,5],[-1,2],[1,2],[1,2],[1,0],[1,0],[0,-10],[2,-4],[0,-5],[-6,-26],[-2,-9],[0,-4]],[[9198,3831],[1,-2],[1,0],[0,-4],[1,-4],[1,-3],[-1,-3],[-1,-1],[-1,2],[-5,12],[1,5],[3,-2]],[[9180,3898],[-1,0],[0,1],[0,2],[0,3],[1,-1],[1,-4],[-1,-1]],[[9164,3906],[-1,-2],[-1,4],[0,4],[1,2],[1,-6],[0,-2]],[[8206,3986],[-2,-4],[-2,1],[0,2],[1,4],[3,4],[0,-2],[0,-5]],[[9139,4015],[0,-1],[-1,0],[-2,1],[1,8],[1,-4],[1,-3],[0,-1]],[[9136,4023],[-1,1],[0,2],[1,2],[1,1],[0,-5],[-1,-1]],[[9062,4134],[1,-6],[1,-4],[0,-3],[-1,-2],[-2,2],[-1,5],[-2,4],[-1,3],[3,-1],[1,1],[1,1]],[[8873,4198],[-1,-1],[0,2],[1,3],[1,3],[2,-3],[0,-3],[-3,-1]],[[8874,4229],[-2,-5],[-1,1],[-1,-3],[-2,-1],[-1,0],[-2,-1],[-1,1],[1,5],[2,6],[1,3],[5,2],[4,2],[3,-6],[-4,-1],[-2,-3]],[[8807,4275],[-1,-3],[-1,3],[-1,3],[-1,1],[1,2],[0,1],[1,4],[1,-4],[1,-5],[0,-2]],[[8793,4284],[-1,-1],[-1,1],[0,2],[0,3],[2,0],[1,-1],[-1,-4]],[[8801,4284],[-1,0],[0,4],[1,3],[1,-5],[-1,-2]],[[8460,4297],[-1,-2],[-1,1],[0,2],[-1,2],[1,3],[0,1],[1,0],[0,-2],[1,-3],[0,-2]],[[8477,4344],[-2,-4],[-1,3],[1,6],[1,2],[1,-1],[0,-4],[0,-2]],[[8797,4389],[1,-3],[1,0],[1,6],[1,-1],[1,-1],[0,-3],[-2,-4],[-1,-2],[-1,-8],[0,-2],[1,-3],[2,-2],[2,1],[0,-4],[-1,-2],[-4,1],[-3,-1],[-5,3],[-3,0],[-1,1],[2,2],[1,3],[-1,7],[1,8],[3,4],[1,4],[2,3],[1,0],[0,-3],[1,-4]],[[8783,4388],[0,-1],[-3,1],[0,2],[1,2],[0,1],[2,4],[1,-3],[1,-5],[-2,-1]],[[8786,4516],[-4,-5],[2,6],[5,5],[1,1],[0,-2],[-3,-4],[-1,-1]],[[8623,4511],[2,-1],[1,-2],[1,-2],[0,-3],[-3,-1],[-5,4],[-5,-3],[-2,0],[-1,2],[1,6],[2,-1],[2,2],[-1,7],[-1,4],[3,6],[1,2],[2,0],[1,-5],[0,-5],[1,-5],[1,-5]],[[8627,4529],[4,-1],[5,4],[2,-1],[1,0],[3,4],[2,1],[1,3],[2,-3],[3,-4],[1,-4],[2,-2],[0,-1],[-2,-4],[0,-5],[-2,1],[-3,-8],[-9,-12],[-9,10],[-4,8],[-2,10],[-1,8],[-1,5],[1,1],[0,1],[1,0],[3,-6],[1,-1],[1,-4]],[[8794,4528],[-2,-3],[-1,3],[1,2],[3,8],[1,2],[1,1],[0,3],[0,5],[2,0],[-2,-10],[-3,-11]],[[8682,4533],[0,-1],[-2,9],[0,3],[-1,4],[2,1],[1,3],[0,-2],[0,-6],[1,-4],[-1,-7]],[[8976,4495],[0,-7],[-2,-5],[0,-3],[0,-5],[3,-3],[1,-2],[1,-6],[3,-8],[0,-6],[2,-7],[2,-13],[0,-12],[2,-9],[-1,-17],[1,-7],[1,-5],[2,-12],[1,-11],[2,-3],[4,-3],[4,4],[3,5],[3,1],[4,3],[3,-7],[2,-8],[8,-10],[4,-7],[3,-4],[3,-5],[0,-5],[-1,-4],[1,-6],[0,-7],[-1,-9],[3,-13],[0,-10],[3,-10],[-1,-10],[0,-4],[0,-6],[2,-7],[1,-6],[3,-6],[3,-8],[2,-2],[2,0],[0,-9],[4,-18],[2,-15],[-1,-20],[-2,-11],[1,-6],[5,-13],[3,-3],[-1,-6],[0,-10],[2,-8],[3,-6],[3,-4],[3,-2],[4,-3],[5,-1],[2,-5],[1,-3],[4,-1],[2,0],[2,2],[2,-3],[1,-3],[2,-8],[4,-9],[3,-1],[2,-5],[2,-1],[2,0],[3,-4],[5,-7],[5,-1],[2,-3],[4,-8],[2,-4],[2,-7],[-2,0],[-3,1],[-1,-7],[3,-9],[4,-6],[4,-7],[4,-9],[1,-7],[1,-3],[1,-10],[4,-6],[0,-11],[2,-15],[2,-13],[1,-4],[2,-7],[1,1],[2,2],[3,-6],[1,-3],[1,2],[-2,12],[1,7],[1,1],[2,0],[2,-6],[2,-6],[5,-5],[4,-6],[1,1],[-1,4],[1,6],[1,0],[1,-2],[3,-10],[0,-18],[1,-16],[1,-16],[3,-5],[1,-4],[3,-5],[2,-5],[2,-2],[7,-11],[3,-1],[3,-1],[4,-5],[2,-4],[4,-17],[2,-6],[4,-6],[2,-2],[3,-4],[1,-6],[0,-3],[2,-6],[2,-8],[4,-4],[4,-9],[0,-15],[2,-7],[1,-3],[3,-3],[1,-3],[-3,-19],[3,-39],[-2,-13],[3,-12],[5,-21],[1,-7],[1,-9],[3,-11],[0,-17],[1,-8],[0,-10],[-4,-11],[-3,-14],[0,-12],[-2,-23],[-2,-6],[-1,-10],[-4,-23],[0,-9],[0,-10],[0,-11],[-1,-7],[-1,-13],[-5,-20],[-6,-15],[-1,-11],[0,-5],[-2,-7],[-3,-6],[-3,-3],[-1,-4],[-2,0],[0,-2],[2,-1],[-1,-2],[-6,-4],[-4,-4],[-4,-12],[-2,-6],[-2,-5],[-1,-3],[-1,-3],[0,-7],[-3,-1],[-1,-2],[0,-7],[0,-8],[-1,-5],[-1,-4],[-1,2],[-1,-1],[-1,-2],[2,0],[1,-1],[-4,-8],[-4,-8],[0,-5],[-2,-6],[-1,-15],[-2,-8],[1,-6],[0,-1],[-1,0],[-2,-2],[0,-2],[0,-2],[1,-1],[0,-1],[-1,-1],[-2,0],[-1,-2],[-6,-22],[-2,-5],[-3,-9],[-1,-8],[-1,-9],[-1,-14],[-1,-10],[-2,-10],[0,-7],[-1,-14],[1,-10],[0,-6],[0,-5],[-1,-5],[-4,-1],[-2,-4],[-4,-6],[-3,-3],[-5,-2],[-10,1],[-19,-2],[-3,-2],[-7,-4],[-7,-7],[-7,-10],[-15,-25],[-11,-3],[-2,0],[-2,1],[-2,-2],[0,-3],[2,-3],[1,-3],[3,4],[1,-1],[0,-8],[0,-5],[-1,-3],[-1,-2],[-2,1],[0,3],[-2,7],[-3,5],[-2,2],[-2,-2],[-2,-2],[-2,7],[-2,7],[-3,0],[-2,0],[-2,3],[-4,4],[1,4],[1,3],[2,1],[-1,5],[-1,4],[-3,1],[-2,-1],[-1,-3],[-2,-5],[-6,-7],[-3,4],[-4,5],[2,0],[3,0],[3,5],[2,3],[1,7],[-2,4],[-2,4],[-2,3],[-10,-10],[-2,-2],[-2,-2],[3,-2],[2,1],[3,-3],[-4,-4],[-2,-1],[-4,-3],[-6,-7],[-8,-13],[-4,-4],[-4,-3],[-5,3],[-3,1],[-4,6],[-7,4],[-6,7],[-5,4],[-3,1],[-4,-2],[-8,7],[-5,0],[-4,-6],[-3,0],[-1,1],[-6,11],[-6,6],[-11,2],[-6,8],[-5,15],[-9,16],[-3,7],[-1,5],[0,5],[1,9],[2,9],[0,5],[-4,17],[-5,16],[-2,5],[-6,10],[-6,8],[-1,4],[-1,2],[3,-1],[1,4],[2,1],[2,-5],[1,0],[0,7],[1,3],[0,2],[-1,1],[-2,2],[-3,-3],[-2,-3],[-3,-2],[-1,-3],[-3,0],[-1,-1],[-6,-5],[-4,0],[-5,2],[1,7],[3,4],[2,5],[3,17],[-1,15],[-1,7],[-5,12],[-2,8],[-3,8],[-1,-5],[-1,-5],[-3,-7],[-1,-15],[-5,-24],[-4,-1],[-3,1],[-5,-2],[-3,-4],[-3,0],[-2,-1],[-3,1],[4,19],[3,-1],[4,1],[1,0],[3,0],[1,8],[1,10],[0,6],[-1,7],[1,7],[0,5],[5,18],[3,9],[5,7],[-1,6],[-1,9],[-1,6],[2,3],[2,4],[-2,18],[-1,6],[-3,5],[0,-7],[1,-7],[-3,-9],[-4,-6],[-3,-6],[-2,-14],[-4,-11],[-3,-4],[-2,-1],[-3,-2],[-4,-5],[-4,-4],[-3,-5],[-3,-2],[-9,-23],[-4,-8],[0,-3],[-2,-3],[0,-3],[2,-3],[1,-10],[-1,-2],[-1,1],[-4,6],[-2,-2],[-2,-3],[-5,11],[-1,2],[-3,4],[-2,4],[-2,0],[-1,0],[0,3],[1,2],[1,0],[2,-3],[3,-3],[1,0],[1,1],[-3,12],[-1,10],[-1,3],[-2,11],[-1,3],[-4,7],[-4,9],[-1,10],[-2,7],[-2,4],[-3,4],[-8,2],[-4,10],[-2,14],[2,0],[2,1],[0,4],[0,6],[-9,8],[-4,8],[-3,4],[-3,1],[-4,0],[-6,0],[-12,13],[-3,1],[-9,-5],[-3,1],[-14,18],[-9,9],[-3,1],[-4,2],[-3,-2],[-2,-2],[-5,-3],[-18,2],[-16,-3],[-10,-2],[-7,-2],[-11,-11],[-13,-10],[-11,-5],[-10,-7],[-7,-1],[-8,-1],[-18,3],[-6,-2],[-10,-12],[-3,-3],[-5,-4],[-14,-15],[-7,-3],[-4,-2],[-4,-3],[-3,-6],[-4,-19],[-3,-8],[-6,-14],[-4,-5],[-4,1],[-4,-5],[-4,5],[-3,1],[-5,0],[-18,-6],[-2,7],[-3,1],[-6,-1],[-9,2],[-17,-2],[-8,-3],[-3,-2],[-6,1],[-10,-2],[-3,-4],[-3,-3],[-5,-16],[-5,-5],[-5,0],[-5,-1],[-11,-15],[-10,-14],[-4,-2],[-4,-2],[-5,-1],[-3,-2],[-12,4],[-8,0],[-9,3],[-9,7],[-6,4],[-7,15],[-5,6],[-8,7],[-2,0],[-2,-2],[-3,5],[0,6],[-1,6],[0,14],[0,16],[3,-3],[3,-4],[5,0],[4,6],[2,10],[3,10],[-1,11],[-1,19],[1,4],[1,2],[1,10],[0,29],[-1,11],[-7,23],[-4,19],[-3,9],[-3,15],[-3,19],[0,10],[-1,19],[1,10],[-1,6],[-2,17],[-7,16],[-1,6],[0,6],[-1,7],[-5,14],[-6,12],[0,6],[-1,25],[-2,12],[-9,28],[-11,25],[-3,10],[-1,4],[1,0],[1,-1],[1,-3],[1,0],[1,2],[0,5],[0,3],[1,-2],[1,-5],[3,-14],[1,-7],[4,-2],[2,2],[1,3],[1,10],[-2,4],[-2,2],[-4,8],[-2,11],[-3,11],[0,4],[2,2],[2,-1],[2,-6],[3,-6],[-1,-10],[0,-3],[0,-2],[1,-2],[1,-2],[2,3],[1,5],[1,0],[1,-14],[2,-3],[2,-4],[3,3],[1,3],[0,9],[0,9],[0,7],[-6,17],[-6,22],[-3,11],[-3,17],[-2,5],[-2,9],[0,11],[0,7],[2,15],[1,8],[6,18],[0,8],[0,6],[1,9],[0,6],[-1,6],[-2,10],[3,18],[5,22],[1,3],[3,4],[1,-5],[-2,-16],[2,-8],[0,-9],[2,1],[2,2],[2,5],[1,5],[6,18],[3,7],[4,5],[8,6],[8,8],[4,8],[5,6],[3,8],[4,4],[16,19],[3,3],[4,1],[4,-1],[4,1],[4,-4],[3,-1],[8,5],[4,4],[7,9],[3,2],[8,3],[8,4],[10,15],[7,-1],[6,-1],[5,4],[12,3],[7,4],[12,10],[3,4],[5,7],[5,9],[4,12],[3,11],[1,6],[2,9],[2,7],[1,4],[5,4],[7,14],[3,3],[0,4],[-1,2],[-2,2],[-2,14],[-1,10],[0,7],[1,7],[2,10],[2,4],[3,5],[3,2],[2,4],[3,5],[1,4],[3,9],[2,7],[1,0],[3,-16],[2,-8],[3,-10],[3,-15],[3,-7],[1,-4],[1,-2],[1,2],[-1,4],[2,11],[-1,8],[0,3],[1,1],[1,-1],[3,-4],[1,-2],[1,1],[0,7],[1,4],[0,3],[-3,0],[0,4],[-2,5],[-2,3],[-3,7],[-1,3],[1,1],[2,0],[1,3],[1,4],[-1,7],[1,3],[2,-1],[4,-11],[1,1],[2,5],[2,1],[2,-1],[2,-3],[3,-3],[4,0],[2,-1],[5,1],[2,-1],[0,2],[-3,2],[-3,0],[-3,0],[-1,2],[-1,6],[1,4],[1,1],[2,0],[2,0],[0,5],[1,5],[1,4],[0,3],[-2,-1],[-2,-8],[-2,7],[-2,5],[1,8],[1,7],[2,1],[1,-1],[3,5],[1,3],[-1,3],[1,2],[1,-1],[7,-6],[1,-4],[1,1],[1,4],[-1,4],[-1,0],[-3,0],[-1,2],[0,2],[-1,5],[2,2],[2,1],[1,2],[0,2],[0,2],[1,-2],[4,-1],[3,-3],[1,-1],[1,2],[0,4],[-4,4],[0,4],[-2,5],[0,4],[3,4],[0,4],[2,1],[2,0],[2,3],[2,2],[1,7],[0,4],[1,2],[2,-2],[-1,-6],[0,-5],[0,-3],[1,0],[0,1],[1,4],[2,-2],[1,-3],[0,-4],[1,-1],[2,5],[2,2],[0,7],[0,5],[1,4],[1,2],[0,4],[-1,3],[0,5],[1,1],[2,-3],[1,-6],[1,-3],[1,2],[1,4],[2,2],[3,-3],[2,-5],[3,4],[3,8],[-1,5],[1,5],[3,2],[3,-2],[3,-5],[5,-4],[5,-5],[2,-4],[4,-6],[2,-6],[4,-11],[8,-13],[0,-2],[-1,-4],[-1,-6],[-1,-9],[0,-14],[1,1],[1,5],[1,-1],[2,-3],[0,3],[-1,2],[-1,6],[0,3],[1,3],[2,3],[2,2],[1,2],[0,3],[2,2],[3,1],[1,-1],[12,-6],[3,-5],[0,-8],[1,-2],[1,4],[0,10],[1,2],[3,-1],[2,-2],[3,-7],[1,-3],[1,-2],[1,3],[-1,4],[-1,5],[1,4],[4,1],[2,1],[-1,1],[-2,1],[-2,4],[-2,4],[3,4],[0,1],[-3,0],[-3,4],[-3,6],[2,10],[5,10],[2,4],[0,3],[2,6],[0,6],[1,4],[1,4],[3,4],[3,2],[2,1],[2,4],[1,5],[-3,9],[0,5],[1,5],[4,5],[2,11],[2,2],[3,-1],[1,1],[0,9],[1,4],[1,1],[2,-1],[1,-4],[2,-4],[1,2],[0,4],[0,5],[2,2],[2,0],[0,4],[0,3],[0,2],[5,0],[1,4],[1,3],[1,-2],[1,-6],[2,-4],[8,0],[5,2],[2,-1],[3,-2],[3,4],[2,2],[3,-3],[1,-3],[1,6],[2,3],[2,1],[3,-1],[1,1],[-3,5],[0,4],[0,7],[1,6],[1,5],[-6,9],[-5,1],[-4,-2],[-2,2],[-4,7],[-3,3],[0,2],[4,5],[1,-1],[3,-5],[1,-2],[1,1],[1,3],[1,2],[2,-1],[6,-8],[4,-8],[2,2],[3,5],[2,-1],[2,-3],[3,-10],[2,-4],[4,-2],[3,-2],[2,-3],[4,0],[7,-1],[6,-6],[3,-4],[3,-1],[2,-1],[3,-1],[6,5],[2,-5],[1,-2],[5,-6],[5,-1],[4,5],[5,4],[4,6],[3,3],[3,5],[1,0],[-2,-5],[-1,-3],[2,-1],[0,-1],[-3,-4],[-2,-5],[0,-3],[1,-2],[1,1],[2,2],[2,2],[2,-2],[1,-8],[1,-6],[3,0],[2,0],[2,7],[-1,6],[-1,2],[0,2],[5,10],[3,0],[2,-10],[3,-5],[3,0],[2,-1],[1,-7],[-11,-25],[-1,-2],[2,-5],[0,-5],[-3,-13],[-2,-1],[-1,4],[-2,2],[-2,-1],[-1,-1],[-7,-8],[0,-18],[2,-11],[-1,-7],[-2,-12],[-2,-5],[-2,-3],[-6,-17],[-2,-4],[-2,-6],[1,-6],[1,-4],[2,-4],[8,-9],[4,-7],[7,-7],[1,-6],[1,-4],[5,-5],[3,-3],[1,1],[1,1],[1,0],[0,-1],[0,-3],[0,-3],[0,-2],[3,-4],[4,0],[2,1],[2,-3],[2,-3],[4,-5],[6,-5],[5,-4],[6,-14],[4,-8],[5,-6],[7,-4],[4,0],[5,-4],[6,-3],[2,-6],[1,-5],[1,-4],[2,-9],[5,-3],[7,-10],[6,-4],[2,-2],[2,-3],[5,0],[8,5],[4,4],[5,8],[2,13],[2,10],[7,21],[2,11],[2,13],[1,9],[0,10],[1,17],[4,24],[1,8],[0,11],[-3,22],[1,8],[1,11],[-1,7],[-2,6],[0,7],[2,14],[1,8],[2,9],[-1,18],[3,7],[2,3],[2,0],[1,-2],[1,4],[-1,3],[-1,4],[-1,2],[-1,1],[-1,2],[-2,2],[0,8],[3,16],[2,6],[1,-2],[1,-3],[1,5],[-1,5],[3,15],[2,20],[1,19],[5,4],[2,5],[1,5],[3,0],[1,-2],[-1,-4],[0,-4],[5,-7],[1,-6],[1,-6],[1,-5],[0,-8],[0,-11],[1,-11],[1,-4],[2,-2],[2,0],[3,-2]],[[8951,4567],[-2,-3],[-2,2],[0,3],[0,2],[2,3],[2,-7]],[[8953,4597],[-2,-4],[-1,1],[-1,2],[1,3],[2,1],[1,-3]],[[8948,4599],[-1,-2],[-1,4],[2,4],[1,-2],[-1,-4]],[[5470,7983],[0,-1],[0,-2],[-1,-2],[-1,-4],[0,-3],[3,-11],[3,-7],[0,-2],[2,-2]],[[5476,7949],[-2,-3],[0,-3],[-1,-2],[0,-2],[0,-2],[0,-2],[1,-3],[-3,-1],[-3,0],[-1,0],[-1,-1],[-1,0],[-3,3],[-2,1],[-1,0],[-1,-1],[-1,-2],[-1,-1],[0,-1],[6,-3],[1,-4],[-1,-4],[-1,-1],[-1,-2],[-2,-1],[-2,0],[0,-2],[1,-5],[-1,-2],[-1,-1],[1,-5],[1,0],[1,-1],[-1,-2],[0,-2],[0,-2],[-1,-1],[-3,0],[-2,-2],[-5,-6]],[[5446,7883],[-1,-1],[-2,-3],[0,-5],[0,-1],[0,-1],[-6,2],[-3,0],[-3,-3],[-3,-1],[-6,0],[-6,-1],[-1,0],[-2,-1],[-1,-1],[-1,-2],[-2,-3],[-2,-2],[-2,-2],[-1,-1],[0,-1],[-2,1],[-1,0],[-1,1],[-4,1],[-5,1],[-2,1],[-3,1],[-2,1],[-3,0],[-1,0]],[[5380,7863],[-6,2],[-4,0],[-5,1],[-10,3],[-3,2],[-3,0],[-3,1],[-2,2],[-2,3],[-2,4],[-3,6],[-1,3],[1,3],[1,1],[0,1],[0,1],[-6,-3],[-5,-3],[-3,0],[-2,1],[-2,0],[-3,-1],[-5,0],[-3,-3],[-2,-4],[-1,-4],[-1,-1],[-2,0],[-3,0],[-2,1],[-2,3],[-3,0],[-2,1],[-1,0]],[[5290,7883],[0,2],[-1,4],[-2,1],[-5,-7],[-1,-1],[-4,2],[-3,3],[-1,3],[0,1],[-3,2],[-3,1],[-1,0]],[[5266,7894],[0,1],[0,2],[0,2],[-1,1],[0,2],[0,1],[0,1],[-1,2],[0,1]],[[5264,7907],[2,6],[1,5],[-2,2],[-1,1]],[[5264,7921],[1,1],[3,-1],[1,2],[1,1],[3,-1],[3,-3],[2,-2],[1,-1],[0,-1],[0,-2],[1,-1],[2,-1],[1,0],[-1,-3],[0,-2],[2,0],[2,2],[2,3],[0,3],[1,7],[0,1],[2,-1],[5,0],[2,-1],[4,0],[-1,-1],[1,-2],[2,-2],[0,-2],[2,0],[3,0],[1,1],[1,0],[2,0],[2,2],[1,2],[2,1],[3,3],[4,2],[13,2],[0,1],[0,4],[1,0],[1,-1],[3,0],[2,-2],[1,-1],[1,0],[2,1],[3,0],[2,-1],[1,-2],[0,-1],[0,-2],[0,-1],[2,-2],[3,-2],[1,0],[0,2],[1,4],[0,5],[0,2],[-2,1],[-1,0],[-1,1],[0,1],[1,3],[0,5],[-3,6],[-2,5],[0,2],[1,3],[3,2],[5,4],[1,1],[3,1],[3,2],[1,1],[1,2],[1,10],[1,0],[0,1],[5,-3],[1,0],[1,1],[1,2],[1,2],[0,4],[0,4],[0,1]],[[5383,7993],[1,-1],[2,-2],[2,-2],[2,-5],[4,-1],[5,0],[1,2],[2,1],[2,-1],[4,-1],[0,4],[2,5],[1,1],[3,0],[1,3],[0,9],[1,1],[2,0],[2,-2],[1,-1],[1,0],[1,1],[2,1],[2,-1],[6,-4],[3,-2],[1,0],[2,0],[6,-6],[5,-1],[4,0],[1,2],[2,2],[2,-1],[2,0],[3,-3],[1,-1],[2,0],[1,-1],[2,-5],[0,-1]],[[6280,7423],[-5,2],[-10,4],[-2,1],[-3,6],[-1,2],[-3,3],[-1,2],[-2,2],[0,3],[-2,3],[-2,4],[-4,11],[-1,2]],[[6244,7468],[-1,2],[0,1]],[[6349,7594],[2,-3],[5,-9],[6,-15],[1,-4],[1,-5],[1,-6],[2,-5],[6,-13],[3,-5],[4,-6],[2,-2],[2,0],[4,0],[4,-2],[1,-2],[2,-3],[2,-3],[1,-7],[-6,2],[-6,0],[-4,-2],[-3,-2],[-3,-3],[-2,-6],[-2,-14],[-3,-14],[1,-6],[1,-6],[0,-3],[-2,-1],[-1,-2],[-2,-13],[-1,-2],[-1,-2],[-1,2],[1,3],[-3,3],[-2,-3],[-1,-7],[-2,-7],[0,-1],[1,-22]],[[6357,7398],[-1,0],[-6,-2],[-1,0],[-5,10],[-1,1],[-2,1],[-1,2],[-1,2],[-1,2],[-5,6],[0,2],[0,1],[0,2],[1,1],[3,2],[2,1],[1,1],[1,1],[0,3],[-1,2],[-4,4],[0,2],[0,2],[0,2],[0,2],[4,3],[2,2],[-1,3],[-4,6],[-4,8],[-3,0],[-4,-3],[-5,-6],[-3,-2],[-4,-4],[-4,-5],[-3,-5],[-2,-4],[-4,-2],[-2,-4],[-6,-10],[-2,0]],[[6249,7562],[6,8],[2,1],[4,-1],[8,-5],[0,-3],[1,-2],[1,-2],[4,-2],[3,-1],[2,1],[2,1],[3,-3],[3,-3],[1,-1],[1,-1],[2,1],[3,5],[1,4],[0,3],[-2,3],[-3,4],[-3,3],[-2,3],[-2,5],[-1,1],[-1,0],[0,2],[0,3],[1,2],[1,1],[2,0],[1,2],[1,4],[1,2]],[[6289,7597],[3,-2],[0,-3],[1,-1],[1,1],[2,1],[2,-1],[2,-4],[3,-4],[2,-3],[0,-2],[2,-2],[2,-2],[2,-3],[1,-9],[2,-1],[5,-3],[2,-1],[6,-1],[2,1],[3,7],[2,7],[3,1],[4,4],[3,3],[1,4],[2,6],[2,4]],[[5848,5046],[0,-2],[-3,-11],[0,-1],[0,-1],[1,-2],[-1,-4],[0,-1],[0,-3],[0,-3],[0,-1],[2,-1],[3,-1],[2,-3],[2,0],[1,-2],[0,-3],[0,-3],[0,-5],[0,-4],[-3,-2],[-2,-2],[0,-1],[0,-1],[0,-2],[-3,-4],[-2,-6],[-1,-4],[-1,-4],[-1,-3],[-2,-4],[-2,-8],[-1,-6],[-6,-12],[-5,-7],[-1,-2],[-9,1]],[[5816,4928],[0,8],[-2,12],[-3,11],[0,4],[0,9],[0,12],[0,6],[0,5],[0,8],[0,5],[-2,6],[-2,6],[-2,3],[0,2],[0,2]],[[5805,5027],[1,3],[1,4],[1,0],[2,-1],[3,-3],[2,-7],[1,-1],[2,0],[5,1],[1,0],[3,1],[2,3],[1,3],[0,7],[1,12],[1,0],[3,-4],[1,0],[1,0],[1,2],[1,2],[1,0],[4,2],[2,-4],[1,-1],[1,0]],[[5158,8108],[0,1],[3,1],[2,-3],[3,0]],[[5166,8107],[0,-1],[3,-3],[1,-3],[3,-2],[-2,-3],[0,-1],[1,-2],[2,0],[2,-2],[0,-3],[0,-5],[-5,-5],[-1,-5],[-1,-1]],[[5169,8071],[0,2],[-1,0],[-3,0],[-3,-5],[-1,-4],[-1,-3],[-1,-2],[0,-2],[0,-2],[0,-1],[0,-1],[1,-3],[1,-2],[2,-5],[-1,-2],[0,-2],[-1,-1],[-1,-1]],[[5160,8037],[-2,0],[-3,0],[-2,-1],[-1,0],[-2,2],[-2,4],[-1,2],[-1,1],[-2,1],[-2,2],[-2,2],[-1,1],[-3,1],[-1,0],[-1,3],[0,4],[-1,2],[2,11],[-2,1],[-1,-1],[-2,-3],[-1,-3],[0,-2],[-3,-3],[-5,0],[-6,0],[0,1],[-1,1],[0,1],[1,1],[1,2],[0,2],[-1,2],[-1,1],[1,2],[0,2],[0,2],[-3,4],[-3,1],[-2,0],[-2,1],[-1,0],[-1,-2],[-1,-1],[-1,1],[-1,8],[-1,1],[-3,1],[-4,1],[-2,1],[0,4],[-1,4],[-1,4],[-1,1],[-1,2],[-3,-1],[-2,-2],[-2,-1],[-1,0],[-2,2],[-2,3],[-2,4],[-1,2],[1,3],[-1,2],[-1,3],[0,3]],[[5070,8127],[12,10],[7,5],[4,1]],[[5093,8143],[0,-5],[1,-1],[1,-2],[1,0],[1,2],[2,1],[3,-1],[2,-1],[1,-1],[1,-1],[2,-1],[4,3],[3,3],[1,2],[1,3]],[[5117,8144],[2,-2],[2,0],[1,0],[-1,4],[2,2],[2,1],[0,-2],[2,-1],[1,0],[4,4],[0,-1],[1,-2],[0,-1],[0,-1],[1,0],[3,0],[1,2],[1,1],[1,-1],[0,-2],[1,-4],[3,-4],[3,-1],[3,1],[2,1],[1,-1],[0,-2],[2,-2],[4,-2],[2,-1],[0,-1],[0,-3],[-2,-5],[0,-2],[0,-1],[0,-1],[-3,-3],[0,-2],[1,-2],[1,-2]],[[5099,5857],[-1,-3],[-2,-8],[0,-6],[5,-12],[0,-2],[1,-2],[1,-2],[0,-6],[1,-7],[0,-5],[2,-7],[0,-2],[-1,-10],[-1,-1],[-2,0],[-1,-1],[-1,-3],[-1,-3],[0,-2],[2,-6],[-1,-9],[-2,-6],[-2,-3],[-2,-1],[-1,-1],[-1,-2],[0,-6],[-3,-6],[-2,-4],[0,-3],[0,-7],[-1,-8],[-2,-6],[-4,-1],[-3,-1],[-2,-15],[0,-10],[0,-10],[0,-4],[0,-6],[0,-13],[-1,-10],[1,-2],[0,-6],[0,-7],[1,-4],[1,-4],[0,-1],[-1,-2],[0,-1],[0,-15],[0,-4],[0,-3],[-1,-2],[0,-7],[1,-5],[1,-4],[-1,-2],[-1,-4],[0,-10],[0,-3]],[[5075,5551],[-12,-3],[-13,-4],[-5,-2]],[[5045,5542],[-1,2],[5,2],[-1,8],[-3,9],[-1,2],[-1,4],[1,3],[0,2],[-1,6],[-1,7],[3,0],[0,21],[0,21],[0,17],[0,14],[-1,17],[0,12],[0,16],[-1,5],[-4,9],[-1,4],[0,6],[-1,6],[0,10],[0,13],[-1,2],[-4,5],[-6,9],[-4,6],[-1,0],[0,2],[0,19],[1,2],[2,8],[1,6]],[[5025,5817],[1,2],[1,3],[1,-1],[1,0],[1,1],[0,2],[0,2],[1,1],[0,3],[0,2],[1,1],[2,-1],[1,1],[1,1],[1,5],[1,2],[0,1],[1,1],[2,1],[2,-1],[1,-3],[7,3],[4,-2],[6,13],[2,3],[2,9],[1,3]],[[5066,5869],[1,6],[-2,11],[0,2],[3,2],[4,2],[1,0],[1,1],[1,2],[2,2],[2,0],[0,-1],[8,-14],[3,-7],[1,-4],[2,-3],[2,-2],[3,-3],[1,-6]],[[5006,6043],[-1,-3],[0,-5],[0,-7],[-1,-9],[2,-6],[3,-6],[1,-3],[-1,-6],[1,-3],[1,-6],[3,-8],[3,-8],[2,-1],[1,-1],[1,-1],[2,-1],[1,-1],[2,-2],[1,-2],[1,-4],[3,-4],[2,-3],[-1,-1],[-3,0],[-2,2],[0,-3],[0,-9],[0,-7],[0,-1],[3,-1],[6,-10],[5,-9],[2,-2],[3,-1],[3,-1],[2,1],[3,5],[2,0],[1,0],[1,-1],[1,-3],[2,-6],[0,-4],[0,-2],[0,-1],[-3,-1],[-1,-1],[0,-1],[0,-3],[1,-2],[2,-8],[5,-11],[1,-3]],[[5025,5817],[-8,-1],[-2,-1],[-2,0],[0,1],[0,1],[-9,4],[-6,3]],[[4998,5824],[-7,3],[0,-3],[-1,-2],[-1,0],[-1,1],[-1,-2],[-1,-3],[-2,-2],[-1,-1],[-1,-2],[-1,0],[-1,4],[-2,0],[-4,0],[-1,0],[-2,1],[-6,-1],[-8,2],[-2,-1],[0,-1],[-8,0],[-9,0],[-8,0],[-7,0],[-2,0],[0,-1],[-2,-14],[0,-8],[1,-5],[1,-3],[1,-1],[0,-2],[-1,-2],[0,-3],[1,-2],[1,-2],[-1,-3],[0,-6],[1,-10],[0,-7],[-1,-3],[1,-5],[1,-7],[1,-3]],[[4925,5730],[-1,-1],[-1,-2],[-2,0],[-1,4],[-1,2],[-1,4],[-1,5],[-2,2],[-1,2],[-2,5],[-2,3],[-2,-1],[-3,1],[-5,1],[-6,0],[-2,-1],[-3,-2],[-6,-5],[-2,-2],[-2,-6],[-2,1],[-2,1],[-1,3],[-3,-1],[-3,3],[-2,5],[-2,1],[-3,4],[0,6],[-2,5],[-1,7],[-2,3],[-3,1],[-3,0],[-2,2],[-2,4]],[[4846,5784],[1,4],[0,4],[0,5],[1,7],[0,9],[-1,7],[2,2],[2,3],[1,4],[2,10],[0,8],[0,4],[-1,2],[0,4],[-1,4],[1,4],[1,4],[2,3],[2,1],[3,2],[5,2],[3,2],[2,3],[1,2],[1,4],[2,3],[1,3],[1,9],[0,5],[-1,3],[-1,3],[7,7],[0,5],[-1,5],[-1,5],[-1,3],[2,5],[2,3],[1,3],[3,5],[3,1],[2,-2],[8,-10],[2,-1],[1,1],[2,3],[3,2],[1,7],[0,10],[0,4],[2,1],[4,-2],[1,0],[2,1],[0,2],[0,3],[0,3],[2,9],[2,7],[6,9],[1,2],[2,1],[10,-6],[1,1],[3,15],[2,2],[3,0],[2,1],[1,2],[5,5],[8,8],[4,3],[1,2],[3,5],[4,7],[3,1],[4,0],[2,-1],[0,-2],[1,-1],[5,3],[7,-4],[6,-4]],[[7553,6423],[-1,-1],[-1,2],[0,2],[0,8],[1,1],[1,0],[0,-2],[1,-5],[-1,-5]],[[7551,6441],[-1,-4],[0,3],[0,4],[1,3],[1,-3],[-1,-3]],[[7531,6461],[-3,-4],[1,24],[2,-9],[1,-5],[-1,-6]],[[7542,6473],[-1,-2],[-1,2],[-2,5],[1,7],[1,1],[0,-2],[2,-5],[0,-4],[0,-2]],[[7521,6456],[-5,-2],[-2,1],[4,15],[0,7],[-1,5],[-2,5],[0,3],[-1,4],[-1,5],[3,2],[2,-3],[0,-2],[1,-4],[1,-4],[3,-9],[0,-6],[-1,-13],[-1,-4]],[[7517,6506],[1,-2],[-2,1],[-1,2],[-1,2],[1,2],[2,-5]],[[7571,6450],[0,-2],[0,-20],[0,-8],[1,-6],[0,-3],[-1,-2],[-1,3],[-2,2],[-3,3],[-1,2],[-1,-1],[-2,-4],[-1,-4],[0,-5],[1,-5],[1,-3],[0,-3],[1,-5],[0,-3],[1,-5]],[[7564,6381],[-1,0],[-1,6],[-2,5],[-4,11],[-1,20],[0,10],[-3,11],[-1,16],[-1,4],[1,5],[0,2],[-2,-3],[-2,6],[-1,6],[-4,12],[-2,5],[0,5],[-2,-5],[-2,-4],[-3,-5],[-2,-2],[-5,-1],[-4,8],[-5,17],[0,4],[0,10],[-1,10],[0,5],[0,4],[-1,-1],[0,-2],[0,-4],[0,-3],[-4,0],[-4,2],[3,-5],[4,-1],[2,-5],[0,-4],[0,-4],[-2,-3],[-2,-1],[1,-4],[2,-5],[-3,-1],[-1,-3],[0,-5],[2,-4],[0,-2],[0,-3],[1,-3],[2,-6],[0,-4],[0,-6],[-1,-2],[-2,-3],[-4,-7],[-2,-9],[-1,-4],[-2,-1],[-1,2],[-2,2],[0,5],[1,3],[3,8],[-2,-1],[-2,-2],[-3,-5],[-1,6],[-1,5],[0,6],[3,9],[-3,-5],[-1,-5],[1,-7],[-1,-5],[-1,-6],[-1,-4],[-3,-2],[-1,-4],[-2,-2],[0,5],[0,7],[-2,17],[0,-4],[0,-10],[0,-7],[-1,-5],[-3,-6],[-2,-1],[-1,1],[-2,4],[-2,5],[0,8],[-1,4]],[[7473,6456],[0,6],[0,5],[-2,13],[-2,7],[0,3],[0,1],[0,9],[-1,5],[-1,6],[2,8],[0,2],[-3,1],[-2,1],[-1,2],[1,9],[-1,3],[-2,3],[0,2],[-1,1],[-1,4],[2,9],[2,10],[1,4],[0,7],[0,2],[0,3],[-2,3],[-4,1],[-3,3],[-2,3],[-1,2],[-2,-1],[-2,1],[-2,4],[-2,4],[1,2],[0,3],[3,12],[1,0],[2,-2],[1,0],[2,5],[2,13],[4,0],[3,-1],[1,-1],[2,1],[2,1],[2,2],[0,2],[0,2],[-3,2],[-1,2],[0,5],[-1,2],[-5,0],[-2,3],[-2,2],[-2,7],[-3,5],[-3,1],[-1,2],[-1,3],[0,4],[1,3],[1,4],[2,6],[3,4],[1,3],[2,4],[0,1],[0,3],[-2,2],[-1,0],[0,1],[1,4],[1,0],[3,-3],[3,-5],[2,-4],[0,-4],[1,0],[1,-1],[2,-1],[2,0],[1,-1],[1,1],[0,2],[-1,3],[-1,2],[1,2],[1,1],[1,-1],[1,-2],[1,-4],[0,-6],[3,-6],[3,-3],[2,-2],[2,-2],[3,2],[1,4],[-1,3],[1,3],[1,2],[1,0],[1,-3],[3,-13],[0,-6],[0,-16],[0,-11],[0,-2],[0,-2],[1,0],[1,0],[3,-2],[4,-3],[3,-2],[5,-1],[4,0],[1,0],[4,0],[8,1],[7,0],[3,-2],[2,0],[8,1],[8,1],[4,-4],[5,-5],[3,-4],[0,-3],[0,-2],[-1,-1],[-2,0],[-3,3],[-1,-1],[0,-6],[-1,-5],[-2,-11],[0,-5],[-1,-2],[-2,0],[-2,-1],[0,-2],[-1,-4],[-1,-4],[0,-1],[-3,2],[-1,0],[-1,-1],[-2,-2],[-1,-3],[-1,-1],[-4,1],[-1,0],[0,-2],[-1,-3],[-3,-5],[-1,-9],[-1,-6],[1,-5],[2,-12],[2,-15],[0,-2],[1,0],[0,3],[0,4],[1,1],[1,-1],[1,-3],[1,-6],[1,-3],[2,-1],[2,2],[2,3],[1,3],[-1,6],[0,4],[1,4],[4,7],[0,2],[0,5],[0,5],[1,0],[2,0],[2,2],[1,0],[1,-3],[2,1],[1,-11],[1,-10],[0,-4],[0,-10],[1,-9],[1,-1],[1,-5],[1,-5],[0,-3],[1,-9],[1,-6],[0,-21],[1,-4]],[[5793,7703],[0,-14],[-3,-6],[-4,2],[-5,-2],[-3,-7],[-1,-2],[-2,-3],[-1,-9],[0,-16],[-2,-2],[-2,0],[-7,-14],[4,-4],[2,-3],[3,-8],[5,-9],[1,-5]],[[5778,7601],[-4,1],[-1,0],[-1,-2],[-2,1],[-2,0],[-2,-2],[-2,-1],[-1,2],[-3,4],[-2,4],[-2,0],[-1,-1],[-5,-1],[-1,-2],[-3,-2],[-2,0],[-3,-1],[-2,0],[-1,-1],[-1,-3],[-1,-3],[0,-1],[-4,-1],[-1,-2],[-1,-2],[1,-1]],[[5731,7587],[-4,1],[-2,-1],[-1,-1],[-1,-2],[1,-2],[1,-2],[1,-5],[0,-5],[-1,-2],[-2,-2],[-3,-3],[-4,1],[-2,-1],[-3,0],[-2,0],[-5,-2],[-3,-2],[-3,5],[-4,2],[-4,2],[-2,-1],[0,-1],[-4,4],[-1,1],[-1,1],[-2,5],[-3,-2],[-3,1],[-1,0],[-5,0],[-1,-4],[-1,0],[-1,-1],[-2,1],[-3,-3],[-4,-1],[-3,0],[-3,0],[-1,0],[-4,0],[-2,-4],[-4,0],[-3,1]],[[5636,7565],[0,1],[1,14],[1,7],[0,1],[0,1],[-1,1],[-1,3],[-2,10],[-1,1],[-3,2],[-3,3],[-3,3],[-4,9]],[[5620,7621],[2,1],[1,2],[2,4],[0,3],[0,1],[-1,2],[-1,5],[0,5],[0,2],[0,3],[1,2],[1,2],[1,1],[4,0],[3,6],[1,2],[2,3],[1,1],[0,3],[1,2],[-4,4],[-1,3],[-1,3],[-2,2],[-4,4],[-2,3],[0,5],[-1,4],[-1,2],[-1,2],[0,3],[0,4],[1,6],[0,3],[2,0],[3,3],[0,5],[1,2],[1,2],[1,1]],[[5630,7732],[2,-3],[5,-4],[2,-2],[0,-2],[-1,-2],[-2,-2],[-1,-2],[-1,-3],[1,-2],[1,-1],[9,2],[8,-1],[12,-4],[7,-1],[6,1],[11,-3],[9,-3],[10,-1],[5,3],[4,3],[3,6],[8,8],[7,4],[10,4],[7,1],[1,-1],[8,-8],[4,0],[3,-1],[1,-2],[1,0],[4,1],[2,-4],[3,-5],[4,-3],[5,-2],[1,0],[4,0]],[[6405,6675],[-1,-5],[-1,2],[-2,7],[1,6],[-1,7],[0,3],[3,1],[1,-1],[-1,-2],[1,-4],[0,-8],[0,-6]],[[2971,6404],[-1,-4],[-3,-8],[-6,-2],[-7,0],[-1,2],[0,2],[0,3],[0,1],[0,1],[3,2],[1,3],[3,1],[4,-3],[1,0],[3,3],[2,6],[2,0],[-1,-7]],[[2974,6423],[-3,-3],[-1,3],[2,3],[2,-3]],[[2971,6476],[2,-1],[4,-2],[2,-2],[0,-1],[-1,-2],[-3,4],[-3,0],[-3,0],[-2,1],[1,4],[3,-1]],[[2938,6463],[-2,-1],[1,3],[4,5],[2,4],[1,2],[0,1],[2,1],[1,3],[0,3],[-2,4],[0,2],[0,2],[3,1],[0,-3],[1,-8],[-4,-10],[-3,-3],[-4,-6]],[[2943,6493],[0,-1],[-2,-3],[-4,3],[-1,3],[-1,2],[1,2],[2,-1],[1,-3],[4,-2]],[[2921,6502],[0,-1],[-4,12],[-4,2],[-3,3],[1,2],[1,0],[1,4],[-1,4],[-2,8],[-2,5],[0,2],[0,4],[2,-7],[2,-6],[1,-6],[2,-11],[3,-3],[3,-5],[0,-7]],[[2898,6534],[-1,0],[-2,2],[-5,7],[-2,0],[0,4],[2,-1],[4,-6],[1,-3],[3,-3]],[[2932,6570],[-2,-6],[-1,0],[1,8],[1,1],[1,0],[0,-3]],[[2843,6581],[0,-2],[-3,-3],[2,-3],[2,6],[1,-5],[1,-9],[0,-1],[0,-1],[0,-2],[0,-2],[-1,-8],[-6,1],[0,6],[-1,1],[-1,9],[-2,3],[-2,8],[1,2],[2,-1],[1,1],[3,1],[1,1],[2,-2]],[[2908,6578],[0,-3],[-2,0],[-3,-1],[-1,0],[1,2],[2,3],[0,2],[-2,4],[-3,9],[-1,3],[-1,3],[-2,4],[0,2],[1,0],[1,-1],[4,-13],[0,-1],[6,-13]],[[2851,6625],[-3,-2],[-2,2],[-1,0],[1,2],[2,1],[4,1],[1,-2],[0,-1],[-2,-1]],[[2840,6607],[0,-7],[0,-5],[0,-2],[-3,-4],[-1,-2],[-2,-2],[-2,-2],[-1,4],[-2,3],[0,5],[-1,-2],[-2,1],[-3,4],[-2,4],[3,1],[0,-3],[2,4],[0,2],[-1,0],[0,4],[3,9],[1,6],[-2,10],[2,0],[3,-3],[2,-3],[0,-5],[1,-4],[2,-8],[3,-5]],[[2871,6652],[4,-7],[4,-2],[4,-8],[2,-3],[0,-3],[0,-12],[-1,-7],[0,-6],[-1,1],[-1,5],[-2,2],[0,1],[3,1],[0,6],[1,5],[0,6],[-3,6],[-3,5],[-3,1],[-4,6],[-2,0],[-2,-1],[1,3],[0,5],[1,0],[2,-4]],[[2819,6723],[4,-1],[2,0],[1,1],[5,0],[4,1],[0,-3],[0,-1],[-8,-2],[-8,-4],[-5,-3],[-2,-1],[-1,2],[-5,9],[1,-1],[4,-5],[2,1],[2,3],[1,3],[-1,1],[1,4],[3,-4]],[[2855,6676],[-1,-1],[-2,6],[-2,2],[3,4],[1,3],[0,8],[1,4],[-1,4],[1,4],[-1,4],[-2,3],[-5,13],[-8,3],[-4,0],[2,3],[2,-1],[3,-1],[4,-1],[2,-3],[3,-6],[2,-2],[0,-1],[0,-1],[1,-2],[2,-2],[3,-4],[1,-11],[-4,-6],[0,-16],[-1,-3]],[[5527,7768],[1,0],[3,2],[3,1],[2,-1],[1,-1],[0,-1],[0,-5],[-2,-5],[-2,-5],[-2,-4],[0,-3],[0,-4],[0,-3],[0,-2],[0,-1],[3,-2],[3,-3],[2,-4],[3,-5],[1,-1],[0,-2],[-1,-2],[-2,0],[-3,0],[-1,1],[-1,-1],[-1,-1],[0,-1],[3,-6],[4,-8],[0,-3],[0,-3],[-1,-2],[-2,0],[-1,2],[-1,0],[-2,-1],[-1,-3]],[[5533,7691],[-1,0],[-2,0],[-1,-1],[-1,1],[-1,1],[-1,-1],[0,-2],[1,-3],[1,-5],[0,-4],[-1,0],[-2,3],[-1,1],[-1,-1],[-3,-3],[-2,-3],[0,-2],[-1,-3],[0,-1],[0,-6],[-4,-1],[-1,-1],[0,-1],[0,-7],[0,-4],[3,-6],[0,-2],[-1,-1],[-1,-3],[-1,-1]],[[5512,7635],[-3,2],[-1,0],[-5,6],[-2,3],[-4,3],[-2,3],[-1,3],[-2,1],[-2,-1]],[[5490,7655],[-2,2]],[[5488,7657],[2,1],[0,1],[0,2],[-1,2],[-6,9],[-3,6],[-1,2],[0,6],[0,2],[-5,2],[-5,8],[-5,7],[-1,2],[-3,6],[-3,5],[-3,4],[-2,3],[-2,6],[-1,7],[-1,7],[-1,3],[-2,1],[-4,8],[-4,5],[0,5],[0,9],[1,10],[1,1],[2,1],[2,0],[2,-1],[3,-7],[2,-3],[2,-1],[2,3],[3,6],[2,3],[7,-1],[3,5],[6,-6],[3,-1],[1,1],[2,-1],[4,-2],[1,0],[1,0],[3,2],[1,0],[3,-5],[2,0],[2,2],[1,2],[4,-1],[3,0],[1,0],[2,0],[2,-1],[2,-1],[5,-1],[2,-3],[1,-3],[0,-1],[0,-2],[2,-2],[3,-1],[1,0]],[[3254,6213],[0,1],[-1,1],[0,1],[2,-1],[0,-1],[-1,-1]],[[5781,8418],[4,-5],[1,-1],[2,2],[1,0],[4,1],[2,-2],[1,-4],[2,-2],[1,-1],[5,3],[2,2],[1,0],[6,-4],[2,-1],[1,-2],[0,-2],[-1,-2],[0,-3],[1,-4],[2,-2],[4,4],[2,1],[2,0],[2,2],[1,2],[2,0],[3,0],[5,0],[6,-3],[1,-1],[3,-4],[1,-2],[1,-1],[2,-1],[2,-2],[2,1],[0,-1],[1,-1],[0,-3],[0,-7],[-1,-3],[-1,-1],[-1,-2],[0,-1],[2,-3],[2,-5],[1,-3],[0,-2],[-3,-7],[-1,-1],[-1,-3],[0,-3],[0,-2],[5,-5],[4,-3],[1,-1],[0,-1],[-2,-5],[0,-2],[3,-2],[1,-3],[2,-6],[3,-6],[6,-4],[5,-4],[0,-1],[1,-2],[-1,-4],[-1,-4],[-1,-3],[2,-1],[5,0],[6,0],[7,-6],[0,-2],[-1,-2],[1,-2],[0,-2],[6,-6],[1,-1],[0,-3],[0,-2],[-2,-1],[-2,0],[-3,-3],[-1,-3],[-5,-5],[-3,-2],[-2,0],[-6,1],[-2,2],[-1,2],[-2,1],[-3,0],[-4,0],[-1,-1],[0,-2],[-2,-5],[-1,-3],[1,-1],[1,-3],[3,-4],[2,-4],[1,-2],[0,-2],[-1,-2],[0,-4],[3,-5],[-1,0],[0,-7],[0,-6],[0,-2],[2,-1],[1,-2],[2,-6],[0,-1]],[[5882,8185],[-6,0],[-6,0],[-3,-3],[-2,1],[-2,0],[-3,-1],[-4,-6],[-2,-3],[-3,-5],[0,-2],[-2,-5],[-1,-5],[0,-4],[1,-4],[1,-3],[0,-3],[-1,-2],[-1,-3],[-3,0],[-3,3],[-1,4],[-2,3],[-2,2],[-2,0],[-5,-1],[-5,-1],[-5,-1],[-2,-1],[-3,-2],[-2,2],[-2,5],[-1,5],[-1,2],[-1,0],[-1,0],[-2,-1],[-1,-2],[-1,0],[-2,-2],[-2,-1],[-1,-5],[-2,1],[-1,1],[-1,5],[-2,1],[-3,0],[-4,1],[-3,1],[-1,0],[-2,-2],[-1,0],[-5,1],[-1,0],[-1,-3],[-1,-3],[-1,0],[-1,1],[1,4],[-3,2],[-4,0],[-3,0],[-1,0],[-1,1],[-4,8],[-2,0],[-3,0],[-5,1],[-6,2],[-3,0],[-1,2],[-4,1],[-9,3],[-4,1],[-6,0],[-9,0],[-5,0],[-3,-1],[-3,-1],[-5,-1],[-2,1],[-3,-1],[-4,-1],[-1,-1],[-1,-4],[-4,-6],[-4,-5],[-1,0],[-3,2],[-2,1],[-2,0],[-2,0],[-1,-2],[0,-4],[0,-1]],[[5655,8151],[-2,6],[0,5],[1,3],[2,3],[-1,4],[1,5],[0,4],[0,2],[-1,2],[-3,2],[-1,2],[-4,2],[-3,3],[-1,1],[0,2],[1,1],[3,6],[3,5],[2,2],[10,6],[1,2],[1,4],[0,3],[0,5],[-1,7],[-1,5],[-2,9],[-5,19],[-3,20]],[[5652,8291],[2,-2],[5,0],[4,1],[2,1],[1,-1],[3,1],[2,0],[2,-1],[2,-2],[4,2],[4,3],[4,0],[1,1],[1,7],[1,1],[5,0],[2,1],[2,3],[3,3],[2,0],[3,2],[1,-2],[1,-2],[-1,-3],[0,-1],[2,-1],[3,0],[2,1],[0,1],[0,3],[0,2],[-2,2],[-2,1],[-2,0],[0,1],[1,3],[1,5],[2,4],[1,2],[0,1],[0,3],[0,4],[2,7],[2,5],[3,2],[3,1],[3,2],[1,3],[0,2],[1,2],[1,1],[8,-1],[2,4],[0,2],[2,1],[1,1],[0,2],[-2,0],[-6,1],[-1,1],[1,2],[1,5],[1,5],[1,5],[0,2]],[[5738,8390],[1,1],[4,1],[1,1],[4,6],[3,1],[7,-2],[3,0],[1,0],[3,0],[1,0],[1,6],[2,2],[5,8],[4,3],[2,1],[1,0]],[[2559,6187],[-2,-8],[0,3],[1,6],[1,2],[1,2],[0,2],[1,-1],[0,-2],[-2,-4]],[[2557,6216],[-2,-1],[1,3],[1,3],[1,8],[1,0],[1,0],[-3,-13]],[[2530,6099],[-1,0],[-5,1],[-3,-1],[0,15],[1,22],[0,16],[0,16],[0,12],[1,16],[0,14]],[[2523,6210],[0,5],[1,4],[2,2],[3,-4],[1,-1],[1,0],[2,3],[2,6],[4,12],[2,9],[1,2],[3,0],[2,0]],[[2547,6248],[-1,-7],[1,-1],[1,1],[4,0],[1,-7],[0,-6],[-3,-16],[-1,-6],[-1,-8],[2,-5],[-2,-7],[-1,-5],[0,-7],[1,-13],[-1,-19],[-3,-8],[-2,-4],[-2,-8],[-4,-2],[-5,-14],[-1,-3],[0,-4]],[[3202,7044],[-3,-2],[-1,0],[0,1],[2,2],[3,4],[-1,-5]],[[3384,4022],[1,10],[-1,8],[0,2],[-9,10],[-7,9],[-10,12],[-12,0],[-13,-1],[-13,-5],[-12,-5],[-5,-3],[-12,-4],[-7,-3],[-2,-9],[-2,-14],[-3,-9],[-3,-8],[-4,-13],[0,-14],[0,-15],[-3,-19],[-3,-17],[-2,-17],[-2,-11],[-1,-3]],[[3133,3869],[-4,-2],[-7,-2],[-3,0],[-2,1],[-1,1],[-2,2],[0,2],[0,4],[0,5],[0,8],[-2,9],[0,3],[0,5],[-1,8],[-2,5],[-1,7],[0,6],[-2,8],[-1,9],[0,9],[-3,10],[-3,10],[-3,2],[-1,1],[0,3],[0,5],[0,2],[2,5],[0,1],[0,1],[-6,6],[-1,2],[0,3],[0,2],[1,2],[1,2],[-2,5],[1,4],[-1,2],[0,2],[1,1],[3,1],[1,5],[0,3],[0,3],[-4,7],[0,1],[4,9],[2,6],[1,2],[0,1],[-1,1],[-1,3],[-2,2],[-2,3],[-2,5],[-3,4],[-2,4],[-1,3],[0,4],[0,5],[-2,9],[0,6],[-1,7],[0,4],[-1,5],[0,4],[-1,4],[1,2],[1,2],[-1,1],[-5,5],[-1,1],[-1,10],[-4,9],[0,6]],[[3069,4175],[0,1],[0,2],[0,4],[-2,3],[-1,3],[-1,2],[1,3],[3,6],[2,1],[0,2],[1,3],[4,8],[1,5],[2,3],[3,2],[0,2],[0,6],[0,4],[1,2],[2,3],[2,2],[0,1],[0,1],[-2,3],[-3,3],[-3,-1],[-1,3],[-1,2],[-5,23],[-1,6],[0,2],[4,12],[1,4],[2,5],[0,2],[-4,10],[-1,4],[0,4],[0,6],[2,2],[1,5],[1,4],[0,1],[2,3],[1,3],[2,3],[1,3],[0,6],[1,2],[2,2],[1,2],[-1,4],[-1,5],[-1,2],[-2,11],[-1,6],[1,2],[1,3],[0,5],[1,7],[0,24],[0,5],[1,3],[2,4],[1,2],[2,2],[0,5],[1,2],[1,4],[-4,13],[-3,12],[-3,11],[-4,13],[-2,8],[-3,10],[-3,9],[-3,13]],[[3067,4553],[3,0],[7,0],[6,-2],[4,-1],[2,-2],[0,-3],[2,-2],[1,1],[2,0],[3,3],[3,2],[2,3],[1,2],[3,9],[3,4],[2,2],[4,1],[2,-2],[2,0],[1,5],[2,6],[5,6],[2,2],[2,3],[2,0],[2,2],[11,17],[4,5],[3,0],[2,1],[4,3],[9,2],[6,1],[2,-2],[3,0],[1,4],[2,1],[1,0],[2,-4],[1,-5],[-1,-3],[0,-6],[1,-7],[-1,-6],[-2,-8],[-1,-3],[0,-3],[0,-5],[1,-7],[2,-11],[0,-7],[-1,-5],[-1,-4],[0,-4],[1,-2],[1,-2],[0,-3],[0,-4],[1,-4],[2,-4],[1,-4],[0,-4],[0,-2],[1,-1],[0,1],[1,1],[1,0],[1,-6],[0,-1],[1,-4],[0,-3],[3,-2],[2,-1],[1,-2],[3,-5],[2,-3],[3,-3],[1,-4],[1,-7],[5,-2],[5,-1],[4,-2],[4,4],[3,-1],[2,-2],[2,-2],[2,-3],[3,-5],[3,-1],[2,2],[1,1],[2,-1],[1,-5],[0,-3],[2,-2],[3,-6],[2,-3],[2,0],[5,-4],[5,-4],[2,0],[3,0],[1,-1],[1,-5],[4,-9],[2,-4],[2,-3],[6,0],[2,-1],[3,1],[8,1],[1,1],[5,-4],[5,-6],[3,-5],[3,-2],[1,-5],[1,-4],[1,-5],[-1,-4],[-1,-2],[0,-3],[0,-5],[2,-4],[1,-5],[1,-8],[1,-3],[0,-27],[-3,-1],[-5,0],[1,-2],[4,-11],[4,-9],[1,-15],[0,-9],[1,-13],[0,-8],[10,-1],[11,-1],[13,-1],[12,-1],[1,0],[2,1],[1,2],[1,0],[0,-3],[0,-4],[0,-5],[-4,-9],[0,-3],[1,-12],[1,-10],[1,-9],[1,-3],[4,-4],[6,-9],[2,-1],[2,1],[1,-3],[1,-6],[3,-16],[2,-10],[1,-4],[2,-1],[-1,-2],[-1,0],[-1,-2],[-1,-11],[-3,-15],[-1,-11],[1,0],[0,-3],[0,-4],[-1,-1],[-1,-1],[-2,-9],[-3,-11],[-2,-12],[-2,-6],[3,-6],[4,-8],[0,-2],[-2,-2],[-2,0],[-1,-4],[-1,-2],[-2,-1]],[[3653,3584],[-2,-2],[0,14],[1,4],[1,4],[2,2],[1,-3],[-1,-7],[-2,-8],[0,-4]],[[3650,3663],[0,-1],[-2,8],[3,6],[1,-2],[0,-6],[-1,-4],[-1,-1]],[[3742,3808],[0,-3],[-1,1],[-3,-1],[-1,2],[4,10],[1,-1],[1,-2],[0,-3],[0,-1],[-1,-2]],[[3774,3851],[1,-2],[-2,0],[-2,-1],[-2,-1],[-2,2],[3,3],[1,3],[0,-1],[1,-1],[2,-2]],[[3919,4408],[-1,-4],[-1,1],[-1,2],[0,2],[0,2],[1,1],[2,0],[0,-4]],[[3923,4429],[-1,-1],[0,4],[3,4],[0,6],[2,-3],[0,-2],[0,-2],[-4,-6]],[[3764,5014],[-3,-5],[1,6],[-1,5],[1,3],[1,4],[1,0],[0,-4],[0,-1],[0,-8]],[[3753,5108],[-2,-3],[0,-1],[-2,1],[0,1],[1,0],[0,5],[3,-1],[0,-2]],[[3560,5101],[-3,-1],[4,15],[3,6],[0,14],[4,11],[3,5],[5,2],[3,-8],[-4,-20],[-1,0],[-4,-11],[-5,-7],[-5,-6]],[[3621,5171],[3,-1],[3,1],[3,3],[3,1],[2,-1],[9,-3],[6,-1],[2,0],[2,-2],[1,-1],[1,-4],[-2,-5],[-1,-5],[-1,-7],[0,-2],[-1,0],[0,-6],[0,-3],[-1,-3],[-1,-5],[-2,-7],[-1,-1],[-2,-3],[-1,-3],[0,-3],[1,-3],[-1,-3],[-2,-6],[-2,-1],[-2,0],[-1,0],[-2,5],[-1,-4],[0,-4],[-1,-2],[-3,0],[-2,2],[-3,3],[0,-7],[-2,-5],[-2,-1],[-2,-1],[-2,-2],[-3,1],[-3,3],[-1,1],[-1,-3],[-7,0],[-3,-3],[-1,1],[-3,5],[0,3],[-2,7],[-1,9],[-1,7],[0,7],[2,0],[2,-1],[1,0],[0,2],[-1,2],[-3,0],[-2,4],[0,6],[0,12],[0,3],[2,3],[0,3],[0,4],[0,6],[2,5],[5,7],[6,2],[17,-6]],[[3593,5176],[-8,-11],[-3,4],[0,2],[0,2],[0,1],[1,4],[4,3],[2,0],[3,-1],[1,-2],[0,-2]],[[3626,5177],[-7,-1],[-4,2],[1,3],[3,4],[3,2],[3,2],[2,-2],[1,-3],[0,-3],[-2,-4]],[[3618,5199],[1,-3],[-4,-12],[-2,-2],[-2,0],[-3,4],[-5,-1],[-2,1],[0,6],[2,5],[4,0],[7,4],[4,-2]],[[3599,5192],[-1,-9],[-5,4],[1,9],[2,2],[2,5],[1,5],[0,8],[1,1],[0,1],[1,-1],[0,-11],[1,-7],[-3,-7]],[[3607,5206],[-4,-2],[0,2],[0,8],[1,4],[4,1],[0,1],[1,1],[1,-3],[0,-4],[-3,-8]],[[3602,5295],[-2,-2],[-2,1],[-1,7],[0,5],[2,2],[2,0],[0,-1],[2,-9],[-1,-3]],[[3431,5296],[1,-1],[1,0],[5,-3],[6,-2],[1,1],[1,2],[0,5],[0,3],[-1,3],[-1,4],[-2,5],[-2,1],[1,2],[1,3],[1,1],[1,2],[0,6],[1,1],[1,0],[1,-2],[5,-5],[2,1],[7,1],[1,3],[2,1],[3,3],[1,0],[1,-1],[1,1],[2,2],[1,-2],[1,-3],[1,-3],[1,-1],[2,1],[2,-1],[0,-2],[0,-2],[1,-2],[2,0]],[[3483,5318],[0,-1],[1,-1],[1,-3],[3,-2],[4,-3],[1,0],[2,-1],[1,-1],[1,2],[4,4],[2,3],[1,2],[1,2],[1,0],[1,-1],[0,-1],[1,-1],[4,-2],[1,0],[2,1],[2,3],[1,1],[2,-3],[0,-4],[1,-1],[1,0],[3,0],[2,-2],[1,1],[2,1],[1,3],[2,3],[3,3],[1,4],[2,5],[1,3],[0,4],[3,13],[1,2],[0,4],[1,5],[0,3],[1,4],[2,3],[1,2],[2,6],[1,5],[3,11],[0,3],[2,2],[0,2],[2,3],[1,3],[1,3],[1,4],[2,2],[1,2]],[[3565,5418],[2,10],[1,4],[2,0],[4,-5],[3,-7],[4,-25],[1,-22],[1,-12],[5,-24],[0,-5],[1,-5],[1,-6],[2,-10],[0,-2],[-1,-2],[1,0],[2,-2],[1,-6],[1,-4],[2,-6],[4,-2],[4,0],[3,-4],[3,-4],[2,-13],[-1,-9],[1,-6],[-2,-3],[-3,-4],[0,-2],[-6,-10],[-2,-5],[-3,-6],[-3,-13],[-5,-11],[-2,-3],[-3,-1],[-1,-2],[-4,-9],[-5,-3],[0,-5],[-3,-13],[-3,-7],[-1,-2],[-5,-12],[0,-5],[0,-10],[-3,-6],[-3,-3],[0,-8],[-1,-3],[-1,-2],[-6,2],[-9,-8],[-3,-3],[10,0],[3,-5],[7,3],[8,11],[3,3],[7,7],[2,5],[5,6],[1,3],[3,3],[1,-4],[0,-2],[-2,-4],[1,-3],[1,-4],[1,-5],[0,-3],[1,-7],[3,-9],[0,-3],[0,-4],[1,-3],[1,-2],[6,-9],[4,5],[2,2],[2,2],[3,1],[2,-2],[6,-3],[3,3],[8,8],[-3,-14],[-1,-12],[-2,-6],[-1,-13],[-1,-4],[-1,-4],[2,1],[1,2],[2,6],[1,9],[6,24],[1,3],[5,2],[8,20],[3,0],[2,-4],[1,-3],[1,5],[3,2],[-3,3],[-1,3],[0,4],[2,5],[-1,5],[4,6],[-1,4],[2,4],[2,4],[2,2],[0,3],[1,2],[1,0],[2,-4],[3,5],[2,2],[1,-1],[1,-2],[1,-1],[1,0],[3,3],[2,-4],[1,-1],[0,2],[-1,3],[1,1],[1,2],[4,-1],[2,-2],[2,-4],[2,0],[3,0],[1,-2],[2,0],[1,-3],[4,-5],[1,-3],[3,-2],[2,-2],[3,0],[3,0],[0,-4],[2,-1],[3,1],[2,-5],[5,-3],[4,-6],[2,1],[3,-1],[3,-12],[0,-9],[2,1],[1,4],[2,7],[3,2],[1,-2],[3,-5],[2,-4],[1,-4],[2,0],[-1,-4],[1,1],[2,2],[2,-5],[1,-6],[0,-6],[-1,-4],[-1,-2],[-1,-5],[-1,0],[-2,-2],[2,-3],[1,-3],[2,8],[2,3],[2,1],[2,-6],[0,-5],[-4,-3],[0,-4],[-1,-3],[-1,-2],[-1,-6],[0,-5],[-3,-22],[0,-4],[3,4],[5,11],[2,12],[2,12],[2,3],[1,0],[2,-1],[1,-4],[-1,-2],[-2,-6],[-1,-3],[1,-3],[5,10],[2,3],[2,-1],[4,5],[8,1],[0,5],[2,2],[4,-1],[8,-4],[3,-4],[4,-3],[2,-4],[10,-8],[7,-1],[3,4],[5,-4],[2,-4],[4,-2],[5,-1],[3,3],[9,1],[11,4],[7,-1],[7,-3],[6,-7],[4,-4],[3,-4],[4,-4],[10,-11],[3,-7],[6,-9],[6,-3],[3,-9],[3,-5],[6,-15],[7,-11],[4,-11],[9,-7],[4,-11],[6,-2],[3,-1],[3,-5],[4,-3],[6,1],[6,-1],[5,3],[12,-5],[2,-2],[2,-5],[5,-18],[2,-20],[2,-15],[3,-12],[1,-23],[2,-7],[0,-6],[1,-1],[1,-15],[-1,-6],[-1,-8],[0,-4],[0,-2],[0,-3],[0,-3],[1,-8],[0,-5],[-2,-7],[-2,-18],[-5,-31],[-5,-17],[-7,-18],[-5,-9],[-2,-1],[-1,2],[1,-5],[-1,-4],[-5,-14],[-5,-8],[-4,-15],[-1,0],[-6,-6],[-4,-5],[-4,-8],[-5,-14],[-1,-2],[-1,1],[0,-7],[-4,-10],[-1,-2],[0,3],[1,2],[0,3],[0,3],[-1,-2],[-2,-8],[0,-6],[-1,-9],[-6,-26],[-8,-22],[-1,-6],[-7,-15],[-4,-7],[-1,0],[-2,1],[-1,11],[-3,6],[-1,2],[-2,-7],[-1,-2],[-2,-1],[2,-3],[1,-4],[-2,-7],[0,-6],[-4,-8],[-2,-5],[-1,-7],[0,-6],[1,2],[1,-1],[1,-2],[-1,-3],[-1,-6],[0,-13],[0,-3],[1,-3],[1,5],[1,-1],[-3,-36],[1,-16],[0,-19],[2,-18],[1,-16],[1,-1],[-3,-19],[-2,-18],[-2,-15],[-1,-16],[-1,-8],[-1,-8],[2,-18],[0,-4],[-3,-8],[-4,-4],[-2,-4],[-5,-16],[-2,-22],[0,-12],[1,-25],[-1,-10],[-1,-7],[-2,-4],[-5,-5],[-3,-13],[-2,-14],[-3,-5],[0,-8],[-2,-8],[-6,-12],[-4,-4],[-1,-3],[-2,-8],[-3,-11],[-3,-16],[1,-5],[0,-1],[1,-18],[0,-4],[-4,-5],[-12,-9],[-4,-4],[-8,-16],[0,-3],[0,-6],[2,-3],[-2,-3],[-1,-6],[-2,0],[-13,0],[-7,-1],[-4,0],[-1,1],[-2,3],[-1,3],[1,4],[0,3],[-2,0],[-2,-1],[-1,-3],[1,-2],[0,-3],[1,-3],[-1,-3],[-4,-1],[-5,-3],[-5,-1],[-5,-2],[-2,3],[2,1],[3,-1],[3,2],[0,3],[-5,3],[-5,-2],[-3,-4],[-6,1],[-7,-3],[-2,-3],[1,-6],[1,-1],[2,-3],[-2,-2],[-1,-1],[-8,-3],[-7,-11],[-3,-2],[-3,-4],[0,-5],[-1,-2],[-2,0],[-4,2],[-5,0],[-3,-2],[-19,-18],[-6,-7],[-8,-15],[-12,-17],[-7,-9],[-1,-3],[-1,0],[-2,-2],[0,-2],[2,0],[-1,-6],[-2,-4],[-5,-10],[-1,1],[1,5],[-2,0],[-4,2],[-1,-2],[0,-5],[-1,-3],[-2,0],[-3,1],[-2,4],[1,-7],[5,-2],[2,-2],[1,-3],[-4,-12],[-3,-2],[-1,-2],[2,0],[1,-3],[-1,-14],[-2,-3],[-1,0],[0,-2],[1,-5],[1,-3],[0,-7],[0,-5],[-1,-5],[2,-10],[1,-11],[1,-3],[0,-5],[-1,-4],[0,-6],[-2,-10],[1,-16],[0,-14],[-1,-8],[-1,-6],[-3,-7],[0,-8],[-6,-7],[-7,-10],[-6,-12],[-7,-16],[-8,-26],[-8,-36],[-8,-27],[-4,-10],[-5,-11],[-6,-12],[-9,-13],[-9,-12],[-4,-5],[-3,-7],[-1,3],[1,5],[0,4],[-1,4],[2,1],[3,-3],[2,2],[1,2],[3,2],[7,12],[4,5],[3,8],[1,4],[-1,8],[2,3],[4,-1],[0,2],[0,3],[1,6],[4,5],[3,6],[-1,16],[1,1],[2,-2],[1,1],[1,7],[-1,3],[-2,1],[-8,-8],[-3,1],[0,6],[-4,3],[-2,5],[0,3],[-1,2],[0,-6],[0,-6],[4,-7],[-1,-3],[-2,-3],[-1,-7],[0,-9],[-1,2],[-1,2],[0,-10],[-3,-4],[0,-3],[0,-5],[-1,-3],[-6,-8],[-6,-5],[-1,-3],[-1,-6],[-1,-6],[-2,-6],[-2,-11],[0,-4],[1,-7],[1,-5],[-2,-3],[-2,-6],[-2,-7],[-5,-25],[-4,-15],[-3,-7],[-4,-8],[-13,-20]],[[3517,3240],[-1,1],[-1,1],[-2,2],[0,1],[-1,2],[1,7],[0,19],[0,4],[1,2],[2,3],[3,5],[2,6],[3,5],[-1,3],[-2,4],[-4,2],[-3,5],[-3,5],[-2,6],[-1,7],[-1,5],[-1,2],[-1,1],[-2,3],[-1,2],[-2,2],[-3,1],[-3,3],[-5,6],[-3,7],[-1,5],[-2,3],[-8,6],[-4,6],[-2,-2],[-2,2],[-2,3],[-1,3],[-1,2],[-1,3],[0,3],[-3,4],[-3,5],[-1,2],[-1,-1],[0,-2],[-1,-1],[-1,-2],[-1,-2],[-2,-3],[-1,-2],[-3,0],[-1,0],[0,1],[0,4],[0,9],[-1,3],[-2,4],[-2,5],[-6,10],[-9,15],[-3,5],[-3,0],[-3,0],[-2,-2],[-2,-7],[-1,-1],[-4,0],[-5,1],[-2,4]],[[3483,3711],[0,8],[4,12],[1,6],[-1,3],[1,11],[3,20],[1,13],[-1,6],[0,4],[1,4],[1,1],[-4,4],[-2,4],[-2,3],[-3,2],[-1,-1],[-1,-1],[-3,-2],[-3,-4],[-2,-1],[-2,-1],[-4,-2],[-2,1],[-2,1],[-2,2],[0,5],[0,4],[-1,6],[-2,4],[0,3],[0,3],[0,3],[0,3],[0,3],[-1,3],[1,4],[-1,5],[-1,4],[0,4],[0,4],[-1,4],[0,4],[0,4],[1,4],[-1,3],[-2,2],[-1,4],[0,6],[-1,3],[-2,3],[-1,0],[-3,1],[-2,0],[-3,0],[-2,1],[-1,2],[-2,3],[-1,5],[-1,1],[-2,-1],[-1,-2],[-1,-3],[-1,-3],[-2,0],[-2,-1],[-2,-1],[-3,0],[-2,2],[-4,1],[-2,1],[-3,-1],[-2,1],[-2,1],[-2,0],[-2,3],[-3,2],[-1,-1],[-1,-2],[-2,1],[-2,1],[-1,4],[0,2],[1,3],[0,3],[0,3],[0,3],[1,3],[0,3],[0,3],[0,3],[-1,3],[0,3],[1,4],[1,4],[0,3],[0,2],[0,3],[1,5],[0,7],[-1,5],[0,1],[-1,2],[1,1],[-1,2],[0,2],[1,2],[-1,3],[-1,1],[-1,1],[0,4],[-1,4],[0,3],[0,3],[-1,2],[-1,3],[-1,2],[0,3],[-1,4]],[[3067,4553],[-3,0],[-4,1],[-4,0],[-3,-3],[-4,-4],[-2,0],[-1,-1],[-2,1],[-1,2],[-3,4],[-1,-1],[-2,-2],[0,9],[0,15],[0,13],[1,10],[0,12],[0,9],[1,3],[1,4],[-1,5],[0,4],[0,3],[1,3],[-2,-1],[0,-1],[-1,-2],[-3,-4],[-1,-3],[-2,-2],[-3,-6],[-2,-3],[-2,-2],[-3,-6],[-3,-2],[-7,-1],[-8,0],[-7,1],[-1,0],[0,5],[0,4],[-3,4],[0,5],[0,3],[-1,4],[-2,3],[-2,1],[-4,2],[-6,3],[-5,0],[-6,0],[3,8],[4,8],[0,8],[-3,6],[-1,4],[-3,6],[-2,3],[-2,5],[0,3],[0,2],[-1,2],[-1,1],[-2,2],[-1,3],[0,3],[-1,3],[-1,3],[0,3],[-1,4],[-1,3],[-1,2],[-2,3],[0,2],[2,1],[0,3],[0,3],[-1,1],[-2,1],[-2,5],[-1,2],[-1,2],[-1,2],[1,1],[0,1],[0,3],[0,3],[0,2],[1,0],[1,0],[1,1],[2,1],[1,0],[1,2],[0,2],[-1,6],[-1,2],[0,3],[0,6],[1,4],[2,4],[5,9],[5,6],[2,1],[2,2],[1,3],[0,4],[0,3],[-1,5],[-1,6],[-1,4],[1,4],[1,5],[3,8],[2,9],[1,3],[0,5],[1,11],[1,6],[0,3],[0,2],[2,1],[3,2],[3,3],[4,6],[3,7],[3,2],[4,6],[3,4],[1,2],[3,2],[5,1],[4,1],[2,2],[4,1],[2,2],[2,0],[5,2],[2,3],[1,4],[2,3],[2,1],[3,0],[3,0],[3,1],[2,-3],[0,-3],[3,-3],[1,0],[2,1],[2,-3],[1,1],[1,1],[0,4]],[[3056,4940],[1,2],[1,12],[1,19],[2,18],[2,19],[1,20],[2,21],[2,16],[1,15],[1,8],[1,12],[0,10],[1,3],[0,2],[-1,4],[0,1],[0,2],[0,2],[-2,2],[0,1],[-1,2],[0,2],[-1,3],[0,2],[-1,2],[0,2],[0,3],[1,2],[-1,2],[0,3],[-1,2],[-1,2],[-2,2],[-2,4],[-3,4],[-3,6],[-1,4],[0,9],[0,10],[1,15],[0,7],[2,1],[1,0],[2,0],[2,1],[1,1],[1,1],[1,1],[1,0],[1,1],[1,1],[1,1],[2,1],[1,-2],[1,-2],[1,-1],[1,1],[1,-1],[0,-1],[1,0],[1,0],[1,0],[1,1],[0,1],[-1,1],[0,2],[0,2],[0,3],[0,4],[0,2],[-1,3],[-1,3],[-2,2],[-1,1],[-1,-1],[-1,0],[-1,1],[-1,0],[-2,0],[-1,1],[-3,-1],[-1,1],[-1,0],[-2,-1],[0,14],[0,14],[0,9],[2,0],[1,2],[3,0],[2,2],[1,0],[2,-1],[2,-2],[2,0],[6,0],[5,0],[7,0],[6,0],[6,0],[2,0],[-1,3],[-1,4],[0,3],[1,4],[0,1],[2,-2],[2,-5],[1,-4],[1,-2],[2,0],[1,0],[2,2],[3,8],[3,6],[1,2],[2,2],[1,1],[1,0],[2,-2],[1,-3],[3,-11],[2,-8],[1,-5],[0,-13],[0,-11],[0,-1],[1,0],[5,2]],[[3142,5254],[7,-13],[5,-10],[3,-3],[1,-1],[3,1],[4,1],[1,1],[2,4],[4,4],[2,2],[1,0],[1,0],[2,-3],[2,-5],[-1,-5],[0,-4],[2,1],[2,5],[1,5],[3,3],[2,6],[2,5],[2,3],[4,3],[2,2],[3,0],[1,2],[3,5],[1,3],[1,1],[3,0],[2,1],[3,4],[3,5],[1,9],[1,7],[1,2],[1,1],[1,1],[2,1],[5,4],[3,4],[3,1],[1,1],[1,4],[0,7],[0,4],[-6,1],[-3,0],[-6,1],[-3,2],[0,1],[0,1],[0,3],[1,6],[-1,7],[-3,12],[-2,11],[0,8],[0,9],[0,5],[-2,5],[-8,13],[-3,7],[-1,4],[-3,9],[1,2],[2,0],[1,-2],[2,-5],[1,-1],[1,0],[8,0],[2,0],[1,-2],[1,-2],[1,-5],[1,-3],[3,0],[5,0],[3,1],[1,-2],[2,-1],[4,3],[1,0],[1,-1],[5,-10],[2,-4],[3,-5],[3,0],[2,4],[1,16],[1,4],[1,1],[2,1],[1,2],[2,3],[2,1],[7,-3],[2,1],[7,5],[8,5],[2,6],[3,2],[2,5],[2,-1],[3,0],[2,1],[1,1],[1,2],[2,7],[2,2],[2,3],[2,3],[2,4],[0,3],[0,2],[-1,6],[-1,4],[-1,2],[-1,0]],[[3312,5483],[3,2],[2,-2],[3,0],[2,1],[2,-1],[2,4],[2,-1],[1,0],[1,-3],[1,-3],[2,-3],[0,-6],[0,-5],[-1,-5],[0,-4],[-1,-4],[-1,-4],[-1,-2],[0,-2],[1,-1],[2,-1],[2,0],[2,-1],[2,0],[2,-4],[1,-2],[0,-1],[0,-4],[-1,-4],[1,-2],[1,-2],[2,-7],[0,-3],[1,-1],[0,-2],[0,-3],[-1,-3],[-2,-4],[0,-3],[-2,-2],[-3,-5],[1,-7],[0,-3],[0,-3],[-1,-4],[-2,-11],[-1,-6],[-1,-13],[0,-4],[1,-6],[2,-13],[1,-2],[3,-3],[0,-9],[0,-9],[0,-4],[0,-1],[1,-1],[1,-1],[0,-3],[0,-3],[2,-1],[2,-1],[1,-4],[3,-6],[1,-1],[1,-3],[2,-5],[4,-2],[4,-2],[1,-3],[2,-3],[1,0],[1,0],[1,3],[2,2],[2,-1],[2,1],[1,1],[0,2],[-1,6],[1,1],[3,1],[0,3],[0,1],[1,2],[1,0],[1,-1],[1,0],[2,-1],[1,-2],[1,0],[2,0],[0,1],[1,2],[0,5],[1,0],[2,1],[2,2],[3,0],[3,0],[1,1],[1,3],[3,8],[1,2],[2,1],[1,0],[2,1],[2,2],[1,-1],[1,-4],[1,-1],[1,0],[4,-2],[2,1],[2,1],[2,1],[1,-1],[2,1],[1,1]],[[3347,5937],[-1,-1],[-2,2],[-1,3],[0,9],[1,1],[3,-7],[2,-3],[-2,-4]],[[8194,5466],[4,0]],[[8198,5466],[0,-2],[2,-7],[1,-6],[0,-11],[2,-4],[-1,-1],[-2,-1],[-2,1],[-1,2],[-2,11],[-1,6],[0,7],[0,5]],[[8194,5466],[-2,-2],[-2,-4],[-2,-2],[-1,-2],[0,-3],[0,-7],[1,-5],[1,-2],[0,-2],[0,-2],[-1,-5],[-1,-6],[-1,-4],[-2,-4],[-1,0],[-1,1],[-2,4],[-2,5],[-1,3],[-2,0],[-1,3],[0,3],[-1,3],[-1,4],[-1,3],[-3,2],[0,1]],[[8168,5448],[3,0],[3,1],[4,3],[3,4],[3,4],[2,5],[3,4],[5,4],[1,0],[0,-3],[-1,-4]],[[7545,6783],[-1,-2],[0,-3],[-1,-4],[1,-3],[1,-4],[3,-3],[3,0],[2,1],[2,0],[1,-5],[1,-4],[-1,-5],[-1,-4],[0,-2],[0,-1],[1,-3],[1,-3],[0,-4],[-1,-2],[-1,-1],[-2,0],[-1,0],[-2,-1],[-2,-1],[-2,-1],[-5,0],[-1,3],[-1,0],[-4,-4],[-4,1],[-8,-2],[-3,0],[-4,0],[-1,1],[-3,3],[-3,3],[-3,-2],[-1,-1],[-2,-5],[-5,-2],[-5,-1],[-2,0],[-3,1],[0,1],[0,1],[0,1],[-1,1],[-2,1],[-3,1],[-1,1],[-5,-2],[-3,3],[-4,4],[-1,2],[-1,6],[-1,2],[-1,2],[-1,2],[1,3],[3,4],[0,1]],[[7468,6757],[2,9],[2,3],[2,4],[2,7],[3,7],[3,7],[3,6],[1,3],[4,3],[2,1],[2,4],[2,2],[3,1],[3,0],[3,-1],[4,-2],[0,-2],[0,-3],[0,-3],[0,-1],[0,-1],[4,0],[4,0],[2,0],[5,-3],[2,-2],[2,-1],[1,0],[2,3],[2,3],[2,0],[1,-1],[1,-2],[4,-2],[3,-2],[1,-2],[0,-7],[0,-2]],[[5701,4159],[0,-3],[-1,-4],[1,-3],[1,-4],[1,-4],[2,-2],[1,-6],[1,-6],[2,-5],[6,-12],[1,-5],[0,-4],[4,-8],[1,-3],[-1,-5],[4,-17],[2,-10],[2,-1],[7,-11],[5,-8],[7,-6],[5,-3],[2,-3],[2,-3],[1,-5],[0,-8],[0,-6],[5,0],[5,0],[1,-1],[1,-2],[0,-3],[0,-6],[0,-4],[0,-5],[-1,-6],[0,-6],[1,-3],[4,-9],[2,-5],[1,-9],[2,-3],[0,-1],[4,-1],[10,-3],[6,-4],[5,-3],[2,-1],[1,-1],[-1,-8],[1,-2],[0,-2],[1,-2],[1,-1],[4,-1],[2,-4],[1,-3]],[[5815,3905],[-6,-1],[-4,-3],[-2,-7],[-2,-5],[-4,-3],[-5,-2],[-4,-2],[-5,-5],[-5,-11],[-3,-6],[0,-3],[-1,-2],[-2,-2],[-1,-3],[-1,-2],[-1,-2],[-2,0],[-1,-2],[-1,-4],[-2,-2],[-2,-1],[-3,-2],[-2,-4],[-1,-2],[-2,0],[-1,-3],[-3,-8],[0,-3],[-4,-27],[-2,-4],[-4,-5],[-3,-7],[-2,-4],[-1,-2],[-8,-3],[-2,-2],[-4,-3],[-1,-2],[0,-8],[-3,-13],[-2,-9],[-1,-7],[-2,-10],[-2,-3],[-2,-3],[-3,-2],[-3,-1],[-4,1],[-2,-1],[-4,-3],[-3,0],[-5,2],[-5,2],[-2,0],[-4,6],[-2,0],[-4,1],[-2,1],[-2,3],[-4,7],[-4,5],[-4,3],[-3,1],[-4,-1],[-2,-1],[-1,-1],[-2,-2],[-2,-6],[-2,-7],[0,-5],[-2,-11],[-3,-12],[-1,-3],[-1,-3],[-2,-2],[-7,-10],[-4,-11],[-2,-3],[-3,-2],[-2,-1],[-1,-2],[-2,-5],[-1,-2],[-1,-1],[-4,1],[-2,0],[-10,-1],[-4,2],[-2,1],[-3,-3],[-2,2],[-1,4],[-1,10],[0,8],[2,6],[2,4],[2,6],[0,2],[0,3],[-1,4],[0,5],[-2,11],[-3,14],[-4,15],[-1,4],[-2,7],[-9,13],[-2,2]],[[5554,3757],[0,1],[0,13],[0,16],[0,17],[0,16],[0,17],[0,16],[0,17],[0,16],[0,17],[0,14],[7,0],[8,0],[9,0],[4,0],[0,2],[0,10],[0,24],[0,23],[0,24],[0,23],[0,24],[0,23],[0,24],[0,23],[0,12],[7,0],[8,3],[14,4],[12,4],[8,3],[10,3],[3,1],[1,0],[2,-2],[4,-11],[3,-9],[0,-4],[1,0],[1,0],[2,2],[4,9],[1,2],[3,4],[4,5],[3,3],[3,2],[2,0],[1,-3],[2,-1],[7,11],[3,2],[9,2],[1,0]],[[5634,5813],[2,-7],[1,-3],[8,-17],[2,-4],[4,-12],[2,-8],[3,-12],[1,-7],[-1,-5],[0,-16],[-1,-5],[-4,-8],[0,-4],[1,-3],[1,-2],[1,-1],[-1,-7],[2,-3],[2,-2],[7,-2],[3,-1],[3,-1]],[[5670,5683],[2,-1],[0,-2],[-1,-9],[1,-5],[2,-5],[3,-2],[2,-1],[8,-2],[3,-3],[4,-10],[5,-9],[2,-5],[0,-5],[-2,-5],[0,-2],[3,-5],[2,-6],[6,-6],[9,-9],[4,-7],[1,-4],[2,-6],[4,-4],[2,-4],[-2,-10],[1,-4],[0,-3],[2,-4],[1,-5],[2,-7],[2,-3],[4,-1],[2,-3],[4,-5],[4,-4],[1,-4],[1,-2],[1,-4],[1,-3],[0,-7],[1,-9],[2,-5],[2,-5]],[[5761,5478],[-8,5],[-2,0],[-1,-1],[-4,-6],[-2,-1],[-1,1],[-4,1],[-13,5],[-9,4],[-3,2],[-6,2],[-3,-3],[-3,-12],[-1,-2],[-5,-3],[-3,1],[-6,-3],[-9,4],[-3,-1],[-3,-2],[-6,-5],[-4,-3],[-5,-2],[-4,-4],[-3,-3],[-3,0],[-3,3],[-2,2],[-4,0],[-3,-1],[-3,-5],[-2,-3],[-2,-8],[-3,-14],[-2,-3],[-1,-1],[-14,7],[-6,1],[-4,-2],[-5,4],[-3,1],[-1,-1],[-3,1],[-4,5],[-5,2],[-4,-1],[-2,2],[-2,4],[-3,9],[-5,8],[-6,7],[-4,5],[-1,3],[-4,2],[-5,0],[-5,-3],[-7,-10],[-6,-22],[-4,-8],[-3,-2],[-1,-5],[2,-8],[0,-9],[-1,-16],[0,-12]],[[5516,5384],[-1,2],[-2,5],[0,1],[-5,-2],[-2,-2],[-1,-2],[-1,-1],[-1,3],[-2,1],[-1,-1],[-2,0],[-1,1],[-1,-1],[-2,2],[-7,5],[-2,1],[-1,0],[-4,-4],[-2,-1],[-6,-2],[-7,-2],[-2,0],[-2,-1],[-1,-3],[-1,-5],[-1,-9],[-1,-3],[0,-4],[0,-6],[0,-5],[0,-4],[-2,-8],[-2,-9],[-2,-8],[-2,-7]],[[5449,5315],[-1,5],[-1,6],[0,8],[0,1],[-1,3],[0,6],[0,3],[0,4],[-2,4],[-1,3],[-1,3],[-1,1],[-1,1],[-2,1],[-3,6],[-3,6],[-3,7],[-3,6],[-3,8],[-3,7],[-2,7],[-1,4],[1,1],[1,0],[1,0],[0,2],[-1,6],[-1,7],[-1,4],[-4,6],[-3,5],[-1,3],[-1,4],[-1,23],[-1,6],[-1,3],[-1,1],[0,2],[0,4],[1,4],[0,1],[0,3],[0,22],[0,1],[-1,2],[-1,-1],[-1,1],[-1,3],[-1,4],[1,2],[1,3],[1,2],[1,1],[4,4],[1,2],[1,2],[0,2],[2,11],[4,11],[1,3],[2,7],[1,9],[1,4],[1,4],[1,3],[4,6],[2,9]],[[5429,5617],[3,0],[4,-2],[4,-1],[3,2],[2,4],[4,3],[5,3],[1,5],[2,3],[1,3],[1,0],[0,-2],[1,-5],[2,-5],[4,-6],[1,0],[2,4],[5,3],[1,1],[4,7],[4,4],[1,0],[1,1],[5,5],[3,-1],[5,1],[8,2],[6,0],[3,1],[1,1],[1,6],[1,2],[2,3],[5,9],[3,8],[0,2],[0,1],[1,0],[1,3],[-1,4],[-5,7],[0,1],[0,1],[0,1],[2,3],[3,3],[2,1],[7,0],[6,1],[2,-1],[4,2],[4,2],[3,3],[8,0],[6,8],[2,2],[0,1],[1,1],[2,4],[4,7],[2,6],[1,4],[7,15],[3,0],[1,2],[3,10],[0,2],[2,0],[1,2],[2,2],[1,5],[0,5],[-1,5],[0,2],[1,2],[1,2],[6,5],[1,3],[1,2],[1,1],[2,-1],[1,2],[1,2],[4,4],[3,2],[4,-1],[3,-1],[2,-2],[1,0]],[[3339,7715],[-4,-2],[-3,0],[-2,2],[5,0],[2,0],[4,3],[-2,-3]],[[3159,7735],[-2,-2],[1,2],[1,5],[2,1],[-2,-6]],[[3145,7757],[-4,-3],[2,8],[1,3],[2,-1],[-1,-5],[0,-2]],[[3306,7804],[-1,-1],[0,1],[-2,3],[0,1],[2,1],[3,-1],[-1,-3],[-1,-1]],[[2953,7809],[-4,-1],[-1,1],[4,5],[4,2],[-3,-7]],[[2956,7803],[-2,-1],[-4,1],[-4,-2],[-1,0],[3,4],[5,3],[4,8],[2,0],[-2,-9],[0,-3],[-1,-1]],[[3027,7884],[-3,-1],[1,2],[3,4],[3,2],[1,0],[-2,-5],[-3,-2]],[[3302,7830],[1,0],[4,2],[2,0],[0,-2],[-3,-2],[-2,-1],[2,-2],[0,-1],[-2,-2],[-1,-3],[1,-3],[3,3],[2,0],[2,-1],[2,1],[1,1],[6,10],[0,2],[-7,-3],[0,2],[4,6],[0,3],[2,5],[2,3],[2,2],[2,1],[1,-2],[1,-4],[3,0],[4,-1],[3,-1],[0,-2],[0,-1],[-1,-3],[-1,-3],[3,-3],[-1,-1],[-4,-4],[-3,-3],[-3,-4],[-5,-6],[-8,-3],[-2,0],[-3,1],[-3,0],[-3,-2],[-3,0],[-1,0],[-2,0],[-1,1],[-2,4],[-1,3],[-2,13],[1,7],[2,6],[3,4],[2,4],[7,20],[1,4],[2,4],[3,4],[4,7],[1,1],[2,0],[3,0],[-1,-2],[0,-2],[3,-9],[0,-2],[-2,-7],[-2,-12],[-1,-6],[0,-2],[-1,-3],[-1,-3],[-5,-4],[-2,-1],[-2,-2],[-6,-6]],[[3227,7860],[1,0],[1,1],[2,5],[4,-2],[2,-2],[1,1],[1,0],[3,-3],[4,-2],[5,0],[7,1],[1,1],[7,1],[7,0],[2,-1],[1,-1],[1,-1],[-4,-4],[-4,-5],[-6,-4],[-1,-2],[0,-4],[0,-4],[1,0],[1,-2],[-1,-1],[-6,-1],[-2,1],[-2,1],[-1,4],[-2,0],[-1,0],[4,3],[-2,5],[-2,-1],[-1,2],[0,3],[2,1],[0,2],[-2,-2],[-2,-2],[-2,-1],[-2,-2],[3,-1],[-1,-1],[-2,-1],[-8,3],[-2,2],[-3,3],[-2,4],[1,1],[1,0],[0,1],[-3,1],[-5,0],[-2,1],[0,8],[-1,2],[-3,2],[-4,0],[0,3],[1,5],[2,3],[2,4],[2,3],[4,6],[0,-4],[0,-4],[-3,-8],[6,-8],[0,-2],[1,-2],[-1,-2],[0,-1],[2,-1],[0,-2]],[[3280,7907],[1,-1],[2,0],[1,0],[-2,-2],[-3,0],[-2,0],[3,11],[2,3],[6,7],[2,2],[2,1],[2,0],[-2,-5],[-3,0],[-3,-3],[-2,-4],[-2,-2],[-1,-3],[-1,-4]],[[3493,7916],[-1,-2],[-1,0],[0,2],[1,4],[1,2],[0,1],[1,2],[1,1],[1,2],[0,-4],[-3,-8]],[[3208,7942],[-1,-4],[-2,-4],[-2,0],[1,3],[-1,4],[2,0],[1,0],[2,1]],[[3209,7946],[-4,-3],[2,5],[0,1],[1,0],[1,0],[0,-3]],[[1571,7992],[-1,-2],[-1,1],[0,1],[-2,10],[1,0],[2,-4],[0,-1],[1,-3],[1,-2],[-1,0]],[[1573,8000],[-1,-1],[-4,4],[-3,5],[-1,4],[6,-8],[3,-3],[0,-1]],[[2924,7776],[4,2],[9,9],[6,3],[8,9],[5,1],[2,2],[0,8],[1,2],[3,7],[3,6],[2,9],[5,5],[7,5],[7,10],[4,3],[3,2],[2,4],[2,2],[5,5],[7,1],[6,4],[5,2],[3,4],[5,1],[13,11],[3,5],[5,10],[4,5],[2,5],[6,9],[6,11],[3,9],[5,4],[8,13],[5,6],[2,0],[5,5],[4,5],[5,5],[10,6],[9,7],[12,6],[15,9],[11,5],[9,1],[10,2],[3,0],[16,-4],[7,-5],[9,-10],[1,-3],[0,-4],[-4,2],[-4,0],[2,-2],[5,-7],[0,-8],[-3,-7],[-8,-4],[-2,-3],[-1,-4],[-2,-2],[-4,-2],[-2,-3],[-6,-5],[-3,-1],[-3,1],[-8,5],[-5,4],[-2,-2],[-2,-3],[-5,1],[-2,-1],[-3,1],[-7,-5],[2,-1],[5,3],[2,0],[5,-4],[10,-5],[2,-3],[3,-9],[1,-1],[4,0],[4,5],[3,3],[6,2],[-1,-3],[5,0],[4,-4],[-1,-3],[-3,-6],[-1,-12],[-5,-8],[-7,-7],[2,-2],[2,-1],[4,2],[3,0],[3,-2],[-1,-6],[-1,-4],[0,-3],[2,-7],[3,-2],[1,-9],[1,-5],[0,-4],[2,-3],[1,-4],[9,-1],[2,-2],[6,-1],[1,-1],[2,-2],[-7,-5],[5,-4],[5,-6],[4,1],[2,0],[4,-4],[1,-1],[1,-2],[2,0],[3,2],[5,-1],[6,-2],[0,-3],[-1,-2],[4,1],[3,-2],[1,1],[1,1],[5,4],[8,8],[1,-1],[0,-3],[1,-5],[3,-4],[3,0],[5,2],[1,-2],[2,-4],[3,-6],[-1,-2],[-2,-2],[-3,-2],[10,-1],[1,-1],[1,-2],[-1,-3],[-1,-1],[-1,1],[-4,-1],[-3,-3],[-3,-1],[-2,0],[-2,-2],[-2,-2],[-2,0],[-6,-6],[-7,-3],[-7,-5],[-7,-4],[-7,-4],[-2,0],[-2,0],[-4,-4],[-2,1],[-2,-1],[-2,1],[-2,1],[1,-4],[1,-4],[-1,-1],[-1,-2],[-4,0],[-2,2],[-2,2],[-1,3],[-2,2],[-1,-3],[0,-2],[-2,-4],[-2,6],[-3,-2],[-1,-6],[0,-2],[1,-5],[-1,-2],[-2,1],[-2,-7],[-3,-3],[-3,-7],[-4,-5],[-1,-3],[-6,-9],[-3,1],[-1,-1],[-3,-3],[0,-7],[-2,1],[-1,0],[0,-2],[-1,-1],[-3,2],[-2,-1],[-2,2],[-3,10],[-2,3],[-2,1],[-1,-2],[-1,-2],[-2,4],[-2,16],[0,3],[3,13],[6,12],[-2,0],[-6,-8],[1,2],[1,2],[2,3],[3,4],[4,1],[2,1],[2,1],[3,3],[0,2],[-2,-2],[-4,-2],[1,3],[1,1],[21,21],[4,3],[8,4],[2,3],[-2,2],[4,-1],[-1,-3],[0,-2],[0,-2],[0,-3],[3,-2],[3,-5],[-1,7],[2,4],[10,6],[8,0],[2,3],[-6,1],[-8,0],[-6,1],[-6,-1],[-8,1],[-2,-1],[-2,-4],[-2,2],[-1,0],[-1,1],[2,6],[7,9],[5,7],[1,2],[1,3],[-2,-1],[-2,-1],[-2,4],[-3,4],[0,-2],[1,-5],[-5,-10],[-3,-1],[-4,-5],[-7,-4],[-7,-8],[-9,-6],[-2,0],[-5,5],[2,2],[1,4],[-1,-1],[-1,-2],[-3,-2],[2,-4],[-1,-2],[-3,-2],[-2,-4],[-3,-2],[-2,3],[-5,-3],[-5,-1],[-1,1],[0,3],[-2,1],[-3,-1],[-1,1]],[[3135,7785],[-1,1],[-1,1],[-1,0],[-1,-1],[0,-1],[-1,0],[-2,1],[-1,2],[-1,2],[-1,2],[1,2],[0,1],[1,2],[-1,3],[-1,1],[0,2],[0,2],[1,0],[1,1],[0,2],[0,2],[-2,1],[-1,0],[-2,0],[-2,2],[-1,1],[-1,1],[-1,1],[-1,2],[0,2],[1,2],[0,1],[0,1],[0,1],[0,1],[0,1],[0,2],[0,2],[0,5],[0,9],[0,8],[-1,9],[0,7],[0,9],[0,9],[0,9],[-3,5],[-5,6],[-4,4],[-2,0],[-1,0],[-1,-2],[-3,-2],[-5,-1],[-4,-3],[-2,0],[-1,0],[-2,2],[-1,2],[-1,3],[1,5],[-3,2],[-3,1],[-1,-4],[-2,-3],[-3,-6],[-4,-9],[-3,-5],[-4,-9],[-4,-8],[-1,-8],[-1,-7],[-3,-6],[-2,-5],[0,-6],[-1,-5],[0,-5],[0,-2],[0,-2],[-1,-2],[-2,-4],[0,-4],[-2,-2],[-3,-3],[-3,-6],[0,-3],[0,-2],[0,-2],[0,-1],[-2,0],[-1,0],[-1,-2],[0,-3],[-1,-3],[-1,0],[0,1],[-1,3],[-2,0],[-1,-1],[-2,-3],[-2,0],[-4,1],[-2,-5],[-3,-11],[-11,0],[-12,0],[-12,0],[-11,0],[-12,0],[-11,0],[-12,0],[-6,0],[-2,0]],[[1497,8027],[1,-6],[-3,1],[-2,1],[0,3],[1,2],[3,-1]],[[3484,8040],[-4,-3],[-1,-2],[-1,0],[-1,1],[-1,3],[0,1],[1,1],[1,-1],[0,-1],[1,0],[3,3],[2,0],[1,0],[-1,-2]],[[3497,8049],[2,-4],[1,-1],[-7,-4],[-1,0],[0,4],[0,3],[0,1],[2,-2],[2,3],[1,0]],[[1551,8037],[1,-1],[-7,4],[-2,3],[-1,2],[-1,1],[-3,2],[-1,2],[1,1],[2,-1],[4,-2],[3,-3],[4,-8]],[[1482,8041],[-1,0],[-2,0],[-2,2],[-3,5],[-1,0],[1,1],[1,1],[0,1],[-1,3],[3,2],[2,-1],[1,-2],[2,-4],[0,-4],[0,-3],[0,-1]],[[3283,8012],[-12,-1],[-9,3],[-7,2],[-6,3],[-15,10],[-2,4],[-1,4],[-3,4],[-3,3],[-15,10],[-2,3],[4,2],[3,2],[3,-1],[11,-3],[13,-4],[5,-2],[7,-4],[6,-5],[14,-12],[2,-1],[7,-7],[2,-4],[1,-4],[-1,-2],[-2,0]],[[1528,8065],[-1,6],[1,3],[0,1],[0,1],[1,-3],[1,-2],[0,-2],[0,-1],[-2,-3]],[[1523,8069],[-1,-3],[-2,5],[-2,11],[0,2],[1,4],[1,0],[2,-2],[2,-3],[0,-1],[1,-3],[1,-3],[-2,-3],[-1,-4]],[[3457,8105],[-1,0],[-1,0],[-1,0],[0,1],[1,3],[2,1],[2,0],[0,-2],[-1,-2],[-1,-1]],[[1467,8101],[13,-8],[14,-3],[10,-4],[7,-2],[2,-1],[1,-1],[2,-4],[3,-8],[2,-6],[5,-9],[3,-7],[1,-2],[0,-1],[0,-2],[2,-6],[6,-6],[4,-3],[8,-5],[6,-4],[1,-3],[2,-3],[1,-2],[2,-8],[4,-7],[3,-14],[1,1],[0,4],[1,1],[1,1],[0,-2],[1,-4],[2,-8],[0,-3],[-1,0],[-3,1],[-1,-1],[-2,-4],[-1,-1],[0,1],[-9,3],[-6,3],[-7,4],[-9,5],[-5,3],[-4,4],[-3,2],[0,3],[0,1],[5,8],[3,4],[1,3],[0,3],[0,4],[-1,-4],[-1,-3],[-1,-3],[0,-1],[-7,-1],[-5,0],[-3,-3],[-1,-1],[-1,1],[-4,5],[-4,3],[0,1],[3,2],[2,3],[-1,0],[-1,0],[-1,1],[-1,3],[-2,1],[-2,-2],[-1,0],[-1,3],[2,5],[0,1],[-3,-2],[0,1],[-1,2],[-1,0],[-2,0],[-2,2],[-1,-1],[0,-2],[-1,-1],[-3,4],[-2,-3],[-1,0],[0,1],[-1,7],[0,2],[1,1],[3,2],[7,2],[1,1],[-6,-1],[-1,1],[-2,3],[-2,0],[-1,0],[-1,2],[-2,7],[-2,1],[-3,1],[-1,2],[-1,-1],[0,-2],[-1,-1],[-2,-1],[-2,1],[-2,2],[0,2],[-1,2],[1,4],[0,1],[0,1],[-1,2],[-1,1],[0,-1],[0,-2],[-1,-1],[-2,-1],[-1,2],[-1,2],[-1,2],[-6,0],[-2,-2],[-2,0],[-1,0],[0,1],[1,4],[0,5],[-1,1],[-2,1],[-1,1],[2,5],[1,1],[1,1],[5,0],[2,0],[3,-4],[-1,1],[0,4],[-1,3],[2,2],[-2,1],[-6,1],[0,-2],[1,-2],[-4,-3],[-3,0],[-2,0],[-2,2],[-4,5],[-2,5],[0,3],[1,2],[2,2],[3,2],[6,0],[5,-2],[15,-10]],[[3459,8152],[-2,-6],[-1,-2],[-2,-1],[-2,-1],[-6,-1],[-3,-1],[0,-4],[0,-2],[1,-1],[1,-1],[3,1],[1,0],[0,-1],[1,-1],[0,-2],[0,-3],[0,-3],[-2,-7],[-3,-4],[-3,-3],[-1,-2],[0,-1],[-1,-5],[-1,-4],[-6,-9],[-2,-2],[0,-2],[0,-5],[-2,-3],[-4,-9],[-1,-3],[-1,-2],[0,-4],[0,-1],[-1,-3],[-1,-3],[0,-1],[0,-2],[1,-1],[0,-2],[-1,-4],[2,3],[4,7],[3,5],[2,2],[2,2],[1,5],[2,4],[2,1],[1,0],[1,-3],[0,-2],[-1,-4],[0,-1],[2,3],[4,2],[2,-1],[3,-3],[2,1],[4,2],[1,-1],[-1,-3],[-1,-2],[-4,-4],[-9,-7],[-3,-5],[1,0],[2,2],[2,1],[2,0],[1,0],[-1,-2],[0,-3],[-5,-8],[1,0],[6,4],[4,-5],[5,2],[3,1],[0,-1],[1,-2],[0,-3],[2,1],[0,1],[0,6],[2,-1],[0,-1],[0,-4],[0,-5],[-1,-3],[-3,-6],[1,-3],[-1,-2],[1,0],[2,2],[0,1],[0,2],[0,2],[2,2],[3,3],[1,1],[1,-1],[-1,-2],[1,1],[2,2],[2,2],[2,1],[2,2],[2,3],[2,2],[2,2],[1,1],[-1,-4],[1,-4],[0,-3],[0,-1],[2,4],[1,1],[1,1],[1,-1],[9,2],[2,-1],[3,-3],[4,-3],[2,-4],[0,-4],[0,-3],[-3,-3],[-3,-3],[-1,-2],[0,-3],[-1,-1],[-2,-2],[-7,-6],[2,0],[4,1],[3,0],[0,-1],[-1,-1],[-2,-2],[-1,-1],[1,-1],[2,-1],[3,1],[2,-1],[0,-2],[-2,-4],[-1,-3],[-2,-3],[-5,-3],[-2,-2],[1,0],[4,3],[3,0],[1,0],[2,3],[3,1],[2,-2],[4,5],[1,1],[3,-1],[1,1],[3,3],[2,1],[1,-1],[0,-4],[-1,-3],[0,-2],[-2,-4],[-2,-2],[-1,-1],[-2,1],[-1,-1],[-2,-4],[-3,-3],[-3,-2],[2,-1],[0,-4],[0,-1],[-4,-2],[-2,-1],[-3,-1],[2,-1],[4,1],[1,-1],[-1,-2],[-1,-3],[-5,-7],[0,-1],[1,-3],[1,-3],[1,-2],[3,0],[2,1],[2,5],[7,14],[5,4],[5,5],[1,-1],[0,-1],[0,-1],[-2,-4],[-2,-3],[-3,-9],[-1,-5],[0,-4],[0,-9],[0,-1],[1,-2],[2,2],[3,4],[2,4],[2,6],[0,2],[2,0],[0,-1],[1,-3],[1,-4],[0,-4],[0,-5],[-1,-3],[-6,-18],[1,-3],[0,-2],[0,-3],[-3,-8],[-1,-6],[-2,-2],[-1,-2],[-1,0],[-2,0],[-1,3],[-1,1],[-1,0],[-1,-1],[-4,-4],[-1,0],[-1,0],[-1,3],[1,12],[0,3],[-1,4],[1,5],[0,2],[-1,0],[-2,-3],[-2,-4],[-2,-5],[-5,-5],[-1,-1],[-1,0],[-1,1],[-1,2],[0,2],[0,3],[2,7],[3,10],[3,7],[1,3],[-1,2],[-1,2],[-1,8],[-1,6],[-2,3],[-4,3],[-1,-5],[-5,-12],[0,-5],[-1,-2],[-1,-2],[-2,-1],[1,2],[2,7],[-1,0],[-2,-5],[-2,-3],[-3,0],[-2,0],[-1,-1],[-7,-12],[0,-4],[-1,-3],[-3,-6],[-2,-3],[-2,0],[-2,1],[-2,0],[-3,-2],[-4,-1],[-2,1],[-1,0],[-2,3],[0,1],[0,1],[1,3],[3,3],[1,1],[5,2],[3,2],[3,4],[1,2],[5,11],[6,4],[3,3],[2,4],[0,1],[-3,-2],[-2,0],[-2,0],[-1,2],[-4,-1],[-4,1],[-1,-1],[-1,-5],[0,-3],[-1,-1],[-1,-1],[-2,0],[-6,2],[-1,1],[-1,0],[-6,-1],[-1,0],[1,1],[6,4],[0,11],[0,2],[-2,-1],[-2,-2],[-2,0],[-1,1],[-1,0],[-2,-6],[-1,-1],[-2,0],[-4,-3],[-7,-1],[-1,-2],[-5,1],[-15,3],[-5,0],[-6,2],[-1,1],[-9,-1],[-3,1],[0,2],[0,1],[-2,-3],[-3,-1],[-2,-2],[-10,-3],[-4,0],[-3,2],[-1,1],[-2,6],[-1,8],[0,1],[0,3],[2,3],[9,10],[7,9],[3,5],[3,2],[4,4],[0,1],[-4,-1],[-3,1],[-4,1],[-6,-1],[-6,0],[0,2],[3,4],[6,7],[1,0],[-2,-4],[-1,-2],[1,-2],[1,-1],[4,0],[0,1],[2,8],[2,8],[2,6],[2,5],[2,1],[1,-1],[3,-1],[4,-5],[1,0],[1,0],[-2,2],[-1,2],[0,2],[1,5],[2,2],[0,1],[-3,0],[-3,2],[-1,3],[1,4],[0,3],[3,4],[2,2],[2,0],[3,-4],[1,1],[0,1],[-3,6],[0,4],[0,1],[6,19],[2,10],[4,15],[1,3],[2,4],[1,2],[3,0],[1,0],[-2,2],[-1,2],[0,1],[1,1],[1,2],[3,2],[2,4],[1,5],[0,1],[-1,2],[0,1],[2,1],[4,6],[1,1],[1,7],[2,3],[2,2],[3,2],[8,5],[5,5],[4,0],[1,-3],[5,-3],[1,3],[-2,3],[1,1],[4,1],[1,-1],[1,-1],[0,-2]],[[1446,8149],[0,-1],[-1,0],[-2,1],[-1,2],[-2,6],[0,2],[1,1],[2,2],[1,0],[1,-2],[1,-4],[1,-1],[0,-5],[-1,-1]],[[3462,8173],[-1,0],[-1,0],[1,2],[1,3],[2,1],[0,-4],[-2,-2]],[[2795,8176],[-2,0],[-2,0],[-2,2],[-2,1],[9,6],[2,-1],[0,-1],[-2,-3],[0,-2],[0,-1],[-1,-1]],[[1360,8177],[-1,1],[-1,2],[0,5],[0,2],[0,1],[3,-4],[-1,-7]],[[1434,8202],[-2,-1],[1,3],[0,2],[-1,2],[0,3],[0,8],[2,5],[3,0],[0,-2],[-1,-12],[-1,-5],[0,-2],[-1,-1]],[[1418,8208],[-1,-2],[-3,6],[-2,2],[-2,7],[-1,2],[0,2],[1,1],[1,-1],[0,-1],[6,-7],[1,-3],[0,-6]],[[1408,8236],[-1,0],[-1,0],[-1,2],[-2,4],[0,2],[-1,3],[1,0],[1,0],[3,-7],[1,-4]],[[2757,8222],[-2,-1],[-6,2],[-2,1],[-7,4],[-14,6],[-4,3],[-1,2],[2,5],[2,2],[1,1],[14,2],[6,-1],[6,-9],[4,-7],[2,-5],[0,-3],[-1,-2]],[[1340,8248],[3,-6],[1,-4],[-1,-6],[-4,-2],[-2,2],[-1,-1],[-2,-1],[2,-1],[2,-3],[3,-4],[3,0],[4,-3],[-3,-4],[0,-3],[4,-7],[0,-2],[1,0],[3,0],[1,0],[0,-2],[-2,-4],[0,-1],[2,0],[3,0],[1,-4],[-3,-4],[-6,5],[-2,4],[-2,5],[-1,2],[-6,6],[-7,12],[-2,2],[-2,5],[-1,2],[0,2],[1,1],[2,0],[0,2],[-9,5],[-1,1],[-1,2],[1,1],[5,-1],[5,2],[3,1],[1,1],[3,2],[1,0],[3,-2]],[[1429,8233],[1,-18],[0,-6],[-2,-4],[-1,-7],[-2,-2],[-1,3],[0,7],[-1,5],[0,2],[1,10],[-1,-1],[-2,-4],[-2,0],[-3,4],[-2,4],[0,4],[-2,4],[-1,2],[1,2],[1,4],[1,3],[1,5],[1,3],[1,-1],[3,-2],[4,-3],[3,-4],[2,-10]],[[1412,8243],[-3,0],[-1,0],[0,2],[-1,2],[1,2],[2,4],[0,2],[0,1],[1,-3],[1,-2],[0,-8]],[[2779,8254],[0,-2],[-2,1],[-1,1],[0,1],[-1,1],[1,2],[2,-1],[1,-3]],[[1393,8246],[-1,0],[-1,1],[-6,9],[-5,4],[-3,5],[-3,3],[2,5],[2,-1],[5,-4],[5,-4],[2,-2],[6,-11],[-1,-2],[-2,-3]],[[1382,8292],[-1,-2],[-2,-4],[-1,-1],[-1,1],[-1,0],[-2,3],[-2,2],[-1,0],[0,-1],[0,-2],[0,-2],[0,-1],[-1,0],[0,1],[-1,2],[0,2],[0,1],[2,3],[4,4],[1,1],[2,0],[2,-2],[0,-1],[2,-4]],[[1315,8301],[3,-3],[6,2],[1,0],[1,-1],[1,-3],[2,-4],[0,-5],[-1,-2],[-1,-2],[-9,-7],[-1,-1],[1,-1],[2,0],[8,2],[0,1],[1,6],[1,3],[0,2],[-1,6],[0,2],[6,1],[3,2],[4,3],[0,-7],[-1,-2],[-3,-8],[-2,-7],[-1,-8],[0,-12],[-1,-4],[-1,-2],[-9,-5],[-5,1],[-5,4],[-2,2],[2,4],[1,0],[3,-1],[2,-1],[1,0],[0,1],[-6,6],[-5,3],[-2,3],[0,2],[0,2],[-4,8],[-1,4],[0,5],[0,4],[1,8],[0,1],[2,0],[2,-1],[7,-1]],[[1363,8322],[-1,0],[0,1],[0,2],[1,5],[1,1],[3,-1],[1,-1],[0,-2],[-2,-2],[-3,-3]],[[1373,8338],[2,4],[5,7],[3,4]],[[1383,8353],[0,-4],[-4,-8],[-5,-4],[-1,1]],[[3305,8412],[1,-2],[-5,1],[-1,1],[0,1],[0,1],[1,2],[2,1],[1,0],[2,-2],[0,-1],[-1,-2]],[[2810,8418],[-1,-1],[-1,0],[0,2],[1,4],[1,3],[0,3],[1,2],[1,3],[1,1],[1,0],[1,-7],[-1,-4],[-1,-2],[-1,-3],[-2,-1]],[[2778,8421],[-1,0],[-2,1],[1,4],[1,2],[4,1],[1,1],[1,1],[1,0],[2,2],[2,3],[1,0],[-1,-4],[-2,-4],[-8,-7]],[[2807,8425],[-2,-6],[-2,-6],[-3,-10],[-1,-1],[-1,3],[3,12],[1,2],[-1,1],[-1,2],[-1,-3],[-5,-13],[-1,-3],[-1,-1],[-1,0],[-3,0],[-4,-4],[7,17],[1,1],[-2,1],[0,-1],[-6,-10],[-4,-4],[-2,1],[-1,1],[0,1],[6,11],[6,7],[2,5],[1,5],[0,3],[0,3],[1,1],[0,-1],[0,-4],[-1,-8],[-1,-3],[-1,-4],[3,1],[1,4],[2,6],[1,5],[1,8],[0,-2],[1,-1],[2,-1],[1,-1],[0,-2],[1,-2],[2,-1],[1,0],[1,-3],[0,-2],[0,-1],[1,0],[-1,-3]],[[2791,8447],[-1,-1],[-1,0],[1,6],[-1,1],[0,1],[0,1],[1,0],[1,-1],[1,-2],[0,-2],[0,-1],[-1,-1],[0,-1]],[[2781,8454],[-1,-1],[-1,1],[0,3],[1,2],[1,0],[1,-1],[0,-2],[-1,-2]],[[3285,8499],[2,-2],[1,-6],[-5,0],[-5,4],[-1,4],[1,1],[1,-1],[1,1],[2,0],[3,-1]],[[2785,8497],[0,-1],[-1,1],[-1,-4],[0,-1],[-1,3],[1,2],[0,1],[0,1],[1,2],[1,1],[0,-3],[0,-2]],[[3079,8584],[-2,-4],[-2,1],[-1,-1],[-1,0],[1,4],[0,2],[0,3],[1,1],[3,1],[0,-4],[0,-1],[1,0],[0,-2]],[[2770,8618],[-1,0],[-1,1],[1,2],[1,0],[2,3],[1,-1],[-1,-2],[-1,-2],[-1,-1]],[[2776,8627],[-3,-1],[1,4],[1,1],[1,1],[3,1],[1,-2],[-1,-2],[-3,-2]],[[3211,8661],[-1,-4],[-4,1],[-5,3],[-2,2],[0,3],[0,3],[1,0],[4,0],[3,-4],[1,-1],[3,-3]],[[3104,8654],[-2,-1],[-1,1],[0,4],[0,2],[3,6],[3,6],[1,2],[3,-1],[2,-2],[2,-3],[1,-2],[-1,-4],[-2,-3],[-3,-2],[-6,-3]],[[2818,8682],[-4,-1],[0,1],[2,2],[6,2],[4,1],[-1,-2],[-2,-2],[-5,-1]],[[3199,8718],[-1,0],[-1,0],[-2,3],[-2,1],[-1,1],[-9,7],[-1,2],[0,3],[3,1],[6,1],[4,0],[5,-2],[1,-1],[2,-3],[0,-3],[0,-4],[-1,-1],[-2,-2],[-1,-3]],[[2415,8746],[-1,0],[-2,3],[-1,1],[3,1],[3,-2],[-1,-2],[-1,-1]],[[3193,8748],[1,-1],[1,1],[1,-2],[0,-1],[2,-2],[0,-1],[0,-1],[-1,-1],[-1,-1],[-6,4],[-2,4],[0,2],[0,2],[1,1],[2,0],[1,-1],[1,-3]],[[2790,8779],[2,-2],[4,-5],[1,-3],[1,-3],[-1,-5],[-1,-5],[-1,-3],[-3,-4],[-2,-5],[-2,-6],[-1,-4],[-2,-1],[-1,-1],[-1,0],[-3,2],[-3,4],[-2,2],[-3,2],[-2,2],[0,3],[0,7],[0,4],[0,3],[1,3],[2,3],[4,8],[3,3],[1,0],[4,0],[2,0],[2,1],[1,0]],[[3199,8787],[5,-1],[4,1],[1,-1],[1,-3],[-1,-4],[-2,-2],[-3,0],[-5,1],[-2,1],[-2,2],[1,2],[3,0],[0,1],[-1,1],[0,1],[1,1]],[[2944,8791],[-1,-1],[-6,1],[-7,2],[-3,3],[0,1],[1,0],[2,0],[3,-2],[8,-1],[3,-1],[0,-1],[0,-1]],[[3046,8787],[-2,-1],[-4,1],[-4,1],[-2,1],[-2,3],[0,3],[-4,5],[-4,2],[-3,3],[3,0],[3,0],[5,-2],[5,-2],[6,-4],[2,-4],[2,-3],[1,-2],[-1,-1],[-1,0]],[[2722,8810],[1,-2],[0,-2],[0,-3],[-1,-3],[-1,-3],[-2,-5],[-8,-7],[-3,-4],[-2,-3],[-12,-11],[-2,-1],[-1,1],[-4,1],[-3,1],[-9,-5],[-1,1],[0,5],[-1,2],[-4,6],[0,1],[0,2],[0,1],[5,6],[10,19],[2,1],[5,-2],[2,-1],[2,0],[7,4],[7,0],[6,2],[3,0],[3,0],[1,-1]],[[2836,8840],[3,-3],[2,0],[2,-2],[3,-6],[0,-1],[0,-2],[-2,-3],[-1,-1],[-4,-2],[-4,-1],[-3,1],[-6,6],[-6,7],[-2,4],[1,1],[2,2],[6,1],[8,-1],[1,0]],[[2870,8835],[-3,0],[-4,1],[-4,2],[-8,8],[6,6],[10,-6],[3,-4],[0,-7]],[[2843,8870],[-2,-3],[-6,1],[-1,1],[0,1],[1,1],[6,1],[3,0],[1,0],[0,-1],[-2,-1]],[[2641,8943],[1,-1],[1,0],[2,3],[4,8],[2,1],[1,0],[7,-5],[2,-3],[2,-4],[1,-2],[5,-2],[5,-1],[7,-2],[2,-1],[5,-8],[1,-1],[5,-3],[9,-7],[3,-1],[8,-2],[4,-2],[3,-3],[3,-5],[4,-7],[3,-13],[0,-2],[0,-2],[-1,-1],[-5,-5],[0,-1],[5,0],[10,3],[7,-2],[2,0],[1,0],[2,4],[2,-1],[4,-3],[3,-4],[1,-2],[-1,-1],[-2,-1],[6,-2],[5,-3],[-1,-3],[-5,-5],[-6,-4],[-7,-7],[-2,-1],[-1,0],[-3,1],[-6,3],[-16,8],[-5,1],[-7,1],[0,2],[-2,11],[-3,2],[-10,2],[-3,1],[0,3],[1,3],[-2,2],[-3,0],[-3,-1],[-6,-2],[-2,-3],[-1,-2],[-1,-6],[0,-2],[-2,-4],[-8,-8],[-4,-3],[-3,-1],[-1,-1],[-2,-3],[-4,-8],[-1,-2],[-2,-3],[-5,-3],[-4,-3],[-8,-3],[-4,-2],[-3,2],[-2,7],[-4,22],[-1,2],[-1,1],[-1,0],[-14,-3],[-7,1],[-8,-5],[-2,-1],[-3,0],[-3,1],[-1,1],[0,2],[0,2],[1,3],[3,6],[3,4],[1,2],[13,7],[3,2],[2,3],[0,3],[-1,3],[-2,8],[-1,7],[0,4],[1,5],[4,14],[1,6],[2,24],[1,6],[1,7],[2,3],[4,8],[3,3],[4,2],[1,-1],[1,0],[1,-4],[6,-2],[2,-3],[1,-3],[1,-4],[-1,-2],[-3,-3],[0,-1],[0,-1],[5,-4],[4,-10]],[[2648,8961],[-2,-1],[-1,1],[-2,1],[-1,3],[-1,2],[-4,3],[-1,1],[-1,4],[0,4],[-1,3],[0,2],[0,2],[4,1],[2,-1],[1,-1],[1,-1],[0,-2],[3,-5],[2,-4],[3,-7],[0,-2],[-1,-2],[-1,-1]],[[2674,8974],[4,-3],[3,-1],[6,-1],[1,0],[0,-1],[-1,-2],[-2,-2],[-1,0],[-4,1],[-1,1],[-1,2],[-1,0],[-1,-1],[1,-1],[-1,0],[-4,0],[0,1],[0,2],[3,2],[-3,1],[0,1],[-4,-2],[-2,0],[-3,1],[0,6],[-1,2],[-1,2],[-1,2],[-1,1],[-3,1],[-2,3],[-1,1],[1,1],[1,2],[8,-3],[5,-3],[4,-4],[3,-2],[0,-2],[-1,-2],[-1,-1],[1,-2]],[[2691,9002],[3,-1],[2,0],[0,-1],[-2,-3],[-1,0],[-3,2],[-2,2],[0,2],[0,1],[0,1],[3,-3]],[[1997,9043],[4,0],[4,0],[-1,-5],[-1,-2],[-2,-1],[0,1],[-3,4],[-1,3]],[[3259,9046],[-4,-1],[-2,1],[2,1],[1,2],[3,2],[1,2],[4,1],[2,0],[0,-1],[-2,-2],[-5,-5]],[[2003,9066],[-2,-5],[0,1],[-1,2],[-2,1],[-2,3],[0,5],[0,3],[0,3],[2,2],[2,-2],[1,-4],[-1,-3],[2,-2],[1,-2],[0,-2]],[[1967,9099],[4,0],[2,0],[2,-2],[0,-2],[0,-1],[-1,0],[-5,2],[-1,2],[-1,1]],[[2955,9088],[-14,0],[-7,0],[-3,1],[-3,2],[-3,4],[-2,5],[0,2],[1,1],[1,1],[9,2],[7,-2],[6,-2],[9,-1],[2,0],[1,-1],[1,-1],[1,-5],[0,-3],[0,-2],[-6,-1]],[[1963,9100],[-1,0],[-4,3],[1,3],[4,-3],[0,-2],[0,-1]],[[2594,9085],[-1,0],[-2,1],[-4,4],[-1,1],[0,2],[0,2],[0,2],[1,4],[-2,3],[-1,2],[0,1],[2,3],[0,1],[2,3],[3,4],[4,-1],[3,-4],[1,-2],[0,-3],[0,-3],[1,-5],[0,-4],[0,-2],[-2,-4],[-1,-2],[-1,-2],[-2,-1]],[[2898,9119],[14,-5],[2,-2],[0,-2],[1,-1],[0,-4],[-1,-2],[-1,-3],[0,-2],[1,-12],[0,-7],[-1,-5],[-2,-5],[-3,-3],[-3,-2],[-10,-5],[-8,-1],[-8,0],[-10,-2],[-4,1],[-3,0],[-1,1],[-2,3],[-3,5],[-1,6],[-3,10],[0,2],[2,8],[3,5],[5,9],[6,8],[1,1],[3,2],[6,2],[6,-1],[2,1],[3,1],[3,0],[6,-1]],[[2806,9112],[-2,-1],[-4,3],[0,2],[1,4],[6,1],[2,-3],[1,-2],[-4,-4]],[[2096,9124],[-2,0],[-3,1],[-4,2],[-3,2],[-2,2],[0,2],[1,1],[3,0],[5,0],[3,-1],[4,-4],[1,-1],[0,-2],[-1,-1],[-2,-1]],[[2920,9121],[-2,-1],[-4,4],[-6,4],[-3,3],[0,1],[0,2],[1,3],[2,3],[3,1],[3,-1],[3,-2],[3,-6],[1,-3],[1,-2],[-1,-1],[0,-1],[1,-1],[-1,-1],[0,-1],[-1,-1]],[[2171,9134],[-1,0],[-2,1],[-9,4],[-1,1],[1,1],[3,2],[2,2],[2,3],[5,-1],[2,-2],[1,-1],[0,-2],[0,-4],[-2,-1],[-1,-3]],[[2216,9147],[-1,-2],[-1,0],[-2,-3],[-1,0],[-1,2],[-1,2],[-1,0],[-2,-1],[-1,0],[0,1],[0,1],[0,3],[0,5],[0,1],[0,2],[0,1],[1,1],[2,0],[3,0],[2,-2],[1,-2],[2,-2],[1,-1],[-1,-6]],[[2222,9159],[0,-4],[-4,1],[-1,2],[-2,2],[0,1],[0,1],[2,3],[1,1],[2,-1],[1,-2],[1,-2],[0,-2]],[[2486,9171],[-2,-1],[-2,3],[-1,0],[0,2],[-3,0],[0,2],[1,2],[2,1],[2,-1],[2,-2],[1,-2],[0,-3],[0,-1]],[[2799,9149],[-1,0],[-3,1],[-1,2],[0,2],[0,1],[1,1],[2,2],[2,3],[2,2],[6,2],[1,1],[3,6],[1,1],[3,0],[0,1],[-1,1],[0,2],[1,1],[1,1],[4,2],[4,-1],[1,0],[0,-1],[2,-3],[-2,-3],[-4,-3],[-3,-3],[0,-1],[-1,-2],[0,-1],[-4,-4],[-2,-4],[-2,-2],[-5,-2],[-5,-2]],[[2494,9182],[1,-3],[-3,-5],[0,-1],[-1,0],[-1,0],[-3,4],[-1,2],[1,2],[2,1],[2,1],[2,-1],[0,1],[1,-1]],[[2861,9166],[-4,0],[-2,0],[-2,1],[-1,2],[-2,5],[1,2],[0,4],[0,1],[1,1],[4,1],[2,0],[3,-1],[7,-1],[2,-1],[0,-1],[0,-1],[0,-1],[-4,-4],[-2,-2],[-1,-3],[-2,-2]],[[2189,9181],[-2,-1],[0,1],[0,1],[0,1],[-1,1],[2,1],[0,1],[-3,2],[-1,1],[0,1],[2,1],[1,0],[4,-2],[2,-2],[1,-2],[-1,-1],[-1,0],[-1,-2],[-2,-1]],[[2347,9191],[3,-4],[0,-2],[0,-3],[-1,-2],[-2,-2],[-2,-1],[-3,0],[-1,1],[1,3],[0,2],[0,4],[-1,2],[-1,1],[-2,0],[0,-1],[1,-2],[-1,-3],[-1,-4],[-1,-2],[-2,1],[-1,2],[1,2],[-1,2],[1,2],[1,4],[2,2],[2,1],[2,0],[3,-1],[3,-2]],[[1138,9191],[-3,-2],[-3,2],[-1,2],[4,3],[2,-1],[4,-1],[1,-2],[-4,-1]],[[3113,9189],[-1,0],[-7,3],[0,2],[3,2],[3,1],[2,0],[3,0],[2,-3],[-3,-2],[-2,-3]],[[2832,9199],[2,-3],[0,-1],[-2,-2],[-7,-3],[-5,-3],[-2,-1],[-3,1],[-4,-1],[-2,0],[2,2],[6,7],[5,1],[1,1],[2,0],[1,1],[0,1],[1,2],[2,0],[3,-2]],[[2793,9203],[1,-3],[1,-1],[-1,-1],[-4,-4],[-9,-1],[-5,2],[2,-5],[1,-2],[-1,-1],[-2,1],[-3,1],[-2,1],[0,2],[-1,1],[-1,-1],[-1,0],[-2,3],[-1,1],[-9,1],[-1,1],[1,1],[1,2],[2,0],[6,0],[0,2],[1,1],[3,0],[3,0],[1,-1],[1,-2],[2,0],[2,0],[3,1],[4,2],[4,1],[4,-2]],[[2293,9195],[1,-1],[2,1],[1,2],[1,0],[1,0],[4,-3],[3,-4],[3,-3],[5,-2],[11,-7],[3,-5],[3,-8],[3,-6],[3,-4],[3,-3],[5,-3],[4,2],[1,1],[2,-1],[1,-3],[0,-1],[-2,-2],[-3,-1],[-4,-1],[-2,0],[-3,-3],[-3,-3],[-4,-2],[-6,-5],[-4,-2],[-6,-1],[-11,5],[-7,-1],[-6,1],[-6,5],[-5,2],[-10,4],[-1,1],[0,1],[0,2],[-1,1],[0,1],[-2,0],[-1,-1],[-3,-2],[-5,1],[-2,1],[-1,1],[-1,1],[0,2],[-1,1],[-1,1],[-1,0],[-3,-1],[-1,-1],[1,-1],[-1,-1],[-4,0],[-2,1],[-3,2],[-2,3],[-2,4],[0,1],[2,3],[1,2],[10,1],[5,1],[5,3],[7,5],[1,1],[0,1],[0,2],[-2,3],[-1,2],[1,1],[2,0],[-1,1],[-1,1],[-1,1],[0,2],[2,0],[3,0],[4,-5],[2,-1],[3,-1],[-3,4],[-3,6],[-1,3],[0,1],[1,4],[1,1],[1,1],[3,2],[6,2],[2,0],[3,-1],[3,-3],[5,-3],[1,-2],[0,-1],[-2,-1],[-1,-1],[1,-1]],[[2585,9222],[4,0],[3,0],[2,0],[1,-2],[1,-2],[1,-1],[-2,-2],[-5,-1],[-3,1],[-3,1],[-2,0],[-4,1],[-2,1],[-2,2],[0,2],[4,1],[2,1],[5,-2]],[[2213,9244],[-6,2],[-2,1],[-1,1],[-1,2],[0,3],[1,1],[3,0],[3,-1],[4,-3],[-1,-1],[0,-2],[1,-2],[-1,-1]],[[2924,7776],[-1,0],[-3,0],[-4,-2],[-5,-4],[-6,-7],[-11,-16],[0,-2],[-2,-3],[-4,-3],[-4,-3],[-1,-4],[-1,-2],[-6,-9],[-4,-7],[-3,-8],[-3,-9],[-7,0],[-6,0],[-9,0],[-8,0],[-9,0],[-7,0],[-7,0],[-3,-3],[-5,-3],[-4,-4],[2,-7],[1,-3],[-1,-10],[1,-1],[0,-2],[1,-2],[0,-2],[1,-1],[1,-1],[0,-1],[1,-2],[-1,-2],[-3,-4],[-4,-3],[-7,-6],[-9,-6],[-7,-6],[-6,-4],[-12,-4],[-10,-3],[-7,-2],[-6,-6],[-7,-7],[-6,-5],[-7,-7],[-6,-6],[-7,0],[-5,5],[-5,4],[-3,9],[0,9],[1,6],[1,3],[2,2],[4,3],[3,6],[3,4],[3,4],[1,7],[2,16],[1,3],[2,11],[4,12],[1,5],[-2,15],[-1,11],[-1,10],[-1,12],[-1,10],[-1,10],[-1,10],[-2,10],[0,7],[-1,8],[-6,6],[-5,4],[-7,6],[-6,6],[-5,5],[3,10],[0,2],[-1,2],[-3,3],[-1,0],[-3,0],[-4,-2],[-2,0],[-1,4],[-2,4],[-1,4],[0,5],[-1,4],[1,2],[0,1],[0,2],[-1,1],[-1,0],[-4,-2],[-2,0],[-1,-1],[-2,-2],[-1,0],[-3,5],[-3,5],[-2,7],[-1,8],[-5,5],[-6,4],[-5,5],[-5,5],[-6,4],[-5,5],[-6,4],[-5,5],[-2,2],[-5,4],[-7,5],[-8,7],[-8,6],[-7,6],[-4,4],[-2,2],[-5,4],[-6,4],[-7,-2],[-8,-7],[-4,-3],[-4,-3],[-2,-1],[-5,-2],[-3,1],[-6,0],[-3,-1],[-3,1],[-1,4],[-2,2],[-6,-1],[-8,1],[-4,0],[-1,1],[-2,4],[-2,1],[-3,-1],[-5,-5],[-5,-3],[-3,0],[-4,3],[-6,5],[-4,6],[-5,2],[-3,-1],[-1,-3],[-2,0],[-2,6],[-1,4],[-2,1],[-4,4],[-3,2],[-4,3],[-2,0],[-3,1],[-3,0],[-3,-1],[-2,-3],[-3,-2],[-4,0],[-3,1],[-1,4],[-6,2],[-10,3],[-6,2],[-1,2],[-1,2],[0,3],[-3,8],[-1,7],[0,8],[0,3],[-1,0],[-1,2],[-6,1],[-1,-9],[0,-12],[-6,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-3,0]],[[1589,8006],[-1,2],[-3,2],[-1,0],[-1,0],[-1,-2],[0,-2],[-1,-1],[0,1],[-1,3],[0,2],[1,2],[0,1],[-2,-1],[-1,1],[0,1],[0,4],[-1,2],[1,1],[3,1],[4,0],[1,2],[1,4],[-3,-4],[-1,0],[-5,1],[-3,0],[0,1],[0,1],[1,1],[0,3],[1,8],[1,3],[0,2],[-4,-6],[0,-1],[0,-2],[0,-3],[-2,-1],[-1,0],[-2,-3],[-1,0],[-9,5],[-1,1],[-1,2],[-2,4],[-1,3],[1,3],[1,2],[1,0],[1,-2],[2,-4],[0,-3],[3,0],[3,4],[1,1],[-3,-1],[-2,0],[-2,2],[-1,3],[-1,3],[0,11],[1,2],[1,1],[1,3],[0,1],[-1,2],[-1,2],[-2,1],[0,-1],[2,-4],[0,-2],[-2,-5],[-1,-1],[0,-4],[0,-1],[-2,-2],[-3,-3],[-3,-1],[-4,0],[-2,2],[-6,8],[-2,4],[0,3],[-5,11],[0,2],[-1,3],[-2,1],[0,3],[3,7],[2,5],[1,2],[0,3],[-1,6],[1,3],[-3,-4],[0,-2],[1,-3],[-1,-3],[-1,-4],[-2,-5],[-4,-2],[-8,1],[0,1],[-1,1],[0,7],[-1,-1],[-1,-3],[0,-5],[-1,-1],[-2,-1],[-1,1],[-1,2],[-2,0],[-3,-1],[-2,0],[-2,0],[-4,2],[-4,0],[-2,1],[0,3],[1,1],[5,1],[5,2],[5,1],[0,1],[-3,1],[-10,-3],[-4,0],[0,1],[-1,2],[2,3],[2,2],[0,2],[-1,1],[-2,-1],[-1,2],[1,5],[-1,6],[-1,-6],[-2,-3],[-9,-1],[-1,-1],[-2,0],[-5,2],[-3,2],[-2,3],[-4,5],[-4,4],[0,7],[1,4],[2,5],[5,10],[2,2],[2,1],[9,1],[6,1],[2,1],[-10,1],[-8,-1],[-3,-2],[-4,-6],[-1,-3],[-1,-2],[-2,1],[-1,3],[-2,3],[-1,4],[0,6],[0,3],[1,3],[3,7],[-4,-1],[1,6],[1,6],[3,3],[4,3],[3,3],[5,3],[2,-5],[5,-1],[1,-2],[2,-4],[2,-4],[2,-3],[1,-1],[-1,3],[-4,7],[0,2],[-1,3],[-5,3],[-1,2],[-1,3],[-1,3],[1,2],[5,7],[1,3],[0,2],[0,2],[-1,3],[0,-5],[0,-2],[-1,-2],[-1,-1],[-1,-2],[-11,-15],[-1,-1],[-5,-2],[-2,-1],[-1,-3],[-2,-5],[-3,-12],[-3,-9],[-2,12],[-5,9],[9,9],[0,2],[0,5],[0,1],[1,2],[2,3],[0,1],[-3,-1],[-4,-8],[-1,-2],[-1,0],[0,4],[2,11],[2,10],[0,3],[2,3],[-2,0],[-7,-5],[-2,3],[-2,16],[-4,6],[-6,4],[-6,3],[-1,4],[-1,5],[1,6],[3,3],[2,2],[3,-1],[0,-2],[-2,-6],[2,-1],[8,-7],[2,-1],[3,3],[2,0],[5,-2],[1,-3],[4,-6],[0,4],[-5,6],[-2,2],[-5,1],[-3,-1],[-1,0],[-2,2],[-2,2],[-3,7],[0,2],[0,3],[1,1],[0,2],[2,1],[3,1],[1,1],[-4,3],[-1,0],[-5,-5],[-1,0],[-1,1],[-2,-3],[-1,-1],[-4,-8],[-1,-3],[0,-6],[-1,-3],[0,-2],[-5,-3],[-3,-5],[-4,5],[-3,4],[-3,8],[-4,2],[-6,4],[-2,4],[3,8],[4,7],[1,7],[1,2],[7,2],[4,3],[-5,1],[-2,-1],[-6,-2],[-5,5],[-3,4],[-1,4],[1,4],[0,3],[0,5],[1,2],[1,2],[3,2],[2,6],[1,3],[4,11],[2,5],[3,7],[6,10],[-2,0],[-1,-1],[-1,0],[-1,1],[-1,2],[-1,4],[0,-2],[0,-6],[-1,-6],[-1,-4],[-3,-8],[-2,-3],[-1,3],[1,5],[2,4],[0,5],[-1,7],[-1,5],[-1,4],[0,4],[0,3],[1,4],[1,3],[0,1]],[[1388,8403],[0,3],[0,4],[-1,3],[-1,3],[-3,-2],[-6,2],[-1,7],[-5,1],[-3,5],[-5,2],[-4,2],[-4,2],[-3,3],[-4,3],[-3,3],[-2,0],[-5,-1],[0,6],[-2,3],[1,3],[-3,1],[-4,3],[1,5],[1,4],[-3,2],[-5,1],[1,4],[2,3],[-2,5],[-4,7],[-3,6],[-4,8],[-3,7],[-3,6],[-3,5],[-3,7],[-4,8],[-4,7],[0,4],[-4,6],[-3,5],[-4,6],[-4,3],[-3,2],[-4,3],[-3,3],[-1,3],[0,1],[-1,3],[-1,2],[-1,2],[-5,4],[-1,3],[-4,3],[-3,1],[-1,1],[-3,9],[0,3],[1,3],[-1,1],[-5,7],[-3,3],[-3,3],[-7,-4],[-6,-4],[-5,-1],[-6,-2],[2,-4],[-1,-3],[-2,-2],[-3,1],[0,-11],[-3,-7],[-6,0],[-4,-3],[-5,-4],[-4,-3],[-5,-4],[-2,0],[1,5],[-2,7],[-1,6],[-3,3],[-5,6],[-3,4],[-6,5],[-3,4],[-4,4],[-5,6],[-2,7],[-5,3],[-4,2],[-4,6],[1,5],[2,6],[0,4],[-5,-1],[-6,0],[-6,0],[-4,-5],[-4,-4],[-6,3],[-8,4],[-2,-5],[-6,3],[-7,2],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17]],[[1083,9196],[4,-1],[13,-2],[12,1],[22,-6],[13,-12],[11,-5],[5,-4],[7,-4],[17,-7],[5,-1],[10,-3],[6,0],[11,-1],[7,-3],[14,-7],[3,-1],[-4,8],[-1,1],[-6,3],[-6,1],[-1,1],[-1,3],[0,1],[2,0],[5,0],[2,1],[1,1],[-2,0],[-3,1],[-3,2],[-1,2],[6,11],[2,-1],[3,3],[6,-2],[1,1],[0,6],[1,1],[2,1],[8,1],[10,-1],[1,1],[-1,3],[0,2],[0,4],[1,1],[1,1],[5,0],[1,-2],[2,-3],[2,-2],[4,-1],[1,-2],[-2,-4],[-2,-3],[-4,-6],[0,-1],[6,2],[7,4],[6,2],[5,1],[4,1],[2,2],[2,2],[3,7],[2,2],[9,-1],[2,0],[1,1],[0,1],[-2,1],[-3,0],[0,1],[1,1],[2,1],[4,0],[3,-2],[2,0],[6,2],[10,8],[4,2],[3,0],[3,-1],[2,0],[3,5],[1,2],[2,2],[7,4],[5,1],[3,-1],[3,-2],[3,0],[4,0],[2,0],[2,1],[4,5],[2,0],[1,-2],[3,-3],[0,-2],[-3,-4],[-23,-13],[-7,-5],[-3,-2],[-4,-2],[-7,0],[-3,-2],[-4,-1],[-11,-1],[-2,-1],[-1,-1],[-4,-7],[-2,-2],[-4,-3],[-4,-2],[-6,-1],[-4,-3],[-4,-6],[-3,-4],[-4,-4],[-4,-4],[-1,-3],[1,-3],[1,-1],[4,-2],[2,0],[-2,2],[-3,3],[-1,1],[1,0],[17,-2],[3,2],[1,2],[0,1],[-4,0],[-1,2],[-1,3],[0,2],[0,1],[1,3],[5,3],[5,2],[4,2],[2,2],[6,3],[3,2],[1,2],[0,1],[-1,1],[1,2],[4,2],[2,0],[6,-2],[2,-1],[-1,-3],[1,0],[2,4],[1,1],[2,1],[1,-1],[2,-1],[0,-4],[0,-6],[1,-3],[1,4],[1,3],[6,9],[4,5],[5,5],[6,4],[16,6],[8,1],[4,2],[3,1],[1,2],[2,2],[1,0],[-1,-4],[-1,-2],[-5,-2],[-1,-2],[1,-3],[1,-2],[1,-1],[2,1],[4,2],[4,4],[9,8],[0,2],[3,7],[5,3],[9,3],[2,3],[-8,2],[-2,1],[0,1],[2,2],[-4,2],[-1,1],[0,3],[1,3],[2,2],[2,1],[3,-2],[3,-2],[11,-8],[4,-4],[2,-4],[6,-10],[3,-6],[2,-6],[2,-4],[2,-3],[10,-11],[5,-4],[4,-3],[5,-2],[6,-2],[4,0],[6,5],[0,3],[-3,5],[-2,3],[0,2],[4,4],[-1,2],[1,4],[2,-1],[1,0],[2,2],[2,3],[2,2],[2,2],[1,1],[-3,1],[-1,0],[-1,0],[-1,1],[1,1],[6,2],[1,2],[2,2],[2,0],[1,0],[2,-2],[0,-3],[-1,-4],[0,-4],[2,-9],[2,-2],[6,-2],[0,-2],[-8,-9],[-1,-3],[-1,-1],[0,-2],[2,-1],[2,-1],[6,0],[2,1],[12,0],[3,1],[1,1],[3,5],[3,1],[1,1],[2,6],[1,6],[1,2],[1,2],[2,0],[5,0],[2,0],[9,0],[9,0],[9,-1],[6,-1],[5,-2],[11,-5],[4,-2],[14,-12],[5,-2],[8,-2],[27,-5],[3,-1],[8,-6],[5,-3],[5,-2],[8,-3],[14,-4],[3,-1],[2,0],[3,0],[13,-2],[4,0],[2,0],[3,-2],[5,0],[0,1],[-5,6],[0,1],[2,0],[6,-1],[2,1],[2,0],[5,0],[5,-2],[6,-3],[7,-3],[10,-6],[6,-5],[5,-6],[3,-4],[1,-2],[1,-2],[1,0],[1,-1],[-1,-5],[-1,-1],[-2,-1],[-4,-1],[-14,1],[-3,-4],[-7,-4],[-2,-1],[0,-2],[1,-3],[-1,-2],[-6,-4],[-1,-1],[4,-2],[5,-3],[3,-1],[4,1],[6,-1],[6,-3],[5,-1],[2,0],[4,0],[4,-1],[6,-1],[13,0],[4,-1],[5,0],[11,0],[2,0],[3,2],[2,1],[4,0],[11,2],[3,-1],[4,2],[4,2],[3,0],[1,-1],[2,-1],[3,0],[5,3],[12,7],[4,0],[3,2],[1,0],[1,-1],[3,-5],[1,-1],[2,0],[2,-3],[2,-4],[2,-1],[11,0],[4,-1],[1,-1],[1,-3],[1,-6],[0,-3],[2,-3],[1,-1],[1,1],[3,8],[1,2],[2,-1],[3,-6],[4,-5],[10,-8],[2,-3],[0,-3],[0,-2],[-2,-2],[-3,-1],[-3,-1],[-4,0],[-3,2],[-1,0],[1,-1],[7,-7],[1,-3],[2,-2],[1,-1],[2,-2],[1,-2],[5,-5],[2,-3],[6,-8],[3,-4],[2,-2],[1,0],[0,2],[-8,11],[-4,7],[-1,2],[0,2],[0,9],[0,1],[3,1],[4,-4],[1,0],[1,0],[0,1],[2,-1],[4,-3],[1,0],[-2,6],[-2,2],[-1,2],[2,3],[-1,1],[-5,4],[-2,5],[-2,6],[0,3],[0,2],[0,2],[-3,5],[-3,3],[-3,3],[0,2],[0,5],[2,2],[3,3],[1,3],[-1,3],[-1,2],[1,-1],[7,2],[2,-1],[3,1],[3,2],[3,1],[4,0],[2,0],[2,1],[1,1],[3,3],[1,1],[3,0],[3,-1],[1,0],[-1,5],[1,2],[4,4],[4,0],[2,1],[3,2],[2,2],[2,3],[1,4],[0,1],[-5,1],[-2,-1],[-6,-2],[-6,-4],[-3,-3],[0,-4],[-2,-2],[-4,2],[-2,0],[-3,-1],[-3,-2],[-2,-2],[-5,0],[-5,1],[-4,1],[-3,-3],[0,-2],[2,-3],[-2,-2],[-8,0],[-2,0],[-4,-1],[-2,0],[-1,2],[-9,5],[-1,2],[2,4],[8,13],[1,1],[15,2],[9,2],[17,7],[4,1],[10,4],[5,1],[4,0],[6,-3],[3,-2],[2,-2],[2,-4],[2,-8],[1,-7],[2,-3],[5,-4],[2,-2],[2,-1],[1,1],[1,0],[1,0],[1,-3],[4,0],[3,-1],[0,-1],[0,-4],[0,-2],[4,-3],[4,-1],[5,-1],[8,1],[6,1],[6,3],[4,-3],[8,-7],[5,-5],[4,-2],[9,-3],[2,-2],[3,0],[4,1],[5,0],[5,-2],[4,-1],[13,4],[1,0],[5,2],[3,0],[4,0],[3,1],[1,1],[7,0],[12,-1],[9,-2],[5,-2],[4,-1],[3,-1],[3,1],[3,1],[3,2],[7,1],[1,0],[0,1],[-1,2],[-4,3],[-3,4],[-1,2],[1,2],[0,1],[2,1],[3,-2],[3,-3],[10,-13],[2,-2],[1,-1],[9,-5],[5,-1],[5,3],[2,2],[1,2],[0,1],[0,3],[0,1],[-1,2],[-4,3],[-6,3],[-5,1],[-5,-1],[-6,-3],[-2,1],[-7,8],[-1,3],[0,1],[3,-1],[0,1],[-2,4],[-1,1],[-4,7],[-1,1],[3,1],[1,1],[2,0],[6,-4],[4,1],[8,3],[-3,3],[-1,4],[1,1],[2,0],[6,-3],[2,0],[2,1],[2,0],[2,-1],[2,-1],[4,-5],[1,-2],[2,-4],[1,-1],[10,0],[5,3],[0,-1],[-1,-3],[-7,-10],[0,-1],[4,0],[1,1],[1,1],[1,3],[1,1],[10,5],[3,1],[-2,-5],[-4,-19],[0,-7],[-1,-2],[-4,-7],[0,-3],[4,-6],[1,-1],[0,-5],[1,-1],[4,-1],[3,2],[5,1],[1,-1],[-3,-6],[4,1],[2,0],[1,0],[3,-3],[1,-2],[0,-4],[-1,-2],[-1,-2],[-1,0],[-2,-1],[-1,0],[-4,0],[-3,1],[-3,2],[-1,0],[-3,-1],[-3,0],[-4,4],[-1,0],[-1,-1],[0,-1],[2,-3],[13,-14],[2,-3],[1,-4],[1,4],[-1,2],[-6,8],[-1,3],[0,1],[2,1],[10,-2],[3,1],[3,1],[1,2],[1,10],[2,6],[-1,6],[-3,9],[-2,5],[-5,5],[0,2],[5,17],[1,1],[1,1],[4,0],[3,1],[5,-2],[3,0],[3,2],[7,6],[3,3],[4,4],[4,5],[5,5],[7,4],[5,3],[1,1],[-4,0],[-1,1],[-1,3],[0,6],[0,3],[0,3],[-1,2],[-2,2],[-1,2],[-1,0],[-1,0],[0,-1],[-2,-5],[-1,-4],[-2,-2],[-4,-2],[-8,-1],[-3,2],[0,2],[1,6],[2,3],[7,5],[4,4],[0,1],[-4,0],[0,1],[-1,5],[0,2],[1,2],[2,2],[9,2],[6,2],[0,-1],[-5,-7],[0,-1],[2,-2],[5,4],[3,4],[0,1],[-2,0],[-1,2],[1,2],[0,2],[-4,2],[-4,-1],[-3,-3],[-3,0],[-4,0],[-3,0],[-2,1],[-2,3],[-3,4],[-3,4],[-1,0],[-1,-1],[-2,-3],[-1,-1],[-13,6],[-6,2],[-2,3],[-4,1],[-4,0],[-3,1],[-2,2],[-2,2],[-2,3],[-2,4],[-7,8],[-1,5],[0,2],[0,5],[6,8],[1,2],[2,2],[3,1],[2,0],[4,-1],[-2,3],[-1,1],[3,5],[-8,-4],[-2,1],[-3,2],[-5,7],[0,5],[1,6],[1,4],[-1,4],[0,1],[2,0],[0,1],[0,4],[1,2],[4,4],[3,3],[2,1],[2,0],[2,-1],[2,-2],[4,-2],[2,0],[2,1],[3,7],[2,2],[-1,0],[-7,0],[-3,1],[-1,1],[-1,2],[1,2],[6,5],[3,5],[8,7],[9,4],[4,1],[4,0],[1,0],[2,-4],[0,-4],[5,-5],[4,0],[2,1],[8,-1],[2,-1],[0,-1],[-1,-3],[0,-2],[5,-4],[5,-3],[4,-3],[7,-7],[1,-2],[1,-3],[1,-8],[1,-3],[-1,-9],[0,-1],[-2,-2],[1,-1],[4,-2],[4,-5],[2,-1],[5,-3],[1,-1],[1,-1],[3,-7],[5,-6],[0,-1],[-1,-3],[1,-1],[2,-1],[1,1],[2,2],[1,0],[2,-1],[1,-1],[2,-4],[2,-3],[0,-1],[-1,-1],[-7,-1],[-4,1],[-3,1],[-3,2],[-2,3],[-1,-1],[-1,-2],[-2,-3],[-2,-2],[2,-2],[9,1],[2,-1],[2,-2],[-3,-3],[-6,-6],[-13,-10],[-3,-2],[0,-1],[2,0],[4,0],[4,1],[6,0],[2,-1],[-1,-1],[1,-2],[9,-4],[5,1],[5,4],[4,1],[5,0],[2,0],[-1,-1],[-3,-2],[-4,-3],[0,-1],[4,1],[9,-1],[5,-1],[3,1],[3,-1],[3,-2],[1,-1],[-3,0],[-2,0],[-2,-1],[-2,-2],[-1,-3],[-1,-3],[-2,-2],[-3,1],[-1,1],[0,1],[-1,0],[-2,0],[-2,-1],[-1,0],[14,-11],[4,-9],[3,-4],[1,-1],[-2,-2],[0,-2],[1,-6],[-1,-4],[-1,-8],[1,-3],[3,-2],[2,-3],[1,0],[1,-3],[1,-1],[1,-1],[1,1],[0,2],[2,2],[3,3],[3,6],[0,2],[0,4],[0,2],[3,6],[1,4],[1,7],[1,5],[3,4],[6,8],[2,2],[2,1],[4,-1],[3,-2],[4,-5],[5,-5],[9,-6],[2,-2],[5,-6],[2,-6],[2,-8],[1,-5],[1,-2],[1,-2],[-1,-4],[0,-2],[-1,-2],[-1,-1],[-2,-1],[-4,1],[-1,1],[-2,4],[-3,-3],[-1,-2],[1,-5],[0,-10],[1,-2],[3,-11],[5,-8],[14,-16],[1,-1],[1,-7],[1,-1],[1,-1],[1,0],[2,0],[5,5],[4,5],[3,3],[2,0],[2,1],[2,2],[1,2],[1,2],[1,7],[1,4],[2,5],[1,1],[10,13],[1,2],[5,14],[1,7],[1,4],[-1,4],[0,3],[1,2],[2,2],[2,1],[1,3],[1,0],[2,0],[2,-2],[2,0],[11,2],[0,1],[-6,3],[0,2],[0,2],[2,2],[3,1],[1,1],[0,2],[0,3],[0,1],[-7,5],[-3,-1],[-1,1],[-3,3],[-1,5],[0,2],[0,4],[0,1],[0,1],[-1,2],[0,2],[1,2],[0,2],[-2,2],[0,2],[1,5],[0,2],[-1,2],[-1,1],[1,1],[2,0],[3,-1],[4,-2],[4,0],[5,2],[5,1],[10,0],[2,-1],[9,-5],[7,-3],[3,1],[15,-1],[7,0],[4,0],[7,-3],[-1,-2],[-3,-4],[-4,-1],[-3,-1],[3,-3],[9,-2],[3,-5],[0,-2],[-1,-2],[1,-1],[2,0],[5,2],[6,-1],[9,-3],[1,-1],[2,-3],[0,-1],[-8,-7],[-4,-2],[-6,-3],[0,-2],[8,0],[6,-1],[2,-1],[2,-1],[1,-3],[1,-2],[0,-3],[-1,-2],[-7,-5],[-3,-2],[-5,-2],[-3,-2],[-2,0],[-3,2],[-3,1],[-5,-2],[-3,0],[-1,-1],[0,-1],[2,-3],[1,-2],[1,-1],[-1,-2],[1,-1],[5,-8],[1,-1],[1,1],[2,2],[1,1],[1,0],[0,-2],[-3,-7],[0,-1],[0,-2],[1,-4],[3,-3],[3,-4],[4,-4],[6,-5],[2,-3],[4,-5],[0,-3],[-1,-6],[-2,-9],[-2,-6],[0,-1],[-5,-4],[-2,-1],[-5,0],[-1,-1],[-2,-3],[-3,-5],[-3,-4],[-1,-1],[-3,-2],[-5,-5],[-3,-2],[-8,-2],[-7,-7],[-3,-2],[-3,-1],[-3,0],[-2,1],[-1,4],[-1,1],[-2,3],[-5,8],[-3,3],[-1,1],[-3,-1],[-1,1],[-4,2],[-1,2],[0,1],[3,1],[-1,1],[-5,4],[-1,2],[-1,0],[-4,3],[-4,1],[-5,-5],[-3,-2],[1,-1],[2,-1],[1,0],[2,3],[2,0],[3,0],[3,-2],[1,-1],[0,-1],[8,-9],[2,-1],[1,-2],[1,-4],[2,-3],[3,-6],[4,-8],[1,-3],[-2,-1],[-1,-1],[-3,2],[-8,3],[-1,0],[-2,-2],[-1,-4],[-1,0],[-4,1],[-8,4],[-5,3],[-3,3],[-3,4],[-4,5],[-4,2],[-5,-2],[-8,-1],[-16,1],[-2,-1],[-1,0],[2,-3],[-1,-1],[-1,-1],[0,-1],[2,-3],[3,-2],[7,-3],[6,-3],[3,-2],[1,-2],[0,-2],[-1,-4],[-1,-1],[-19,-21],[-7,-8],[-3,-5],[-3,-3],[-3,-2],[-4,-1],[-7,0],[-8,1],[-4,2],[-8,7],[-5,5],[-2,1],[-2,4],[-2,1],[-4,0],[-4,2],[-9,7],[-5,3],[-4,2],[-4,0],[-2,-1],[3,-3],[-1,0],[-3,1],[-3,0],[-6,2],[-6,0],[-3,0],[-5,2],[-5,0],[-9,0],[-2,0],[-1,-1],[4,-3],[7,-4],[-1,4],[0,1],[2,1],[11,-2],[12,-4],[3,-1],[4,-1],[4,-3],[5,-5],[10,-12],[3,-3],[4,-2],[22,-4],[7,0],[15,-1],[8,-2],[2,-2],[1,-5],[-1,-3],[-4,-8],[-3,-5],[-17,-25],[-2,-5],[-1,-4],[-3,-3],[-7,-6],[-8,-4],[-4,-1],[-4,1],[-3,1],[-4,5],[0,-1],[3,-7],[-1,-1],[-2,1],[-6,3],[-1,0],[-1,-1],[-2,0],[-2,1],[-3,3],[-1,1],[0,4],[-1,0],[-6,-2],[-1,-1],[2,-1],[1,-1],[3,-6],[0,-1],[-2,-1],[-6,2],[-1,0],[3,-6],[1,-3],[0,-1],[-4,-7],[-2,-3],[-3,-1],[-3,1],[-2,2],[-2,0],[-1,-3],[-2,-1],[-3,-1],[-4,0],[-4,2],[-12,6],[-4,1],[-7,1],[-1,1],[0,1],[1,1],[-1,1],[-2,-1],[-1,-1],[-3,-1],[-4,1],[-6,2],[-12,7],[-13,5],[-7,7],[3,-7],[0,-2],[-2,-1],[0,-2],[3,-5],[4,-1],[4,0],[0,1],[-2,1],[-1,1],[-1,3],[1,0],[3,-1],[3,-2],[18,-8],[5,-1],[4,-2],[1,-1],[-1,-2],[-8,-5],[0,-1],[5,1],[6,4],[3,2],[4,2],[4,-3],[5,-5],[5,-3],[6,-2],[4,-2],[6,-5],[1,-3],[1,-11],[-1,-3],[0,-2],[-2,-3],[-2,-2],[-4,0],[-3,-1],[-7,-6],[-2,-1],[-12,2],[-5,2],[-2,0],[-1,-2],[-1,0],[-5,-1],[-1,-1],[1,-2],[1,-2],[1,-1],[1,-2],[3,-1],[5,-1],[1,-3],[0,-1],[-2,-2],[-2,0],[-4,3],[-1,0],[-2,-2],[-2,0],[-3,0],[-1,-1],[0,-2],[-1,-2],[-3,-3],[-2,-2],[0,-2],[2,-1],[2,-3],[2,-4],[1,-2],[-2,0],[-2,2],[-2,3],[-4,3],[-8,3],[-1,0],[0,-1],[6,-4],[2,-2],[0,-2],[-4,-3],[-1,-2],[2,-1],[0,-1],[-2,-2],[-2,-1],[-5,0],[-1,-1],[2,-2],[1,-1],[-2,-2],[-1,0],[-6,1],[2,-4],[1,-2],[1,-2],[4,-2],[0,-1],[-1,-1],[-2,-2],[-8,-6],[-6,-7],[-1,-2],[2,-5],[0,-1],[-2,-2],[-3,1],[-1,-1],[1,-2],[0,-4],[0,-4],[-3,-6],[-4,-9],[-3,-8],[-2,-7],[-2,-4],[-3,0],[-3,-3],[2,-1],[1,-1],[1,-2],[-1,-7],[-2,-11],[-1,-9],[0,-27],[0,-12],[-1,-7],[-2,-4],[-2,-1],[3,-1],[2,-2],[1,-2],[1,-4],[1,-2],[1,0],[2,0],[1,-2],[3,-6],[4,-1],[0,-4],[-2,-18],[0,-2],[2,4],[2,15],[2,6],[2,1],[8,1],[8,-2],[3,0],[3,1],[2,-2],[1,-1],[1,-8],[1,-4],[5,-16],[2,-8],[3,-13],[1,-4],[6,-18],[1,-5],[0,-4],[0,-2],[-1,-4],[-2,-6],[-2,-4],[-2,-3],[-1,-2],[-2,-1],[0,-1],[2,1],[2,2],[4,3],[2,1],[4,1],[0,-2],[-2,-3],[3,2],[7,4],[25,10],[6,1],[8,-2],[7,-5],[8,-5],[8,-4],[12,-4],[4,-2],[7,-2],[3,-2],[4,-5],[7,-7],[5,-4],[5,-4],[6,-7],[9,-16],[2,-2],[5,-3],[10,-4],[15,-8],[7,-3],[4,-1],[5,-2],[4,-4],[3,-3],[2,-4],[2,-2],[4,-3],[2,-2],[0,-3],[-4,-12],[-1,-1],[5,9],[2,2],[2,1],[4,0],[6,-1],[5,0],[5,1],[3,1],[3,-1],[3,1],[1,1],[2,0],[7,-3],[2,0],[10,-3],[7,1],[1,0],[2,-4],[2,0],[3,0],[3,-1],[5,-4],[2,-4],[3,-9],[0,-2],[-4,-19],[-2,-7],[0,-7],[1,-3],[4,-7],[0,-1],[2,-9],[1,-4],[0,-5],[-1,-7],[0,-6],[1,-8],[0,-6],[-2,-3],[-1,-3],[-1,-6],[0,-2],[1,-4],[1,-2],[3,-3],[2,-3],[5,-10],[3,-5],[4,-7],[1,-4],[-1,-2],[-2,-2],[-3,-2],[-1,-2],[0,-1],[5,2],[2,0],[3,-2],[2,-4],[3,-3],[4,-2],[5,-5],[7,-10],[1,-2],[2,-5],[3,-8],[1,-6],[0,-2],[-1,-3],[-5,-4],[-5,-8],[1,0],[4,3],[5,7],[3,1],[3,0],[5,-2],[4,-3],[3,-4],[5,-9],[6,-8],[3,-6],[-1,4],[-2,5],[-5,7],[-3,4],[0,2],[0,2],[0,4],[1,5],[1,4],[2,2],[1,3],[1,2],[0,2],[5,4],[1,-1],[1,-4],[1,-1],[2,0],[2,-2],[1,-2],[1,-2],[1,-2],[1,-8],[1,-3],[0,4],[1,6],[1,3],[3,4],[0,2],[-2,2],[-5,10],[0,2],[1,1],[1,3],[1,4],[1,3],[4,4],[3,6],[1,4],[1,2],[2,1],[-2,2],[-1,1],[0,5],[0,5],[-2,3],[-3,5],[-1,2],[0,6],[0,3],[1,2],[0,3],[-4,4],[-1,4],[-1,9],[-1,12],[-2,9],[-2,5],[0,4],[1,1],[1,5],[1,1],[2,-1],[0,1],[-3,2],[-1,3],[0,1],[2,3],[0,1],[-2,2],[-4,3],[1,1],[1,2],[0,1],[-2,1],[-2,2],[-2,2],[-2,5],[-1,3],[-1,5],[-2,7],[-1,1],[-1,1],[-2,1],[0,1],[2,1],[21,11],[2,1],[10,6],[5,4],[4,4],[7,5],[3,3],[2,4],[11,12],[4,6],[3,5],[4,7],[4,7],[4,6],[1,6],[1,9],[1,8],[0,12],[0,11],[-1,16],[-1,6],[-2,6],[-3,12],[-1,4],[-2,6],[-8,15],[-9,10],[-2,2],[-3,3],[-6,4],[-3,2],[-10,11],[-3,1],[-1,3],[0,2],[0,5],[1,3],[0,3],[1,1],[5,8],[3,6],[2,4],[2,2],[4,4],[3,4],[-1,2],[-2,2],[0,2],[3,4],[0,2],[0,4],[1,1],[3,0],[6,-6],[1,0],[-2,2],[-2,5],[1,1],[4,5],[0,2],[-1,3],[-1,2],[3,6],[-1,1],[-6,1],[-1,2],[0,1],[3,1],[0,1],[-5,13],[-1,3],[2,5],[3,2],[0,1],[-4,0],[-2,1],[-2,4],[1,2],[0,1],[2,5],[2,1],[0,1],[-7,-2],[-4,2],[-3,-1],[-2,1],[1,2],[6,8],[3,5],[2,4],[1,3],[0,2],[-1,9],[0,2],[3,3],[4,4],[-6,4],[-3,4],[-2,2],[-1,2],[-3,4],[-1,5],[-2,11],[0,6],[0,4],[1,2],[1,2],[5,4],[8,7],[6,2],[5,-1],[9,-2],[7,-3],[23,-9],[4,-4],[-4,-3],[0,-1],[9,6],[2,2],[2,0],[6,-3],[3,0],[3,-2],[8,-6],[-2,3],[1,2],[6,4],[6,2],[5,3],[5,4],[3,2],[1,0],[2,-1],[6,-5],[4,-2],[3,-3],[4,-5],[1,-1],[3,-3],[4,0],[2,0],[0,-1],[1,-2],[0,-1],[0,-2],[-1,-4],[-3,-6],[2,0],[1,1],[3,3],[2,0],[4,-2],[3,-3],[2,-2],[1,-2],[1,-2],[2,-3],[-2,-2],[-4,-2],[1,-1],[5,2],[2,1],[1,2],[1,1],[7,-4],[1,-2],[-1,-1],[-1,-1],[-3,-1],[-2,-4],[0,-1],[1,-1],[5,-1],[0,-1],[-3,-1],[0,-2],[5,-7],[4,-4],[2,0],[5,0],[4,-1],[8,-5],[5,0],[5,1],[2,0],[3,-1],[1,-2],[0,-2],[0,-3],[2,-3],[2,-1],[3,0],[3,3],[2,0],[1,2],[1,4],[1,2],[2,1],[1,-1],[1,-2],[2,-5],[0,-2],[0,-3],[-1,-1],[-2,-2],[-2,-3],[-2,-3],[-2,-7],[-1,-4],[0,-3],[0,-3],[0,-3],[1,-3],[2,-4],[1,-1],[0,-3],[0,-1],[-2,-3],[-3,-3],[-5,0],[-15,0],[-4,0],[1,-2],[4,-1],[4,0],[15,-1],[2,-2],[1,-3],[2,-3],[1,-5],[0,-3],[-1,-3],[-1,-3],[-1,-5],[-1,-5],[1,-3],[8,0],[1,-2],[0,-2],[-2,-6],[-1,-1],[2,-4],[-1,-1],[0,-1],[-1,-3],[-1,-4],[-1,-3],[-2,-3],[-1,0],[-1,0],[-2,7],[-1,1],[-1,-1],[0,-1],[0,-1],[0,-2],[-1,-1],[-3,-2],[-5,-2],[0,-2],[3,-1],[5,-2],[2,-1],[4,2],[7,8],[4,1],[2,1],[3,0],[4,0],[6,1],[2,-1],[2,-2],[3,-2],[1,-2],[1,-3],[2,-8],[2,-2],[0,-2],[0,-3],[0,-4],[-2,-10],[-1,-4],[-3,-5],[-4,-2],[-6,-3],[-3,-1],[-3,-3],[0,-1],[7,4],[8,2],[2,2],[2,3],[2,5],[3,13],[2,4],[2,0],[1,-1],[3,-8],[0,-1],[-1,-2],[-4,-7],[2,0],[4,7],[1,2],[0,4],[2,2],[0,-1],[1,-8],[0,-6],[1,-2],[-1,-6],[1,-1],[1,5],[0,4],[1,2],[1,2],[5,5],[6,4],[4,3],[3,2],[5,2],[3,3],[2,5],[1,4],[1,2],[3,3],[2,0],[2,-1],[2,-3],[2,-4],[1,-3],[1,-2],[0,-8],[2,6],[0,2],[0,3],[0,2],[-2,5],[-1,3],[0,2],[2,1],[3,0],[1,1],[-2,2],[0,1],[2,4],[1,0],[3,-1],[-1,2],[0,1],[1,1],[4,-1],[1,1],[3,0],[0,2],[-3,1],[-3,1],[-1,1],[0,2],[-1,3],[0,1],[1,0],[1,-1],[1,2],[1,5],[1,1],[3,-2],[0,1],[-2,7],[0,1],[3,1],[3,-1],[5,-5],[1,0],[-1,2],[-3,3],[-2,2],[-2,1],[-2,1],[-2,5],[0,1],[0,3],[1,5],[1,1],[1,1],[2,0],[2,0],[5,-4],[0,1],[-2,2],[-1,2],[-1,2],[0,2],[2,5],[1,4],[4,11],[1,2],[1,1],[1,2],[3,0],[6,-4],[2,-2],[0,-3],[-3,-5],[-5,-3],[-1,-2],[1,0],[4,2],[5,1],[3,0],[3,-5],[0,-7],[-1,-6],[2,3],[2,1],[2,-3],[1,-4],[1,-3],[2,-4],[3,-3],[-3,-4],[-3,-2],[0,-2],[5,-2],[1,-2],[-1,-2],[1,0],[3,4],[3,-1],[3,-8],[-2,-4],[-4,-2],[-3,-1],[-5,0],[-1,-1],[1,-1],[4,0],[6,1],[5,2],[2,0],[2,-1],[0,-1],[-2,-1],[1,-2],[2,-4],[0,-1],[-2,-3],[3,0],[3,1],[1,-1],[3,-5],[1,-6],[-6,-7],[-3,-2],[-5,-3],[-1,-4],[-3,-3],[2,0],[4,6],[3,1],[2,0],[0,-1],[0,-2],[2,0],[6,4],[3,1],[4,0],[0,-1],[-2,-9],[-4,-7],[-7,-4],[-3,-3],[-3,-4],[2,0],[6,5],[5,2],[6,2],[3,-1],[5,-10],[3,-1],[2,0],[5,-3],[1,-2],[0,-3],[-2,-1],[0,-2],[1,-6],[-1,-3],[-3,-3],[-2,-1],[-3,-1],[-2,-2],[-1,-1],[-3,1],[1,-1],[1,-1],[3,-1],[3,1],[3,0],[5,-2],[2,-2],[0,-1],[-1,-1],[-2,-4],[-1,-2],[1,-1],[2,-2],[2,0],[2,0],[3,-1],[8,-9],[0,-6],[-2,-4],[1,-4],[0,-5],[-5,-2],[-14,3],[-9,3],[0,2],[2,2],[-2,0],[-2,-1],[-1,-1],[2,-4],[8,-3],[4,-5],[3,0],[2,-1],[2,-2],[-1,-1],[-4,-1],[-3,-3],[2,-1],[7,-2],[5,0],[2,-2],[-2,-2],[-5,-2],[-1,-3],[5,-2],[4,1],[1,0],[1,-8],[1,-2],[-4,-1],[0,-2],[2,-1],[5,-1],[2,-2],[0,-2],[1,-1],[2,-1],[3,3],[2,3],[2,-1],[1,-3],[2,-4],[2,0],[0,-5],[3,4],[2,-1],[2,0],[-1,-4],[-1,-4],[1,-2],[1,-3],[4,-5],[-1,-2],[-4,-4],[-2,-7],[0,-3],[-2,-4],[-3,-4],[2,1],[6,7],[3,2],[8,2],[2,2],[3,1],[1,-3],[1,-4],[2,-1],[2,1],[3,-1],[-2,-3],[-7,-11],[-2,-4],[0,-3],[2,4],[9,10],[1,1],[2,5],[2,2],[4,-1],[3,-2],[1,-5],[2,-6],[3,-7],[8,-3],[2,0],[5,2],[1,3],[4,1],[3,0],[1,-6],[2,-3],[3,-3],[3,-1],[4,-1],[2,-3],[0,-1],[-2,-3],[-2,-5],[-4,-3],[-5,0],[-8,-2],[0,-1],[-2,-2],[-3,-2],[-3,-2],[-3,-7],[-2,-3],[-2,-1],[-4,1],[-2,-1],[-2,-1],[-1,-2],[0,-1],[-5,-2],[-8,-5],[-4,-1],[-3,1],[-2,0],[-1,-2],[-4,-3],[-2,-1],[0,-2],[-1,-4],[0,-1],[-1,-1],[-3,1],[-4,2],[1,-2],[6,-5],[1,-2],[-1,-3],[-4,-3],[0,-2],[1,-1],[-1,-1],[-2,-2],[1,-1],[5,2],[4,5],[3,5],[2,2],[6,1],[3,3],[5,4],[5,5],[6,8],[7,6],[9,4],[7,2],[4,0],[1,1],[-4,1],[-3,1],[-4,-1],[-1,2],[0,1],[1,2],[3,1],[16,-2],[6,-2],[6,-13],[1,-5],[1,-3],[-1,-2],[-2,-2],[-7,-5],[-1,-1],[0,-1],[3,-1],[1,-1],[1,-5],[3,3],[6,8],[5,4],[4,1],[5,1],[1,0],[1,-3],[2,-6],[3,-1],[4,-1],[4,-6],[2,-5],[1,-3],[0,-1],[0,-2],[1,-2],[1,-2],[-1,-5],[-2,-7],[2,-7],[-1,-4],[0,-5],[1,-3],[1,-2],[-2,-1],[-9,-3],[-3,0],[-1,-2],[3,0],[5,0],[6,-2],[2,-2],[1,-2],[0,-3],[-2,-1],[-3,0],[-3,2],[0,-2],[5,-3],[1,-2],[3,-2],[0,-3],[0,-3],[-9,-12],[-8,-8],[-7,-6],[-12,-13],[-1,-1],[-2,0],[-6,2],[-4,-1],[-9,-2],[-2,-2],[-5,-4],[-2,-1],[-5,-1],[-5,1],[-2,-1],[-2,-2],[-1,-1],[0,-4],[-12,-17],[-3,-5],[-6,-6],[-6,-11],[-6,-4],[-2,-6],[-5,-4],[-10,-1],[-5,-1],[-5,2],[-5,-2],[-6,-1],[-3,0],[-12,-5],[-3,5],[-2,2],[-7,0],[-6,3],[-5,0],[-4,1],[-4,0],[-3,0],[-5,0],[-3,-3],[-10,1],[-4,2],[-3,1],[-5,-1],[-4,-2],[-9,3],[-10,-2],[-9,1],[-2,1],[-14,-3],[-5,2],[-5,-6],[-3,1],[-4,0],[-1,1],[-2,-1],[-2,-3],[-2,0],[-3,-6],[-6,-4],[-8,-22],[-1,-9],[-3,-6],[-2,-1],[-3,0],[-14,-4],[-6,-4],[2,-2],[-2,-2],[-4,-1],[-3,-3],[-3,-2],[-1,-4],[-7,-7],[-8,-14],[-4,-11],[-5,-8],[-4,-3],[-2,0],[-3,0],[-4,4],[-3,1],[-7,5],[-18,5],[3,-2],[2,-3],[5,-1],[4,0],[10,-6],[5,-3],[3,-2],[3,-4],[-2,-8],[-2,-7],[-3,-5],[-8,-14],[-4,-5],[-7,-16],[-8,-8],[-4,-4],[-4,-8],[-10,-5],[-4,-2],[-3,1],[-4,-5],[-5,-2],[-1,-5],[-12,-11],[-5,-2],[-4,-3],[-1,-5],[-3,-3],[-1,-2],[-3,-7],[-5,-10],[-7,-1],[-2,-4],[-3,-5],[-4,-3],[-8,1],[2,-2],[7,-3],[1,-5],[-4,-2],[-7,-6],[-10,-12]],[[2311,9385],[-4,-1],[-4,4],[0,4],[0,2],[0,2],[2,2],[4,1],[2,-1],[1,-2],[3,-2],[1,-1],[0,-2],[-1,-3],[-1,-2],[-1,-1],[-2,0]],[[1819,9365],[1,-1],[4,1],[4,2],[6,1],[8,2],[2,-2],[1,0],[2,3],[0,1],[0,2],[0,4],[1,3],[5,5],[2,1],[4,1],[9,0],[8,-3],[11,-3],[17,-7],[5,-3],[1,-3],[-3,-5],[-7,-8],[-6,-3],[-2,-2],[3,-1],[3,-2],[3,3],[3,3],[4,3],[1,0],[0,-2],[0,-1],[0,-1],[0,-1],[2,-1],[2,1],[5,4],[5,6],[7,3],[2,2],[7,2],[-1,1],[1,5],[-2,2],[-8,4],[-4,4],[1,4],[4,-1],[12,0],[2,0],[11,-7],[4,-4],[3,-1],[7,-3],[2,-3],[1,0],[1,-1],[-1,-1],[0,-3],[1,-1],[5,0],[1,-1],[1,-3],[2,-5],[2,-6],[3,-10],[5,-14],[2,-8],[1,-2],[1,-1],[3,-2],[3,-2],[3,-1],[1,1],[1,1],[1,4],[10,5],[0,1],[-1,2],[0,1],[2,1],[-6,7],[-5,7],[-2,9],[-1,3],[0,5],[-1,2],[-2,1],[0,2],[0,2],[0,2],[-2,3],[-7,27],[0,2],[1,2],[3,1],[3,0],[2,1],[-2,1],[-2,3],[-1,1],[2,3],[9,-2],[6,-2],[10,-5],[2,0],[1,3],[2,1],[3,0],[10,-4],[11,-7],[8,-4],[5,-5],[3,-4],[3,-4],[0,-1],[-1,-1],[1,-2],[1,-3],[1,-2],[1,-4],[1,-5],[1,-3],[10,-25],[1,-5],[2,-2],[7,-9],[3,-7],[1,-5],[0,-2],[0,-2],[0,-3],[-1,-2],[-1,-2],[-2,-3],[-2,-7],[0,-2],[2,-2],[9,-8],[6,-9],[3,-2],[7,-6],[8,-3],[3,-2],[3,-2],[1,0],[1,0],[1,1],[0,1],[-3,4],[0,2],[1,0],[9,-7],[4,-3],[6,-4],[11,-7],[1,0],[6,0],[1,0],[1,-1],[1,-1],[0,-4],[2,-3],[9,1],[2,0],[2,0],[1,-2],[2,-5],[2,-9],[0,-3],[-1,-6],[-1,-2],[-2,0],[-5,0],[-3,2],[-2,2],[-1,5],[-1,1],[-1,-1],[-1,-4],[-2,-2],[-1,-2],[-2,1],[-4,2],[-6,5],[-3,1],[-1,0],[-3,-2],[-5,-3],[-2,-3],[1,-1],[0,-2],[1,-2],[-1,-2],[0,-1],[-2,-1],[-3,0],[-5,1],[-4,1],[-7,5],[-1,1],[-2,-1],[-1,-2],[1,-2],[4,-2],[4,-4],[1,-1],[1,0],[0,-1],[1,-2],[0,-4],[-2,-7],[-1,-2],[1,0],[6,8],[3,2],[6,3],[3,3],[8,0],[3,-1],[2,-2],[0,-1],[-2,-3],[0,-1],[-1,-2],[1,-2],[0,-1],[2,-1],[2,0],[1,0],[1,-1],[1,-2],[0,-3],[-2,-7],[-3,-2],[-11,-3],[-3,-2],[-7,-2],[-3,-2],[-1,0],[-8,0],[-8,-1],[-10,2],[-7,1],[-8,4],[-3,-1],[-3,-2],[-15,3],[-2,2],[1,1],[4,4],[0,1],[0,1],[-7,1],[-8,2],[-7,1],[-6,0],[-4,0],[-3,2],[-2,2],[0,2],[-1,1],[1,4],[-1,2],[-1,2],[-4,2],[-3,-1],[-3,-1],[-2,-4],[-5,-9],[-3,-2],[-6,-7],[-3,-2],[-11,-3],[-14,-1],[-6,-2],[-4,-4],[-6,-4],[-15,-5],[-14,-2],[-14,-1],[-10,-2],[-3,1],[-5,-1],[-5,-2],[-6,-1],[-22,-1],[-10,-2],[-5,0],[-5,0],[-3,1],[-2,2],[-3,4],[-6,10],[-2,4],[0,7],[0,4],[-2,9],[-11,4],[-7,1],[-10,0],[-13,-1],[-13,1],[-7,2],[-6,2],[-12,5],[-1,2],[-1,3],[-3,3],[-8,9],[-3,4],[-1,2],[0,3],[-1,6],[-1,4],[1,2],[1,0],[16,5],[29,4],[26,4],[12,-1],[6,-1],[7,-1],[13,0],[16,-2],[3,0],[7,1],[2,2],[12,-1],[2,1],[2,1],[-3,3],[-10,5],[-29,10],[-7,2],[-10,2],[-6,1],[-7,-1],[-3,0],[-7,-2],[-7,-2],[-13,-1],[-19,-1],[-3,1],[-4,1],[-2,1],[-19,-2],[-16,2],[-19,15],[-3,4],[0,2],[3,2],[9,6],[3,1],[14,4],[14,3],[11,4],[5,1],[5,0],[5,1],[-1,1],[-4,2],[0,1],[2,1],[7,1],[7,-1],[4,0],[1,2],[-1,1],[-7,2],[-33,-6],[-16,-1],[-10,-2],[-6,0],[-7,2],[-1,1],[0,1],[2,4],[7,2],[4,5],[-4,0],[-13,-1],[-6,1],[-8,2],[-2,2],[-1,2],[-1,3],[1,6],[0,3],[1,1],[10,11],[6,2],[4,3],[0,1],[-1,2],[-4,3],[-1,2],[-1,2],[0,2],[3,4],[6,5],[17,12],[8,5],[8,2],[11,6],[28,9],[25,9],[10,-2],[2,-2],[2,-2],[1,-2],[1,-3],[1,-6],[0,-4],[0,-3],[-1,-3],[-1,-3],[-2,-3],[-3,-4],[-6,-6],[0,-2]],[[2075,9384],[-1,0],[-3,1],[-4,3],[-6,6],[-8,6],[-1,3],[-2,3],[-9,6],[-6,3],[-5,1],[-1,2],[3,5],[4,4],[2,2],[7,1],[24,3],[5,0],[6,-2],[8,-5],[3,-1],[2,-1],[2,-2],[0,-2],[1,-5],[-1,-6],[-1,-3],[-5,-8],[-5,-4],[-1,-3],[-2,-3],[-3,-3],[-3,-1]],[[2790,9426],[5,-1],[30,2],[6,-1],[19,-7],[5,-2],[3,-3],[2,-4],[1,-1],[7,-3],[2,-3],[1,-2],[2,-3],[3,-2],[3,-2],[2,-1],[-1,-5],[2,-2],[3,-3],[1,-1],[-2,-3],[-7,-1],[-17,1],[-22,4],[-14,-1],[-6,-2],[-16,-5],[-6,0],[-5,-1],[-9,4],[-3,3],[-1,1],[-2,5],[-2,6],[-1,5],[-1,3],[-3,2],[-9,1],[-3,2],[-1,2],[-1,2],[0,3],[0,3],[1,0],[1,0],[-2,3],[-1,4],[0,4],[0,3],[1,1],[1,1],[4,1],[6,0],[8,-4],[7,0],[9,-3]],[[2594,9274],[2,-1],[6,1],[5,2],[9,5],[5,1],[15,0],[3,-1],[-2,-2],[0,-1],[0,-1],[2,-2],[3,-2],[2,2],[0,4],[3,15],[1,5],[0,4],[0,4],[-1,3],[-4,1],[-5,0],[-3,0],[-3,1],[-3,1],[-1,2],[-4,5],[-2,3],[-6,5],[-3,2],[2,2],[5,3],[3,2],[4,6],[3,1],[8,-1],[12,-5],[7,-4],[2,-1],[0,1],[-2,2],[-8,6],[-4,4],[-2,3],[1,1],[4,1],[1,2],[-6,1],[-3,0],[-3,-1],[-3,0],[-5,2],[-1,1],[-3,4],[-2,4],[-1,2],[-1,1],[0,5],[0,3],[0,3],[2,2],[3,4],[2,1],[3,1],[8,-2],[20,-7],[0,2],[-23,10],[-8,2],[-2,4],[12,13],[11,3],[6,4],[9,0],[8,-3],[1,1],[-4,5],[0,1],[5,3],[9,3],[11,2],[2,2],[3,1],[5,1],[12,0],[7,0],[10,-2],[5,-4],[2,-2],[3,-7],[3,-9],[3,-4],[6,-3],[4,-2],[2,-3],[0,-3],[-1,-4],[1,-4],[3,-4],[2,-2],[4,-3],[0,-1],[-1,-2],[-3,-2],[-7,-7],[-9,-8],[-7,-6],[0,-2],[13,10],[5,0],[0,-2],[-3,-5],[-3,-4],[-4,-3],[1,-1],[6,-5],[-1,-1],[-3,0],[-1,0],[-1,-1],[-1,-1],[0,-2],[1,-3],[0,-2],[-1,-1],[1,0],[2,0],[1,1],[3,3],[9,9],[5,4],[2,0],[5,-2],[2,0],[-6,7],[-1,2],[2,3],[0,1],[4,2],[2,1],[2,-1],[2,-3],[1,-3],[2,-1],[4,1],[3,3],[4,-2],[5,-4],[0,-5],[0,-5],[0,-4],[7,-6],[4,-3],[1,0],[0,1],[-1,2],[-3,2],[-2,4],[-2,4],[1,9],[4,5],[3,-1],[4,-3],[4,0],[5,0],[11,-6],[5,0],[0,2],[-4,2],[-7,3],[-10,4],[-5,4],[0,2],[0,2],[0,2],[1,2],[2,1],[10,5],[7,3],[5,0],[9,0],[10,-1],[5,-1],[6,-4],[8,-3],[3,-1],[3,0],[4,1],[4,0],[11,-5],[3,-3],[2,-3],[1,-4],[1,-3],[0,-2],[-10,-11],[-4,-2],[-2,-4],[-4,-7],[-4,-5],[0,-1],[3,2],[3,6],[3,4],[4,4],[8,5],[7,2],[6,-1],[5,0],[4,-1],[2,-1],[1,-1],[1,-3],[0,-3],[-1,-2],[-2,-3],[-8,-3],[-5,-3],[-3,-1],[-8,-1],[0,-1],[7,-1],[7,0],[0,-1],[-4,-5],[-1,-4],[1,-3],[0,-2],[-3,-6],[-3,-4],[1,-1],[7,7],[2,7],[3,7],[3,4],[2,1],[7,1],[4,3],[4,2],[1,0],[3,-2],[0,-1],[-4,-7],[-9,-11],[3,1],[3,3],[3,2],[4,4],[3,-3],[4,-3],[2,-6],[4,-3],[2,-2],[0,3],[-4,8],[1,3],[3,2],[8,6],[5,-2],[4,-2],[1,1],[5,-1],[6,-1],[7,-1],[7,-3],[5,-3],[3,-3],[2,-3],[1,-1],[1,-4],[-1,-2],[-5,-5],[-2,-3],[-3,-1],[-7,1],[-3,0],[-2,-2],[-8,-7],[-4,-3],[-4,-2],[-1,-1],[9,0],[2,2],[3,4],[3,4],[8,2],[10,-4],[5,0],[4,4],[5,3],[1,1],[1,-1],[4,-3],[1,-2],[0,-6],[-1,-2],[-3,-5],[-7,-6],[-5,-3],[-5,-1],[-6,-3],[-2,-2],[-2,-2],[-2,-2],[-2,-1],[3,-3],[1,0],[1,2],[4,5],[2,2],[2,0],[1,0],[1,-1],[2,-1],[0,-5],[-4,-17],[3,5],[7,18],[2,3],[4,4],[8,5],[6,3],[7,2],[4,1],[4,0],[3,-3],[3,-1],[5,1],[3,0],[3,-1],[3,-2],[5,-3],[11,-4],[1,-1],[2,-2],[1,-2],[0,-3],[-2,-2],[-2,-1],[-2,-1],[-2,-1],[-4,-4],[-2,0],[-6,-2],[-6,0],[-4,-2],[-7,-3],[-10,-7],[0,-2],[4,-1],[3,1],[4,5],[5,2],[6,1],[9,2],[4,-1],[1,0],[0,-1],[1,-2],[-2,-2],[-2,-2],[-4,-6],[3,-1],[4,-1],[3,2],[2,3],[2,2],[3,1],[2,1],[2,1],[1,1],[-3,2],[0,1],[1,3],[2,3],[2,2],[2,0],[6,-2],[4,-4],[9,-10],[2,-2],[3,-8],[1,-4],[-1,-2],[-1,-2],[-1,0],[-2,0],[-13,3],[-6,-1],[-2,0],[-2,-2],[-2,-2],[-1,-2],[-3,-1],[-8,0],[-4,-1],[-8,-3],[-3,-1],[-1,-2],[5,0],[8,3],[8,0],[12,-5],[4,-1],[3,0],[2,1],[11,-1],[3,0],[5,-3],[8,-5],[1,-1],[1,-1],[1,-2],[-1,-4],[0,-1],[-3,-1],[-11,1],[-4,1],[-4,-1],[-3,0],[-5,2],[-4,2],[-8,-2],[-5,1],[-6,-1],[-12,-6],[1,-1],[16,5],[3,0],[5,-2],[8,-4],[3,-2],[0,-6],[-2,-4],[-2,-4],[-4,0],[-8,3],[-4,0],[-2,0],[-4,-2],[-1,0],[-14,4],[-3,0],[0,-1],[13,-6],[9,0],[6,-1],[3,-2],[2,-1],[0,-4],[3,-4],[3,-1],[1,0],[3,1],[3,0],[3,-1],[3,-2],[4,0],[3,-2],[2,0],[8,1],[3,-1],[1,-1],[-2,-1],[-6,-3],[-1,-3],[3,-3],[2,-3],[0,-2],[-2,-5],[0,-2],[5,4],[1,-1],[0,-5],[1,0],[2,5],[-1,6],[3,2],[8,2],[-1,-9],[0,-5],[-4,-8],[-3,-3],[2,-1],[1,0],[2,1],[3,6],[7,6],[1,1],[0,-3],[-1,-4],[3,-2],[3,2],[2,2],[3,-1],[2,0],[0,-2],[-1,-8],[0,-2],[4,-5],[0,3],[-1,6],[1,3],[3,3],[6,5],[3,1],[1,-1],[3,-2],[-1,-2],[-3,-1],[-2,-3],[-1,-4],[2,-2],[5,0],[5,3],[3,-1],[4,-4],[7,-7],[3,2],[5,-6],[-6,-4],[2,-8],[-9,0],[-4,0],[-3,0],[-4,0],[4,-2],[5,-1],[1,-2],[5,0],[3,0],[6,0],[1,3],[4,2],[2,2],[2,-1],[6,-2],[8,-6],[-4,-3],[-1,-3],[-1,-3],[0,-3],[-2,-1],[-11,-10],[2,0],[5,2],[9,4],[5,1],[3,-1],[2,0],[2,1],[3,-1],[6,-2],[7,9],[4,-2],[4,-5],[9,-9],[4,-5],[2,-2],[0,-3],[-4,-2],[-2,-1],[-6,5],[-5,2],[-3,0],[-3,-2],[1,-1],[12,-7],[2,-5],[0,-2],[-8,-4],[-2,0],[-6,2],[-3,3],[-3,1],[-4,0],[-1,0],[4,-6],[0,-1],[-2,-1],[-1,-3],[8,-4],[6,-5],[1,-2],[-4,-1],[-3,0],[-7,0],[-3,1],[-1,-1],[4,-2],[1,-2],[1,-2],[1,-2],[0,-2],[-3,-2],[-3,-5],[-2,-4],[-3,-1],[-1,1],[-4,-1],[-6,2],[-2,2],[-6,9],[0,-1],[1,-5],[0,-2],[-6,-2],[0,-1],[4,-2],[4,-1],[0,-4],[0,-18],[-1,-6],[-3,-6],[-3,-5],[-4,3],[-1,4],[-1,1],[-2,2],[-2,1],[-3,0],[-2,-3],[-3,2],[-3,4],[1,8],[1,5],[-2,-2],[-3,-7],[-3,-8],[-3,3],[-2,4],[-3,4],[-3,4],[-4,5],[-2,6],[-1,2],[-2,5],[-1,1],[0,1],[-2,3],[1,3],[2,4],[3,3],[4,3],[5,1],[2,4],[3,6],[3,5],[4,3],[-2,0],[-4,-2],[-3,-3],[-4,-6],[-3,-3],[-8,-4],[-3,-1],[-4,0],[-8,0],[-2,1],[1,4],[6,7],[-1,1],[-2,-3],[-3,-2],[-2,0],[-3,0],[-4,4],[-2,1],[-4,2],[-2,1],[-6,11],[-2,3],[-1,2],[-2,3],[-3,1],[-1,0],[1,-2],[0,-2],[-3,-1],[-3,0],[-3,2],[0,-3],[3,-5],[0,-6],[-1,-1],[-2,0],[-2,1],[-5,4],[-5,4],[-4,2],[0,-2],[2,-6],[3,-5],[4,-5],[7,-6],[3,-3],[-2,-4],[-2,-2],[-1,0],[-5,0],[-7,2],[-4,3],[-5,7],[-9,7],[-2,0],[-6,-3],[1,-1],[4,0],[3,-1],[7,-5],[0,-2],[-1,-3],[0,-3],[2,-4],[2,-3],[4,-1],[2,-1],[1,-1],[-3,-8],[0,-3],[1,-1],[6,4],[2,1],[2,0],[2,-1],[2,-2],[2,-3],[0,-2],[1,-1],[5,-3],[0,-1],[-5,-4],[-1,0],[1,-1],[4,-2],[3,-3],[2,-4],[0,-2],[0,-2],[0,-1],[2,-1],[1,1],[1,-1],[1,-3],[2,-9],[1,-3],[1,0],[0,9],[1,2],[3,-2],[5,-4],[3,-3],[1,-1],[-3,-3],[1,-1],[1,-2],[2,0],[1,4],[3,3],[2,2],[5,-2],[4,-5],[0,-1],[3,-2],[2,1],[4,-6],[-2,-2],[-4,-4],[-1,-1],[2,0],[8,0],[3,-1],[0,-3],[-4,-7],[-3,0],[-5,0],[-2,0],[0,-1],[6,-4],[2,-2],[3,-3],[1,-3],[0,-1],[-1,-2],[5,-1],[3,1],[3,0],[3,0],[0,-1],[0,-3],[-3,-3],[1,0],[3,0],[2,-1],[2,-6],[2,-5],[-1,-1],[-3,0],[1,-7],[1,-6],[0,-6],[0,-5],[-2,-1],[-3,0],[0,1],[-6,16],[-1,3],[-2,3],[-5,7],[0,-2],[1,-3],[2,-5],[1,-9],[1,-6],[0,-3],[-1,0],[-1,-1],[1,-2],[4,-6],[2,-4],[2,-4],[1,-3],[1,-1],[0,-1],[-2,-1],[-3,0],[-2,0],[-6,4],[0,-1],[3,-14],[0,-3],[-2,-1],[-2,1],[-2,4],[-4,4],[-5,5],[-4,4],[-2,-1],[0,-1],[-1,0],[-1,1],[-1,3],[-2,2],[-7,6],[-1,0],[1,-2],[1,-4],[-1,-1],[-2,0],[-3,2],[-2,4],[-3,7],[-2,3],[0,-2],[1,-7],[0,-2],[-2,0],[-1,0],[0,2],[-1,3],[-2,2],[-2,2],[-2,1],[0,3],[-1,1],[-4,-1],[-3,2],[-6,8],[-6,9],[-4,5],[-1,1],[2,-6],[2,-8],[1,-4],[-1,0],[-3,1],[-11,11],[-7,5],[-4,1],[-6,1],[-2,-3],[4,-6],[3,-5],[3,-3],[5,-6],[5,-8],[2,-3],[6,-3],[3,-1],[4,0],[0,-1],[-2,-3],[0,-1],[8,-3],[2,-2],[3,-4],[2,-1],[6,-8],[2,-1],[6,-3],[1,-1],[4,-6],[2,-2],[2,-7],[3,-3],[5,-3],[2,-1],[1,-1],[-1,-3],[0,-1],[-3,-2],[0,-3],[2,-5],[0,-3],[-2,-1],[-4,-2],[-2,0],[-2,2],[-4,2],[-7,5],[-10,3],[-4,2],[-2,2],[-2,1],[-26,4],[-4,2],[-3,1],[-2,2],[-10,5],[-1,1],[-7,9],[-5,10],[-2,1],[-5,1],[-5,0],[-3,-1],[-4,0],[-3,1],[-7,5],[-6,2],[-6,4],[-2,2],[0,1],[4,5],[-1,0],[-8,-4],[-2,1],[-4,4],[-4,3],[-6,10],[-4,3],[0,1],[5,1],[3,-1],[2,1],[5,4],[2,2],[0,2],[-4,0],[-1,1],[0,2],[-2,2],[-3,2],[-3,1],[-10,-1],[-2,1],[0,2],[2,5],[1,2],[0,1],[-2,0],[-6,-4],[-1,0],[-3,4],[-1,5],[-1,2],[-2,1],[-5,5],[-7,9],[-3,3],[-3,3],[-2,1],[1,1],[4,8],[0,2],[-4,-1],[-5,2],[-3,-2],[-2,0],[-2,1],[-1,-1],[-1,-6],[-1,-2],[-2,-1],[-1,1],[-1,1],[0,1],[0,8],[-3,1],[-5,1],[-2,0],[-1,2],[-1,2],[-1,4],[-1,3],[-2,0],[-1,0],[-1,-1],[-1,-1],[-3,0],[0,-2],[2,-3],[3,-4],[2,-5],[-1,-3],[-6,-2],[-4,-1],[-5,1],[-3,1],[-4,3],[-6,-1],[-2,-7],[-1,-1],[-6,0],[-3,0],[-8,-4],[-2,-1],[-2,0],[-2,-1],[-2,-2],[-4,0],[-5,2],[-4,1],[-3,-1],[-3,1],[-4,3],[-3,1],[-3,0],[-1,0],[-6,6],[-1,2],[-4,7],[0,2],[-1,3],[1,2],[1,4],[1,7],[2,3],[1,2],[3,3],[12,5],[3,2],[0,1],[-3,7],[0,1],[1,1],[2,4],[1,1],[2,0],[4,-1],[4,-1],[5,0],[8,-3],[12,-5],[6,-3],[5,-5],[4,-5],[0,-3],[-1,-3],[-1,-1],[0,-2],[1,-1],[3,-2],[1,0],[-1,3],[1,2],[1,2],[0,2],[-1,3],[-1,2],[-2,2],[-7,8],[-1,2],[3,1],[11,-2],[4,0],[1,3],[2,2],[2,1],[4,0],[5,-1],[2,0],[2,0],[3,2],[5,5],[2,1],[4,0],[4,1],[5,-2],[4,0],[-1,3],[-2,6],[-3,7],[-2,2],[-6,4],[-7,8],[-3,5],[-1,2],[1,2],[1,2],[12,9],[10,8],[4,5],[2,3],[2,2],[2,2],[5,1],[1,2],[1,4],[0,3],[5,9],[3,2],[5,2],[4,2],[4,7],[-1,1],[-2,2],[-1,2],[-6,18],[-4,9],[-5,7],[-5,10],[-7,9],[0,2],[1,3],[-1,1],[-7,-4],[-2,-1],[-3,2],[-2,2],[-1,4],[0,2],[1,2],[1,5],[0,2],[0,2],[-1,2],[-1,1],[-2,0],[-4,1],[-1,-1],[4,-7],[-1,-2],[-5,-1],[-2,1],[-3,1],[-2,1],[-6,7],[-1,3],[0,2],[0,1],[-2,-1],[-1,0],[-3,1],[0,1],[4,4],[1,1],[-3,1],[-3,1],[0,1],[1,1],[4,2],[1,2],[-2,1],[-2,0],[-2,-2],[-5,-5],[-3,-2],[-4,2],[-2,1],[-2,-1],[-3,-3],[-6,-3],[-11,-7],[-5,-2],[-5,1],[-1,1],[0,2],[1,2],[0,2],[1,1],[-1,8],[1,2],[2,1],[3,1],[8,-1],[4,0],[3,2],[2,2],[3,3],[0,3],[-2,5],[-1,1],[-8,4],[-4,2],[-3,0],[-3,1],[-1,2],[-2,3],[0,2],[0,2],[2,2],[6,2],[-5,2],[-3,-1],[-2,-1],[-2,-4],[-2,-1],[-5,2],[-3,1],[-2,1],[-1,1],[1,1],[2,1],[4,3],[1,2],[-3,3],[-2,0],[-6,1],[-7,-1],[-3,1],[-1,3],[-1,4],[0,4],[-1,8],[-2,3],[-2,1],[-8,-2],[-2,0],[-2,1],[-6,5],[-2,2],[-1,0],[-4,5],[-2,1],[-2,3],[-2,4],[-3,1],[-2,-1],[-3,-3],[-2,-3],[-2,-2],[0,-2],[2,-2],[9,-3],[2,-1],[2,-3],[2,-4],[1,-4],[-1,-4],[-1,-2],[-2,-2],[-5,-3],[-6,-1],[-6,-1],[-3,1],[-15,5],[-3,1],[-3,0],[-8,3],[-4,0],[-8,2],[-13,1],[-2,-1],[3,-3],[3,-1],[3,0],[3,-2],[5,-5],[3,-3],[2,-3],[0,-1],[-2,-3],[-18,12],[-11,-4],[-5,-1],[-4,-1],[-6,2],[-12,6],[-4,2],[-2,0],[-11,-2],[-9,0],[-18,2],[-7,2],[-2,1],[-2,1],[-4,0],[-10,2],[-10,-4],[-12,4],[-3,2],[-1,2],[-4,6],[0,4],[1,3],[1,2],[1,1],[-6,-3],[-3,-1],[-3,0],[-8,1],[-2,0],[1,-2],[2,-1],[0,-2],[-5,0],[-7,0],[-3,0],[-2,0],[-3,-3],[-1,-1],[-2,0],[-8,7],[-6,4],[-7,2],[-3,1],[-2,2],[-10,13],[-2,3],[-3,11],[-1,2],[-1,2],[2,0],[10,-1],[9,0],[5,-1],[6,-3],[7,-2],[6,0],[8,1],[10,2],[1,1],[-6,2],[-6,3],[-5,5],[-3,1],[-5,1],[-15,1],[-14,3],[-9,4],[-8,4],[-3,2],[-1,2],[-1,5],[-1,9],[-2,6],[-1,3],[0,3],[3,6],[7,6],[0,1],[-1,0],[-3,2],[-1,2],[-1,4],[0,3],[1,3],[1,3],[3,6],[5,7],[5,6],[0,2],[1,6],[1,4],[0,3],[1,3],[3,4],[4,4],[6,3],[1,2],[0,2],[0,1],[1,1],[15,11],[6,4],[6,3],[7,2],[20,5],[10,1],[12,-1],[24,-2],[2,-2],[1,-1],[1,-2],[-1,-1],[-6,-6],[-8,-4],[-5,-4],[-9,-9],[-3,-3],[-11,-17],[-2,-3],[-2,-2],[-1,-6],[1,-2],[1,-4],[6,-8],[2,-4],[0,-3],[-1,-8],[0,-4],[0,-4],[2,-6],[2,-7],[5,-7],[8,-8],[6,-5],[6,-3],[6,-6],[2,-2],[-3,-3],[-8,-5],[-9,-2],[-6,-1],[-6,-4],[-8,-3],[-4,-2]],[[2222,9443],[23,-12],[4,1],[7,0],[7,2],[10,2],[7,2],[2,1],[5,1],[2,0],[7,-2],[3,-1],[2,-1],[1,-2],[3,-5],[0,-2],[-2,-3],[-2,-1],[-4,-2],[-3,0],[-2,-2],[-3,0],[-1,-2],[0,-1],[1,0],[2,0],[1,1],[4,-1],[1,-1],[2,-2],[-1,-2],[-6,-3],[-9,-3],[-10,-10],[-6,-4],[-1,-1],[-1,-2],[1,-2],[0,-1],[1,0],[6,3],[3,2],[3,1],[6,0],[3,-1],[4,-2],[4,-3],[1,-1],[0,-1],[-2,-2],[4,-2],[4,-4],[0,-3],[-2,-2],[0,-2],[1,-1],[2,1],[5,2],[5,2],[3,0],[1,-1],[2,-4],[1,-4],[0,-4],[-1,-3],[-1,-2],[-4,-3],[-3,-2],[-1,0],[4,-2],[1,-2],[1,-2],[-1,-2],[0,-2],[-4,-5],[0,-1],[1,-1],[3,-3],[0,-8],[-9,-2],[-2,-2],[-3,-3],[-3,-2],[-6,-2],[-4,0],[-16,1],[-2,2],[-1,2],[-1,2],[0,3],[0,1],[0,1],[-2,-1],[-2,-3],[1,-3],[5,-10],[1,-3],[0,-2],[0,-1],[-6,-6],[-3,-1],[-4,-1],[-3,0],[-3,3],[-3,1],[-5,-1],[-1,2],[-2,2],[-3,7],[-5,6],[-5,6],[-10,9],[-6,5],[-8,9],[-3,2],[-2,0],[-5,1],[-1,1],[-2,3],[-4,2],[-1,0],[-2,0],[-5,-2],[-6,2],[-1,2],[-1,2],[-1,1],[-2,2],[-2,3],[-12,6],[-7,7],[-1,3],[0,1],[0,3],[2,4],[2,4],[1,2],[5,3],[4,1],[5,0],[3,-1],[2,-2],[1,-3],[1,-2],[4,-2],[2,-1],[3,-4],[2,-4],[3,-2],[5,0],[5,1],[12,2],[0,1],[1,1],[1,10],[1,0],[4,-4],[1,-1],[1,1],[1,2],[0,1],[-2,6],[-2,2],[-1,1],[-1,1],[-3,-1],[-3,1],[0,2],[0,2],[1,2],[2,1],[3,1],[3,-1],[4,-2],[3,-1],[4,1],[-5,1],[-7,6],[-3,1],[-4,-2],[-2,-1],[-5,-1],[-4,-1],[-15,9],[-1,1],[-1,2],[0,2],[1,1],[4,2],[6,2],[4,0],[3,-2],[5,-4],[5,-3],[0,1],[-1,3],[-2,4],[-1,1],[-4,1],[-3,2],[-1,2],[-1,2],[0,3],[0,1],[2,1],[12,2],[8,-2],[5,-1],[2,3],[0,1],[-3,-1],[-3,0],[-2,2],[0,1],[2,2],[4,1]],[[2270,9439],[-8,-2],[-4,1],[-2,-2],[-1,0],[-4,-1],[-9,3],[-3,1],[-1,1],[1,1],[1,1],[7,1],[3,1],[1,1],[1,1],[3,1],[6,1],[15,4],[7,1],[3,-1],[1,-1],[0,-1],[0,-1],[-3,-3],[-3,-2],[-8,-4],[-3,-1]],[[2412,9455],[11,-2],[5,-2],[3,-1],[4,-4],[3,-2],[10,3],[6,1],[16,-1],[12,-4],[5,-2],[3,-2],[-1,-3],[-2,-4],[-3,-4],[-5,-6],[-5,-3],[-1,-2],[-1,-2],[-2,-3],[-5,-6],[-1,-1],[-7,-3],[2,-1],[1,-1],[-1,-3],[-4,-7],[-5,-6],[-3,-4],[-6,-6],[-3,-1],[-5,-1],[-26,5],[-7,0],[-17,-3],[1,-1],[7,-2],[4,-2],[6,-6],[0,-2],[1,-1],[-1,-4],[0,-1],[-9,-10],[-3,-7],[-1,-5],[-3,-2],[-10,2],[-3,0],[-11,-1],[-5,0],[0,9],[0,10],[-2,9],[-8,16],[-1,3],[-1,3],[0,3],[0,3],[0,7],[1,4],[-1,8],[-1,14],[0,4],[0,2],[0,2],[2,1],[3,2],[2,0],[11,-4],[5,-1],[3,0],[-2,1],[-3,2],[-5,5],[-2,4],[0,2],[0,1],[0,2],[1,1],[2,2],[2,1],[6,3],[7,2],[15,1],[5,-1],[6,3],[4,0],[7,-1]],[[1674,9453],[0,-1],[7,6],[5,0],[3,-1],[1,0],[0,-1],[0,-3],[1,-5],[0,-1],[1,0],[2,2],[7,8],[4,2],[2,1],[10,1],[6,0],[7,0],[6,-2],[8,-3],[7,-4],[7,-4],[21,-16],[9,-5],[3,-3],[2,-2],[1,-2],[0,-3],[0,-2],[-1,-1],[-2,-2],[-13,-5],[-7,-2],[-7,-2],[-16,-8],[-11,-4],[-14,-8],[-28,-13],[-3,-2],[-1,-2],[-8,-14],[-3,-4],[-7,-3],[-9,-1],[-2,-1],[-1,-5],[-3,-8],[-2,-6],[-2,-14],[0,-2],[-2,-3],[-3,-3],[-8,-3],[-7,-2],[-8,-1],[-2,1],[-3,2],[-2,0],[-1,0],[-11,-10],[-11,-5],[-5,-3],[-3,-2],[-3,-1],[-4,1],[-4,1],[-3,3],[-2,3],[-5,12],[-3,4],[-2,2],[-5,7],[-2,1],[-21,9],[-10,5],[-2,2],[-3,1],[-13,0],[-1,0],[-1,1],[2,2],[0,2],[1,2],[-1,2],[0,1],[5,2],[0,1],[-1,1],[0,2],[0,1],[2,0],[1,3],[2,4],[2,2],[2,2],[4,4],[3,2],[2,2],[0,1],[-1,0],[0,2],[0,5],[0,3],[1,2],[0,1],[2,2],[9,3],[1,1],[0,1],[0,2],[-1,1],[-1,1],[-3,0],[-2,2],[-1,1],[1,3],[4,4],[2,2],[5,11],[8,6],[3,7],[6,7],[0,1],[-2,2],[-6,2],[-3,2],[-2,3],[-9,17],[-1,2],[-1,2],[-1,1],[0,1],[34,5],[24,2],[24,4],[7,0],[5,0],[5,-3],[7,-4],[9,-4],[17,-5],[11,-2],[-5,-4],[0,-1],[0,-1]],[[2295,9476],[-8,-3],[-2,1],[-1,1],[7,6],[3,1],[2,-1],[1,-2],[0,-1],[-2,-2]],[[2352,9475],[-1,0],[-2,0],[-10,3],[-1,1],[-1,1],[2,1],[1,1],[3,1],[4,0],[4,-3],[2,-3],[0,-1],[-1,-1]],[[2108,9506],[-6,-1],[-9,2],[-5,4],[-2,1],[0,1],[1,1],[2,2],[3,6],[1,2],[5,3],[3,1],[8,0],[4,-2],[2,-1],[1,-1],[2,-4],[0,-2],[2,-2],[1,-2],[0,-1],[-1,-1],[-1,-2],[-3,-2],[-8,-2]],[[2401,9505],[2,-4],[0,-2],[1,-4],[-1,-4],[-1,-1],[0,-1],[-1,-1],[0,-2],[0,-1],[-2,-1],[-10,-1],[-6,0],[-9,0],[-5,0],[-3,1],[-4,2],[-9,6],[-5,0],[-11,2],[-7,6],[-2,1],[-2,-2],[-1,0],[-1,2],[0,2],[-2,1],[-4,-1],[-1,1],[-1,2],[1,1],[0,2],[5,7],[3,0],[3,2],[2,3],[0,3],[4,5],[3,2],[5,3],[18,5],[4,1],[7,0],[6,-2],[5,-3],[9,-7],[5,-4],[2,-5],[2,-2],[3,-5],[-1,-3],[-1,-2],[0,-2]],[[2331,9533],[-2,-2],[-2,0],[-3,2],[-4,-1],[-4,-3],[-2,-3],[-1,0],[-4,-1],[-1,1],[-2,1],[-1,4],[1,2],[3,2],[10,2],[2,2],[1,1],[0,1],[1,0],[6,-2],[3,-2],[2,-1],[0,-1],[-3,-2]],[[1637,9547],[-3,-1],[-2,1],[1,1],[5,4],[0,2],[0,1],[0,1],[1,1],[2,1],[1,-1],[0,-1],[0,-4],[-1,-1],[-1,-2],[-1,-1],[-2,-1]],[[2374,9547],[-3,0],[-3,1],[-1,1],[-1,2],[0,2],[-1,2],[-1,1],[0,1],[0,1],[1,1],[3,0],[6,2],[1,0],[1,-1],[0,-3],[1,-2],[2,-4],[1,-2],[0,-1],[-6,-1]],[[1713,9537],[-8,-4],[-6,1],[-7,2],[-6,1],[-2,1],[-1,1],[2,3],[3,2],[6,4],[11,8],[7,3],[6,2],[7,5],[4,2],[3,0],[4,-1],[0,-1],[-4,-7],[-2,-2],[-5,-7],[-9,-11],[-3,-2]],[[2804,9557],[0,-3],[-2,0],[-7,-2],[-5,-1],[-2,1],[-2,3],[4,4],[5,3],[5,5],[5,3],[2,-1],[3,-2],[-3,-4],[-3,-3],[0,-3]],[[2160,9562],[6,-3],[0,-1],[-1,-1],[-7,-2],[-3,-1],[-3,-4],[-2,-1],[-10,-1],[-10,0],[2,3],[6,6],[-5,2],[-16,-4],[-6,2],[5,6],[-5,1],[-7,0],[-4,4],[1,4],[10,2],[12,2],[13,3],[10,0],[4,-1],[2,-5],[1,-6],[2,-1],[5,-4]],[[2110,9595],[2,0],[4,1],[3,0],[3,-2],[0,-2],[11,-3],[4,-2],[1,-1],[-2,-1],[-3,-2],[-3,-2],[-4,-1],[-23,0],[-2,1],[-1,1],[-3,7],[-2,3],[-1,3],[1,1],[2,2],[8,2],[4,0],[2,-1],[1,-1],[0,-1],[-2,-2]],[[2286,9588],[0,-2],[0,-2],[-1,-2],[0,-1],[1,-2],[3,-5],[2,-2],[0,-3],[0,-1],[-3,-4],[-1,-4],[0,-2],[2,-4],[0,-1],[-3,-3],[-5,-3],[0,-1],[12,-3],[1,-1],[0,-7],[2,-7],[-1,0],[-3,2],[-5,3],[-6,-5],[1,-9],[4,-4],[1,-3],[0,-1],[-4,-1],[-1,1],[-4,2],[-2,2],[-1,-1],[0,-2],[3,-2],[1,-3],[-1,-1],[-4,0],[-5,0],[-7,-2],[-4,0],[-4,1],[-4,0],[-5,0],[-2,0],[-2,2],[-3,-1],[-6,-3],[-9,1],[-8,0],[-1,1],[-2,3],[-3,7],[0,1],[9,1],[0,1],[-6,2],[-7,2],[-3,2],[0,2],[0,1],[12,3],[9,6],[5,3],[1,1],[4,1],[11,1],[0,2],[-20,-1],[-27,-4],[-9,-1],[-7,1],[-30,-6],[-1,0],[-3,2],[-3,3],[2,2],[9,5],[4,3],[0,2],[3,4],[6,1],[10,-3],[5,-3],[4,-2],[4,1],[4,2],[-1,0],[-7,-1],[-1,0],[-3,3],[-2,2],[-1,3],[0,1],[2,3],[-8,1],[-3,2],[-1,2],[0,1],[3,3],[7,4],[-1,1],[-10,0],[-2,0],[-4,3],[1,2],[3,4],[3,3],[2,0],[3,0],[8,-1],[2,-1],[5,-4],[2,-2],[0,-2],[1,-2],[4,-2],[19,-11],[3,-3],[2,-1],[5,-1],[2,0],[2,1],[1,1],[-8,4],[-2,2],[-2,3],[1,1],[2,0],[6,0],[7,1],[-8,1],[-5,2],[-5,0],[-6,2],[-1,1],[2,1],[9,1],[1,1],[1,0],[-3,2],[-3,1],[-13,2],[-5,2],[-1,2],[-1,1],[2,2],[7,4],[5,2],[9,1],[7,0],[4,-1],[10,-6],[4,-4],[8,1],[-2,4],[-2,5],[2,1],[7,3],[5,-1],[7,-4],[1,-2],[7,-2],[5,-1],[2,-1],[1,-2]],[[2188,9595],[-7,-1],[-4,1],[0,1],[3,1],[10,3],[5,4],[2,0],[8,1],[4,-1],[6,0],[-14,-5],[-13,-4]],[[1992,9565],[3,-1],[4,1],[5,0],[2,-2],[1,-2],[1,-1],[-1,-1],[0,-1],[-6,-6],[-2,-2],[2,0],[1,0],[6,4],[5,2],[3,0],[6,-1],[2,-1],[1,-1],[1,-1],[2,-4],[2,-5],[0,3],[1,3],[5,1],[0,1],[-2,1],[-1,2],[-2,3],[1,1],[1,2],[4,3],[4,1],[3,1],[14,-3],[5,-3],[3,-1],[0,-1],[1,-3],[3,-7],[0,-3],[-1,-4],[-5,-7],[0,-6],[-5,-12],[-3,-4],[-3,-2],[-14,-4],[-10,-5],[-3,0],[-3,-1],[-8,2],[-10,3],[-6,-1],[-5,-2],[-4,-1],[-3,1],[-4,0],[-4,2],[2,1],[1,1],[-1,1],[-4,1],[-5,-3],[-14,-7],[-19,-3],[-5,-1],[-5,-2],[-2,-2],[-4,-3],[-5,-3],[-10,-3],[-12,-5],[-22,-5],[-14,-1],[-13,2],[-5,1],[-4,2],[-10,5],[-2,2],[-3,4],[1,2],[5,3],[8,3],[15,3],[13,6],[5,1],[13,1],[7,0],[5,0],[3,1],[5,2],[6,4],[5,4],[2,2],[-2,1],[-3,1],[-8,-4],[-4,-2],[-4,0],[-6,-1],[-6,-1],[-1,0],[-7,4],[-3,1],[-1,-1],[-2,-1],[-3,-2],[-1,-1],[-3,-1],[-11,-1],[-10,-1],[-2,1],[-2,1],[0,1],[0,3],[-1,2],[1,3],[1,2],[2,1],[7,5],[1,1],[-3,-1],[-8,-2],[-2,1],[-1,2],[-1,1],[-1,-1],[-1,-2],[-1,-6],[-2,-3],[-3,1],[-4,2],[-1,0],[-1,0],[0,-1],[4,-5],[0,-2],[-2,-3],[-12,-5],[-4,-2],[-2,1],[-1,1],[-1,2],[-3,4],[-2,0],[-2,0],[-2,0],[-2,-2],[-1,-1],[-1,-3],[-2,-2],[-1,0],[-11,4],[-10,8],[-10,-2],[-4,1],[-14,2],[-2,2],[-1,2],[0,2],[1,1],[2,2],[3,4],[2,1],[2,1],[3,1],[7,0],[19,0],[3,1],[21,7],[2,1],[3,3],[1,1],[-25,-5],[-11,-2],[-17,1],[-3,1],[-1,2],[4,4],[2,2],[4,1],[12,2],[15,2],[10,0],[9,2],[5,1],[-17,0],[-21,-1],[-3,1],[-6,2],[0,2],[2,2],[1,1],[-1,4],[0,1],[4,3],[7,2],[4,1],[8,-1],[23,-1],[5,0],[-3,2],[-4,0],[-18,2],[-4,1],[0,1],[-1,1],[0,2],[2,2],[5,4],[16,4],[7,0],[6,0],[7,-1],[3,-2],[1,-1],[1,-2],[0,-3],[0,-1],[2,-1],[3,-5],[3,-1],[13,3],[5,0],[6,-1],[7,-2],[10,-8],[13,-7],[0,-2],[-5,-2],[-1,-2],[1,0],[5,-1],[5,1],[4,-1],[1,-1],[2,-2],[2,-5],[3,-4],[3,-2],[3,-2],[5,0],[4,1],[7,0],[39,-3],[2,0],[1,2],[1,2],[1,3],[-1,3],[0,1],[-24,9],[-2,4],[11,6],[1,1],[0,1],[0,3],[-1,2],[-7,4],[-5,0],[-8,4],[-2,1],[-1,1],[0,3],[0,1],[1,1],[8,4],[3,2],[10,10],[5,4],[3,2],[3,1],[8,1],[7,-4],[2,0],[1,-1],[0,-2],[-1,-2],[-3,-2],[-1,-2],[0,-1],[2,-3],[1,-2],[0,-3],[1,0],[4,-3],[4,-4],[2,-5],[-1,-2],[-4,-3],[-2,-2],[0,-2],[0,-1],[3,0]],[[2507,9591],[-1,-1],[-4,0],[-2,-1],[-2,1],[-3,1],[-3,4],[-4,4],[-4,5],[0,1],[1,2],[3,1],[8,1],[5,0],[5,-3],[1,-1],[1,-1],[0,-1],[0,-1],[-2,-3],[-1,-1],[0,-2],[0,-2],[1,-2],[1,-1]],[[1845,9604],[-4,-2],[-29,3],[-1,1],[-1,1],[5,3],[6,2],[15,1],[5,-1],[4,-2],[2,-1],[0,-3],[-2,-2]],[[2380,9614],[6,-1],[4,1],[4,0],[6,-2],[5,-4],[4,-2],[1,0],[1,-1],[0,-3],[0,-1],[0,-1],[-2,-3],[-1,-3],[-3,-2],[-2,-2],[-1,-3],[3,2],[12,8],[7,-1],[12,1],[14,3],[7,1],[7,-1],[5,-1],[10,-4],[4,-2],[1,-2],[1,-1],[-3,-2],[-6,1],[-11,1],[-2,1],[-2,0],[-1,-1],[0,-2],[3,-1],[13,-1],[44,-7],[1,-3],[0,-1],[-2,-1],[-3,-2],[-25,-2],[-14,2],[-12,3],[-4,-1],[3,-4],[7,-1],[6,-2],[3,-1],[13,-2],[2,-1],[4,-3],[3,-1],[3,-2],[3,-4],[1,-1],[4,1],[7,-4],[2,-1],[0,-2],[-2,-2],[-3,-3],[-7,-4],[0,-1],[8,1],[2,-1],[10,-6],[1,0],[1,0],[1,3],[0,2],[-2,3],[1,2],[2,1],[1,1],[2,0],[2,-1],[11,-8],[13,4],[2,-2],[2,-3],[1,0],[5,6],[3,1],[12,-7],[8,-2],[3,-1],[5,-2],[8,-1],[2,3],[-5,4],[3,1],[10,3],[6,0],[11,4],[7,0],[4,0],[13,7],[3,1],[2,2],[5,-1],[15,-3],[4,0],[15,4],[5,1],[6,0],[14,-3],[10,-2],[4,-1],[-2,-3],[1,-1],[1,0],[4,-1],[13,0],[6,-1],[4,-3],[1,-1],[0,-1],[-4,-3],[0,-1],[5,0],[10,-1],[2,0],[2,-4],[2,-5],[0,-2],[-3,-4],[-10,-4],[-10,-4],[-1,-1],[3,-2],[4,-1],[2,0],[9,2],[2,0],[4,-2],[1,-2],[2,-2],[-3,-2],[-12,-3],[-7,4],[-3,0],[-1,0],[1,-1],[3,-3],[1,-2],[-1,-1],[0,-2],[0,-2],[-1,-3],[-1,-4],[-27,-1],[-3,-1],[-7,-3],[-6,-1],[-3,-1],[-4,1],[-10,3],[-6,-1],[-2,1],[-6,2],[-1,1],[-2,2],[-2,4],[0,2],[1,3],[-1,2],[-1,0],[-2,1],[-5,3],[-3,1],[-1,-1],[1,-2],[1,-1],[3,-2],[1,-2],[-2,-5],[0,-1],[-4,-4],[-2,-1],[-7,0],[-10,-3],[-5,-1],[-7,1],[-4,1],[-3,2],[-3,2],[-1,0],[-1,-5],[-1,0],[-2,0],[-4,1],[-3,4],[-1,0],[0,-2],[-1,-2],[-8,-2],[-4,0],[-4,2],[-3,0],[-4,-1],[-8,2],[-2,0],[1,-4],[-3,0],[-6,0],[-10,1],[-6,-2],[-12,1],[-11,1],[-3,0],[-1,2],[0,2],[0,2],[2,3],[3,5],[1,2],[-3,1],[-1,2],[-2,0],[-4,-2],[-2,-5],[-2,-1],[-1,1],[-1,3],[-1,2],[-1,-1],[-1,0],[-1,-2],[-2,0],[-2,0],[-1,-1],[1,-2],[0,-2],[0,-1],[-2,-2],[-5,-2],[-3,-1],[-8,0],[-5,0],[-9,3],[-6,0],[-6,5],[-5,1],[0,2],[2,3],[0,1],[-7,-5],[-1,-1],[1,-3],[-1,-1],[-4,2],[-5,-1],[-1,0],[-4,2],[-5,3],[-3,3],[-4,9],[-2,6],[1,1],[3,1],[-1,2],[-4,3],[-3,3],[-2,2],[0,2],[-1,3],[0,2],[1,1],[2,4],[6,8],[1,1],[0,2],[-1,4],[-1,4],[-1,2],[-3,4],[-5,5],[-6,7],[-5,6],[-6,8],[-3,0],[-3,0],[-7,-3],[-2,-1],[-1,-1],[-5,0],[-15,1],[-6,0],[-4,0],[-7,-2],[-8,1],[-5,5],[-10,3],[-4,2],[-2,2],[1,2],[6,1],[3,2],[1,1],[-6,-1],[-3,0],[-19,8],[-5,1],[-1,1],[-1,1],[0,1],[1,2],[5,-3],[3,0],[4,1],[1,1],[-1,1],[-6,3],[-3,1],[-1,2],[1,2],[0,1],[2,1],[4,0],[5,1],[8,3],[6,1],[6,0],[14,-3],[15,-4],[8,-2]],[[1790,9640],[2,-2],[0,-1],[-1,-1],[-3,-2],[-16,-5],[-4,-2],[2,-2],[6,-4],[6,-4],[1,-2],[-3,-1],[-5,0],[-2,0],[-2,-1],[0,-1],[6,-6],[2,-2],[0,-2],[-1,-1],[-3,-2],[-4,-3],[-6,-1],[-15,-3],[-1,-2],[0,-2],[0,-3],[0,-2],[-2,-3],[-1,-2],[-3,-1],[-3,0],[-4,0],[-7,3],[-3,1],[-4,4],[-1,2],[1,3],[1,4],[2,5],[2,5],[1,2],[-1,2],[-2,0],[-5,-2],[-4,-1],[-2,-1],[-2,-2],[-1,-3],[-1,-4],[-1,-2],[-3,-1],[-4,0],[-2,-1],[-1,-2],[1,-1],[4,-3],[1,-3],[-1,-1],[-4,-4],[-2,-1],[-2,-5],[-2,-1],[-2,-2],[-2,1],[-3,1],[-3,4],[-2,3],[-1,3],[-1,1],[-2,-1],[-2,-3],[0,-2],[1,-3],[0,-2],[-3,-2],[0,-1],[5,-3],[1,-1],[0,-2],[-1,-1],[-2,0],[-1,-2],[-2,-2],[-5,-3],[-7,0],[-6,-2],[-1,0],[-1,3],[-2,5],[-1,3],[-2,1],[-3,6],[-1,2],[-1,1],[-1,0],[-1,-1],[-4,-9],[-5,-2],[-3,0],[-3,0],[-8,2],[-5,1],[-5,-1],[-6,-3],[-3,-1],[-4,0],[-1,2],[-2,2],[0,1],[1,1],[2,2],[0,1],[-2,1],[0,1],[1,1],[-1,1],[-2,0],[-6,-2],[1,2],[2,3],[8,8],[2,2],[2,0],[21,3],[1,0],[10,10],[3,2],[3,2],[14,6],[1,1],[3,4],[1,1],[3,2],[10,8],[10,6],[4,4],[7,3],[7,2],[23,3],[16,-4],[4,0],[2,1],[2,2],[2,-1],[6,-1],[2,1],[2,2],[-2,1],[-7,2],[0,1],[0,1],[2,2],[3,1],[9,1],[5,0],[4,-1],[5,-4],[13,-5]],[[2504,9634],[-7,-3],[-4,0],[-21,7],[-4,3],[-1,2],[0,4],[0,4],[1,3],[1,1],[2,1],[5,1],[5,-1],[7,-1],[7,-2],[9,-6],[4,-3],[0,-3],[0,-3],[0,-1],[-1,-1],[-3,-2]],[[2095,9627],[-4,-1],[-8,2],[-6,1],[-4,5],[-5,5],[-4,6],[-2,4],[-2,2],[-1,4],[-5,6],[5,1],[8,-1],[3,-2],[5,-3],[6,-6],[2,-2],[0,-3],[1,-2],[6,0],[6,-5],[1,-1],[1,-4],[0,-1],[-1,-4],[-2,-1]],[[2347,9664],[7,-2],[8,1],[8,1],[18,-1],[12,0],[3,0],[5,-2],[3,-1],[2,-3],[-6,-2],[-5,-9],[-1,0],[-5,0],[-3,-1],[-16,1],[-44,1],[-1,1],[-6,5],[-1,2],[1,3],[2,1],[1,1],[13,4],[5,0]],[[2175,9659],[-4,-1],[-7,1],[-8,2],[-2,2],[-1,4],[0,2],[1,1],[5,0],[10,1],[7,-1],[9,-2],[4,-1],[2,-1],[2,-2],[1,-1],[0,-2],[-11,0],[-5,-1],[-3,-1]],[[1838,9662],[-8,-2],[-5,0],[-9,3],[-10,9],[-1,3],[3,0],[3,1],[2,1],[3,2],[8,2],[1,-1],[0,-2],[0,-1],[3,-1],[3,-1],[5,-3],[4,-1],[1,-1],[1,-1],[2,-2],[0,-1],[-3,-2],[-3,-2]],[[1932,9682],[22,-1],[1,0],[0,-1],[-2,-4],[-2,-2],[-12,-3],[-16,-3],[-3,-1],[0,-1],[2,-1],[2,-1],[12,0],[3,0],[1,-1],[1,-1],[0,-2],[0,-5],[-1,-3],[-1,-3],[-5,-2],[-9,-2],[-6,-2],[-4,1],[-5,0],[-20,-5],[-6,0],[-6,1],[-7,4],[-8,2],[-3,2],[-4,1],[-1,2],[0,1],[1,1],[1,1],[1,1],[-2,3],[0,2],[-3,4],[0,2],[0,1],[0,1],[2,3],[1,0],[4,1],[6,1],[14,4],[31,5],[9,-1],[4,1],[8,0]],[[2139,9685],[-4,-1],[-3,0],[-1,1],[0,1],[0,1],[5,4],[3,1],[3,0],[2,-1],[1,-2],[-6,-4]],[[1949,9714],[5,-3],[2,0],[2,-1],[1,-1],[3,-4],[1,-2],[0,-3],[-1,-2],[-1,-2],[-2,-1],[-7,-1],[-8,1],[-8,-1],[-3,-1],[-10,1],[-2,1],[-5,3],[-4,1],[-2,-1],[-2,-2],[-4,-3],[-2,-1],[-7,1],[-10,5],[-12,-2],[-12,-3],[-5,0],[-1,1],[-2,2],[0,1],[4,3],[8,3],[6,2],[12,3],[14,2],[5,1],[3,3],[9,3],[6,2],[7,1],[6,0],[7,-3],[6,-1],[3,-2]],[[2327,9707],[7,-1],[11,0],[4,-1],[11,-4],[3,-2],[1,-2],[0,-1],[-4,-2],[-7,-2],[-1,-3],[6,-2],[3,-3],[2,-1],[0,-2],[-5,-5],[-3,-1],[-4,0],[-3,-1],[-6,-2],[-9,-2],[-13,-1],[-4,-1],[-6,-2],[-4,-1],[-2,2],[0,1],[0,2],[1,1],[-2,2],[-10,2],[-5,4],[-1,2],[0,1],[12,0],[5,1],[2,1],[1,1],[-2,1],[-9,2],[-13,2],[-1,2],[-6,3],[0,4],[-2,1],[-4,1],[0,1],[-1,2],[0,1],[0,1],[7,3],[-1,1],[-5,6],[-2,4],[0,1],[4,2],[4,0],[13,-1],[6,0],[6,-2],[6,-2],[10,-2],[3,-1],[6,-4],[0,-2],[0,-1],[1,-1]],[[2127,9752],[6,-1],[8,-4],[7,-7],[1,-1],[0,-2],[-1,-1],[-1,-2],[-1,-2],[4,-1],[0,-1],[0,-2],[0,-1],[3,1],[2,2],[0,1],[1,4],[5,1],[6,3],[3,0],[5,0],[11,-6],[4,0],[2,-1],[1,-1],[0,-2],[-2,-3],[-1,-2],[1,-1],[6,-1],[13,2],[12,-6],[6,-6],[5,-2],[1,-1],[-2,-1],[-1,-3],[-4,-2],[-1,-1],[2,-3],[0,-2],[0,-2],[1,-1],[5,-1],[12,-10],[2,-2],[2,-4],[0,-1],[-2,-2],[-2,-5],[-1,-1],[-5,-1],[-9,-1],[-8,-1],[-9,2],[-8,3],[-3,2],[-2,3],[-1,1],[0,5],[-1,1],[-4,2],[-3,4],[-6,0],[-15,4],[-6,1],[-6,-1],[-9,-1],[-2,0],[-2,1],[-1,2],[0,1],[1,3],[-26,-3],[-8,-4],[-10,1],[-5,1],[-7,4],[-4,3],[-2,3],[-1,3],[3,2],[2,1],[3,1],[14,-2],[12,-2],[6,2],[2,3],[-3,1],[-12,1],[3,2],[10,1],[5,3],[-1,1],[-3,1],[-13,-1],[-5,1],[0,1],[1,1],[7,5],[0,1],[-3,2],[-3,2],[-1,0],[-7,-1],[-10,-8],[-2,-1],[-2,0],[-2,1],[0,2],[2,2],[4,6],[0,2],[-4,1],[-11,-1],[-7,0],[-1,2],[0,3],[0,3],[2,4],[2,3],[1,2],[15,-1],[25,2],[7,0],[8,-2]],[[2256,9791],[0,-8],[0,-4],[-2,-2],[-1,-1],[-2,0],[-7,2],[-3,1],[0,1],[0,2],[-6,3],[-9,0],[-4,0],[-2,1],[-1,1],[0,5],[0,1],[1,3],[1,1],[6,3],[2,0],[9,-1],[8,0],[3,-1],[4,-2],[2,-2],[1,-3]],[[2447,9857],[4,-5],[13,-11],[6,-5],[11,-5],[1,-2],[0,-3],[3,-1],[9,-2],[10,-3],[1,1],[4,1],[4,1],[5,-1],[3,-1],[2,-2],[1,-1],[0,-1],[-2,-2],[0,-1],[1,-1],[0,-1],[-2,-4],[1,-1],[5,-4],[4,-2],[9,-2],[6,0],[4,-1],[0,1],[-2,2],[-3,4],[-7,1],[-1,2],[0,4],[0,2],[4,2],[3,0],[8,0],[4,0],[8,-3],[1,-1],[1,-3],[0,-5],[0,-2],[-7,-3],[-2,-2],[2,0],[6,-1],[9,-2],[3,0],[4,-4],[3,-4],[-2,-6],[-3,-8],[-2,-2],[-2,-3],[1,0],[9,1],[2,1],[6,2],[8,0],[3,-1],[2,-1],[2,-3],[3,-4],[1,0],[4,5],[2,1],[2,2],[1,-1],[4,-4],[9,-9],[3,-3],[0,-3],[-3,-2],[-3,-2],[-23,-6],[-10,-4],[-5,-2],[-2,-1],[-6,0],[-1,0],[-1,-5],[-2,-2],[-5,-3],[-6,-5],[-4,-3],[-7,2],[-2,3],[0,6],[-1,2],[1,1],[0,2],[3,5],[0,1],[-1,-1],[-5,-2],[-2,-1],[-1,-3],[-1,-4],[1,-7],[-1,-2],[-2,-2],[1,-1],[5,-1],[1,-1],[1,-1],[0,-2],[0,-2],[-2,-2],[-3,-1],[-4,1],[-8,6],[-3,0],[-1,-1],[0,-2],[3,-5],[0,-4],[-1,-3],[-2,-6],[-2,-2],[-1,-1],[-4,0],[-3,2],[-11,9],[-5,4],[-7,7],[-2,2],[-1,0],[-1,-3],[2,-3],[6,-7],[5,-5],[2,-5],[1,-2],[-1,0],[-2,0],[-2,2],[-6,2],[-2,2],[-2,1],[-3,2],[-5,0],[-4,1],[-5,-1],[0,-1],[5,-2],[1,-1],[2,-2],[1,-2],[-2,-1],[-6,-1],[-9,1],[-13,1],[-14,3],[-13,4],[-9,5],[-3,2],[-1,2],[3,2],[12,1],[12,2],[-2,1],[-22,2],[-7,1],[-4,-1],[-4,1],[-3,1],[-5,4],[-2,3],[0,1],[2,0],[10,0],[1,0],[-5,2],[-16,4],[-6,3],[-1,1],[0,2],[0,1],[6,2],[18,6],[7,1],[6,0],[4,2],[4,5],[19,2],[14,3],[2,1],[-11,-1],[-16,1],[-6,3],[-5,1],[-5,0],[-5,-1],[-10,-4],[-5,-1],[-10,-3],[-3,0],[-2,1],[2,3],[2,1],[0,1],[-4,0],[-5,0],[-4,0],[-12,-4],[-5,-2],[-2,0],[-6,4],[-9,2],[-2,1],[1,6],[3,2],[7,1],[22,6],[1,1],[2,2],[-4,0],[-11,-3],[-9,-1],[-7,0],[-6,0],[-3,1],[-4,2],[-13,8],[-3,4],[-1,3],[-1,3],[-3,6],[27,-4],[11,0],[21,-1],[1,1],[0,1],[0,2],[0,1],[0,1],[8,2],[1,1],[-9,0],[-16,-4],[-6,0],[-7,6],[-7,-1],[-4,0],[-5,2],[-2,1],[-2,2],[-1,1],[0,1],[2,1],[6,2],[3,0],[7,-1],[6,0],[-2,1],[-8,5],[-7,5],[0,7],[6,2],[6,0],[6,-2],[8,0],[5,-2],[4,-4],[4,0],[7,-1],[16,0],[-3,1],[-5,2],[-11,2],[-5,6],[-12,3],[-8,2],[0,1],[6,8],[8,3],[13,-1],[9,2],[10,2],[11,-1],[3,0],[1,1],[2,2],[0,1],[-2,2],[-3,1],[-13,1],[-6,0],[-3,1],[0,2],[-1,1],[0,1],[1,1],[1,1],[3,0],[13,0],[7,1],[8,-1],[18,-4],[5,-2],[6,-3],[3,-3]],[[3069,9965],[23,-1],[7,1],[9,-3],[5,0],[8,0],[6,0],[23,-1],[5,-1],[0,-1],[-5,-3],[-7,-2],[-42,-8],[-3,-1],[8,-1],[12,0],[10,1],[11,3],[3,0],[7,2],[14,3],[11,2],[5,0],[4,-2],[3,0],[1,1],[3,3],[1,1],[4,1],[2,0],[3,-2],[4,-3],[4,-2],[2,0],[8,2],[4,1],[10,-1],[4,-1],[1,-2],[-3,-1],[-2,-1],[0,-1],[1,-1],[6,-2],[8,-6],[0,-1],[-4,-4],[0,-1],[21,4],[22,-2],[6,-1],[2,-2],[3,-2],[2,-3],[-1,-4],[-10,-6],[-10,-4],[-5,-4],[-9,-2],[-31,-9],[-15,-3],[-8,-3],[-4,0],[-18,0],[-5,-2],[-3,-2],[-5,-2],[-9,0],[-17,-1],[-4,-3],[-1,-2],[-2,-2],[-1,-1],[-49,-11],[-1,-2],[5,0],[6,0],[72,14],[13,1],[13,-1],[-1,-3],[-18,-9],[-23,-8],[-12,-6],[-29,-11],[-24,-10],[-9,-6],[-12,-9],[-4,-2],[-5,-1],[-6,0],[-6,2],[-7,3],[-6,4],[-3,1],[2,-2],[12,-13],[-1,-3],[-23,-3],[-11,-2],[-5,0],[-4,0],[-3,0],[-4,-1],[0,-1],[3,-1],[9,-1],[21,3],[3,0],[5,-2],[1,-1],[-6,-4],[-16,-5],[2,-1],[5,-1],[-1,-2],[-5,-4],[-2,-1],[-16,-4],[-7,0],[-6,0],[-29,8],[-9,1],[-10,2],[-7,-1],[-7,-2],[3,-1],[14,-2],[11,-1],[5,0],[2,-2],[5,-5],[0,-3],[-1,-2],[-1,-2],[-2,-1],[-3,0],[-11,0],[-4,-1],[-5,-1],[-6,-1],[-11,0],[-13,-2],[-7,0],[-7,1],[-8,2],[-9,2],[-14,1],[1,-2],[5,0],[10,-4],[5,-5],[5,-1],[10,-4],[7,-1],[7,-1],[10,2],[7,-1],[-2,-10],[-3,-1],[-16,0],[-8,2],[-3,1],[-8,2],[-7,-1],[-6,0],[-4,-1],[-7,0],[-17,-2],[-9,0],[-7,1],[-8,1],[-9,-1],[1,-1],[3,0],[6,-2],[5,-3],[4,-1],[5,0],[6,2],[19,2],[8,0],[7,-1],[5,-1],[4,-1],[4,-4],[11,-1],[9,-1],[13,-6],[4,0],[1,-2],[-3,-4],[0,-2],[-9,-4],[-15,-1],[-15,0],[-12,-1],[-1,0],[8,-1],[18,-5],[7,-3],[1,-2],[-10,-6],[-9,-12],[-3,-1],[-3,0],[-7,0],[-10,-3],[-7,-1],[-14,1],[-15,0],[-2,-2],[0,-3],[0,-6],[1,-8],[-1,-5],[-3,-4],[-3,-2],[-6,-3],[-6,-1],[-4,-1],[-8,0],[-21,-2],[-10,0],[-8,1],[-9,3],[-14,7],[-4,1],[-4,1],[1,-1],[4,-4],[3,-3],[3,-1],[-1,-1],[-6,-2],[-7,-1],[-8,0],[0,-1],[3,-2],[3,-2],[3,0],[6,0],[7,3],[4,0],[9,0],[4,-1],[11,-5],[1,-1],[9,3],[11,0],[5,-2],[1,-4],[1,-4],[-2,-2],[3,-3],[7,-2],[5,-1],[4,2],[5,3],[3,1],[2,0],[3,-3],[5,-5],[1,-5],[-4,-7],[-5,-4],[-18,-7],[-5,-2],[-5,-3],[-6,-3],[-12,-3],[-7,-1],[-14,-4],[-3,0],[-4,1],[-1,2],[1,3],[1,3],[2,3],[0,2],[-4,3],[-2,2],[-3,1],[-5,-1],[-3,-1],[-4,0],[-3,1],[-3,1],[-6,7],[-2,0],[-3,0],[-3,1],[-2,2],[-4,2],[1,-2],[4,-3],[3,-4],[1,-3],[-1,-3],[-32,-1],[-13,0],[-3,3],[-7,10],[-1,-18],[-24,-3],[-6,0],[-9,2],[-12,5],[-5,4],[-2,3],[-2,2],[-1,0],[-3,-4],[-3,-8],[-8,2],[-11,2],[-4,8],[0,-11],[-17,1],[-8,0],[-2,10],[0,11],[-4,-7],[2,-6],[0,-7],[-7,2],[-16,1],[-5,1],[0,9],[2,10],[20,9],[6,5],[4,2],[7,1],[9,1],[6,-1],[7,1],[8,1],[6,1],[1,1],[-1,0],[-7,7],[-2,1],[-2,1],[-5,0],[-4,3],[-3,2],[-3,3],[-4,6],[-4,7],[2,4],[7,3],[7,2],[8,1],[6,0],[7,-1],[10,-4],[6,-3],[7,-8],[5,-6],[4,-3],[18,-5],[6,0],[7,0],[14,1],[7,2],[3,1],[2,3],[2,1],[6,5],[10,8],[5,7],[1,2],[2,3],[0,3],[-3,-2],[-16,-16],[-4,-3],[-9,-5],[-5,-1],[-6,0],[-9,2],[-10,-3],[-7,1],[-5,2],[0,12],[-8,9],[8,5],[7,3],[11,8],[3,0],[8,-1],[-4,1],[-5,3],[-10,-1],[4,17],[-7,-13],[-7,-6],[-4,-3],[-5,-2],[-17,-2],[4,6],[4,9],[-4,-3],[-10,-5],[-7,-3],[-7,-1],[-11,0],[-6,3],[1,6],[0,8],[4,3],[6,5],[5,6],[4,6],[16,3],[15,1],[13,3],[7,1],[6,-2],[24,-2],[10,-2],[4,-2],[4,0],[3,2],[4,2],[16,0],[4,0],[4,1],[4,2],[6,3],[1,2],[-4,0],[-4,-1],[-6,-2],[-5,-1],[-6,0],[-11,2],[-20,0],[-11,1],[-4,1],[-3,1],[-2,2],[-2,2],[1,2],[4,1],[3,0],[6,-1],[6,-3],[7,0],[-2,2],[-9,4],[-6,4],[-5,4],[-4,5],[-9,7],[-7,6],[-5,3],[-5,2],[-16,2],[-3,1],[-8,6],[-2,10],[-3,6],[3,8],[5,3],[32,-3],[14,1],[17,-1],[9,-2],[11,-5],[9,-5],[9,-4],[8,-5],[10,-7],[5,-3],[5,-2],[6,-2],[12,-3],[10,0],[5,0],[6,2],[4,2],[-4,0],[-12,0],[-9,1],[-4,2],[-5,3],[-8,6],[-6,4],[-13,6],[-10,7],[-8,6],[0,2],[5,2],[7,1],[43,4],[26,5],[11,6],[1,1],[34,8],[25,3],[9,0],[9,1],[0,1],[-7,1],[-8,1],[-17,0],[-15,1],[-5,1],[1,3],[2,3],[4,4],[5,3],[21,9],[14,3],[4,3],[-30,-6],[-11,-4],[-10,-6],[-6,-2],[-4,1],[-3,-1],[-3,-2],[-3,-3],[-2,-4],[-2,-3],[-2,-2],[-4,-2],[-10,-4],[-24,-7],[-9,-1],[-7,0],[-22,-4],[-7,0],[-8,1],[4,3],[12,6],[3,2],[-8,0],[-8,-2],[-17,-1],[-7,-3],[-6,-4],[-6,-2],[-4,-1],[-5,-1],[-20,0],[-5,0],[-12,3],[-10,-1],[-4,0],[-8,3],[-2,1],[0,2],[5,4],[5,3],[17,8],[11,4],[16,3],[36,3],[2,3],[-37,-3],[-32,-4],[-5,-1],[-8,-4],[-23,-12],[-7,-4],[-11,-1],[-8,2],[-6,1],[-11,4],[-8,2],[-4,1],[-2,2],[-2,1],[-2,2],[3,2],[21,3],[28,0],[13,0],[13,2],[18,5],[20,7],[4,3],[-7,0],[-6,0],[-13,-3],[-20,-7],[-19,-2],[-44,-1],[-15,-2],[-6,0],[-4,2],[-6,3],[1,3],[11,3],[8,1],[2,1],[-12,3],[-1,1],[7,4],[15,5],[7,1],[14,1],[14,0],[0,1],[-14,1],[-10,1],[-14,-2],[-37,-8],[-3,1],[-5,1],[1,2],[20,9],[1,1],[-14,0],[-5,0],[-4,1],[-5,-1],[-8,-3],[-5,-1],[-3,1],[-8,3],[1,3],[6,3],[6,3],[8,2],[12,3],[9,1],[15,0],[7,1],[6,2],[8,4],[9,2],[14,2],[11,0],[7,-2],[5,-3],[6,-3],[0,2],[5,3],[5,1],[7,-1],[6,-1],[8,-3],[7,-1],[3,0],[3,2],[10,0],[0,1],[-3,1],[-4,1],[-35,9],[-1,1],[12,2],[7,2],[4,1],[8,4],[6,2],[10,3],[5,-1],[5,-2],[5,-2],[15,-1],[7,-1],[11,-8],[5,-3],[6,-3],[4,-1],[8,0],[1,1],[-9,4],[-3,2],[1,2],[2,1],[3,0],[7,-2],[19,-5],[29,-7],[11,-1],[7,-3],[6,-3],[6,-2],[1,0],[-5,5],[-14,6],[-37,9],[-15,5],[-7,3],[-5,4],[-1,1],[5,3],[7,1],[9,1],[1,1],[-8,2],[-4,3],[0,1],[9,1],[6,0],[10,-3],[10,-1],[1,1],[-9,7],[-1,2],[1,1],[3,1],[10,-1],[16,-3],[29,-2],[8,0],[-1,1],[-11,2],[-13,3],[-5,2],[-4,2],[-4,2],[-1,1],[8,2],[19,0],[18,-3],[16,1],[10,-1],[4,0],[7,-3],[22,-9],[2,-2],[3,-2],[3,-3],[3,-1],[8,2],[5,2],[-2,2],[-13,5],[-3,2],[-6,3],[-14,6],[-3,3],[-3,2],[39,2],[37,-2],[6,-1],[4,-2],[3,-3],[6,-3],[12,-5],[17,-3],[-3,2],[-13,5],[-5,4],[0,2],[1,2],[2,1],[14,5],[21,2],[2,-1],[16,-7],[8,-3],[5,-1],[-7,4],[-6,2],[0,1],[9,3],[6,1],[25,1],[3,0],[2,-1],[6,-4],[2,-1]],[[5264,7907],[-1,-6],[0,-4],[0,-2],[3,-1]],[[5290,7883],[-1,-7],[-1,-4],[1,-3],[1,-2],[-1,-2],[-2,0],[-2,1],[-2,3],[-2,0],[-1,-1],[-1,-3],[-1,-4],[1,-2],[1,-1],[0,-4],[1,-4],[0,-2],[0,-1],[-2,-1],[-1,1],[-2,5],[0,2],[-2,1],[-3,-2],[-4,-3],[-1,0],[-2,1],[-1,2],[-1,5],[-1,3],[-3,1],[-1,-1],[0,-5],[-1,-6],[-1,-4],[-4,-7],[-1,-3],[0,-2],[-1,-2],[1,-3],[1,-3],[-1,-2],[-2,0],[-1,1],[-1,4],[-3,4],[2,4],[-1,1],[-4,2],[-3,3],[-3,4],[0,3],[0,7],[0,1],[-1,1],[-1,0],[-2,-2],[-2,-4],[-4,-4],[0,-1],[1,-4],[0,-1],[-3,-7],[0,-2],[-4,-4],[-2,-1],[-6,3],[-1,0],[-3,-2],[-3,-2],[-5,-2],[-3,2],[0,1]],[[5195,7829],[-1,2],[-1,3],[-2,2],[-1,2],[-1,3],[-1,2],[1,6],[-1,2],[-1,4],[1,2],[-1,0],[-5,2],[-4,-1],[-3,-2],[-2,-4],[-1,0],[1,-1],[1,-3],[-2,-4],[-3,-2],[-3,0],[-1,0],[0,4],[2,1],[2,2],[0,4],[1,2],[-2,3],[0,2],[1,3],[1,3],[1,3],[3,4],[4,4],[0,4],[0,6],[1,1],[5,3],[1,1],[0,2],[4,6],[4,6],[0,2],[1,2],[-1,1],[-1,1],[-1,2],[2,3],[2,2],[3,0],[1,-1],[0,-1],[1,-1],[1,-1],[2,1],[3,1],[1,3],[1,2],[3,3]],[[5211,7925],[2,-1],[7,-1],[4,1],[3,2],[4,0],[2,-1],[1,0],[1,1],[2,1],[1,1],[-1,0],[0,1],[-3,-1],[-1,1],[0,2],[1,2],[2,2],[2,1],[1,-1],[3,-4],[1,0],[0,1],[1,0],[1,-1],[1,-2],[7,1],[2,0],[4,-5],[5,-4]],[[3123,1965],[-1,0],[-3,1],[-4,0],[0,1],[0,1],[2,1],[6,-1],[1,0],[0,-1],[-1,-2]],[[3131,1971],[-1,0],[-1,1],[-1,1],[-5,1],[0,1],[0,2],[1,1],[2,1],[2,3],[1,-1],[1,-5],[1,-3],[0,-1],[0,-1]],[[3153,2003],[-2,-3],[-2,0],[0,1],[0,1],[0,2],[1,1],[1,1],[1,0],[2,-1],[-1,-2]],[[3136,2007],[0,-2],[-2,-3],[-3,-2],[-2,-1],[-2,1],[0,2],[-1,2],[0,1],[-1,1],[-1,0],[-2,-1],[-3,-3],[-1,-1],[-1,0],[-8,2],[-1,1],[-1,2],[-1,6],[-4,5],[6,3],[6,0],[13,-2],[5,-1],[4,-5],[0,-3],[0,-2]],[[3064,2021],[22,-6],[7,3],[5,0],[2,-5],[-6,-5],[0,-1],[1,-1],[5,-1],[2,-2],[1,-2],[-1,-3],[0,-1],[0,-2],[5,-4],[1,-3],[1,-2],[1,-4],[-1,-3],[0,-1],[-3,1],[-2,2],[-1,5],[-2,1],[-3,1],[-4,2],[-2,0],[-3,1],[-2,-1],[-1,1],[-1,4],[0,1],[1,5],[0,1],[-1,0],[-2,-1],[-1,1],[-3,3],[-1,1],[-3,0],[-2,-6],[0,-1],[2,-4],[3,-6],[-2,-1],[-4,2],[-2,1],[-1,4],[-3,1],[-1,1],[0,2],[0,4],[-1,0],[-4,-1],[-1,1],[0,2],[-1,1],[-2,1],[0,1],[1,1],[0,3],[1,11],[6,-2]],[[3028,2023],[1,-3],[0,-1],[4,-1],[1,1],[4,0],[2,1],[4,1],[3,-9],[0,-3],[-3,-3],[-2,0],[-2,1],[0,1],[0,1],[-1,2],[-2,0],[-1,-1],[-1,0],[-2,1],[-4,1],[-1,2],[0,1],[0,1],[-4,3],[-2,3],[-2,0],[-1,0],[-1,-1],[-1,-1],[-1,0],[0,1],[-1,1],[1,3],[1,0],[5,0],[3,-1],[3,-1]],[[3017,2072],[6,-5],[4,0],[0,-3],[0,-5],[0,-2],[-2,-2],[-1,-3],[-5,3],[-5,5],[-2,-1],[-3,2],[-3,-1],[-1,-2],[-4,-2],[-1,6],[-3,5],[-3,4],[2,6],[2,1],[2,2],[8,-2],[4,-2],[5,-4]],[[2974,2103],[1,-4],[0,-1],[2,1],[4,0],[5,-2],[1,0],[2,-6],[2,-2],[3,-4],[-3,-4],[-1,-4],[-1,-2],[-1,-2],[-1,-1],[-3,-3],[-3,0],[-3,-1],[-2,-2],[-1,1],[-2,1],[0,2],[2,1],[3,5],[0,5],[-3,1],[-1,0],[-2,0],[-1,1],[-1,-2],[0,-3],[0,-3],[0,-1],[-1,-1],[-3,1],[-3,3],[0,1],[1,5],[0,2],[-1,4],[-1,0],[-3,0],[-3,4],[-2,5],[-6,2],[5,6],[7,1],[2,-3],[7,-2],[0,3],[0,2],[1,1],[1,-1],[2,0],[0,-1],[1,-3]],[[2933,2136],[1,-1],[1,0],[2,-1],[5,-1],[6,-3],[2,-2],[4,-1],[3,-3],[1,-1],[1,0],[4,-6],[1,-1],[4,-5],[-2,-1],[-5,3],[-3,0],[-2,0],[0,1],[-1,3],[0,1],[-5,6],[-2,2],[-4,1],[-4,-1],[-2,1],[-1,-1],[-4,5],[-4,5],[-2,5],[-3,3],[0,2],[2,0],[2,-2],[3,-3],[1,-2],[1,-3]],[[3093,2024],[-5,0],[-1,-1],[-6,-2],[-11,3],[-3,3],[-4,5],[-1,-1],[-4,-3],[-4,-1],[-3,-1],[-2,3],[-1,1],[-1,0],[-6,-3],[-6,3],[-5,2],[-9,2],[-6,4],[-11,-1],[-2,2],[0,4],[0,2],[3,1],[0,2],[3,0],[3,-3],[1,0],[2,3],[3,2],[1,1],[5,-3],[2,0],[3,1],[1,2],[0,2],[1,1],[3,1],[3,-2],[0,-3],[0,-4],[3,-2],[5,1],[3,-2],[0,3],[-5,6],[-2,4],[-2,2],[-4,2],[-3,7],[0,7],[0,6],[6,4],[-1,5],[2,4],[2,2],[3,-15],[2,-6],[-3,-1],[-4,0],[2,-7],[5,-3],[3,-5],[0,-5],[3,-1],[5,0],[3,0],[2,3],[1,1],[4,-3],[5,-3],[2,-2],[1,-3],[0,-3],[0,-1],[2,0],[2,5],[1,1],[2,1],[1,1],[0,1],[-4,3],[-22,14],[-3,6],[-2,7],[0,7],[2,3],[4,2],[7,4],[8,6],[1,1],[0,4],[-1,3],[-3,1],[-4,1],[-3,0],[-3,-1],[-6,-4],[-4,0],[-3,2],[-2,5],[-2,5],[0,4],[1,3],[1,4],[2,1],[2,0],[2,1],[1,1],[1,1],[-1,2],[0,1],[-3,2],[-1,3],[-2,3],[1,1],[4,1],[3,-3],[2,-3],[2,0],[1,2],[4,4],[3,4],[2,6],[2,3],[3,1],[6,-11],[3,0],[8,5],[1,0],[2,-3],[1,-1]],[[2940,2193],[-1,-1],[-3,1],[-1,2],[-3,3],[0,3],[-1,3],[1,1],[2,-2],[1,-1],[1,-2],[4,-4],[1,-1],[0,-1],[-1,-1]],[[2921,2210],[1,-11],[1,-2],[3,-1],[3,-5],[0,-2],[-3,-10],[-1,-6],[-5,0],[-1,7],[-3,7],[-1,7],[-2,7],[3,4],[3,-1],[0,5],[2,1]],[[2929,2230],[0,-5],[-1,-1],[-1,-1],[-2,2],[-1,0],[-2,-2],[-2,-2],[-2,1],[-3,1],[-3,-7],[-1,-2],[-3,-4],[0,4],[2,6],[1,4],[1,6],[3,-2],[5,2],[4,4],[3,0],[1,-2],[1,-2]],[[2908,2265],[-1,-6],[-2,1],[-1,1],[0,4],[-1,1],[1,4],[1,3],[0,3],[3,0],[4,-1],[1,-1],[-1,-2],[-1,-2],[-3,0],[0,-5]],[[2915,2287],[-6,-5],[-1,2],[-4,0],[1,5],[0,4],[1,1],[0,3],[1,6],[4,-2],[2,0],[3,-2],[4,-1],[1,-5],[-4,-3],[-2,-3]],[[2913,2371],[0,-5],[-4,-8],[-3,-6],[-4,-4],[-2,0],[-1,2],[1,3],[3,4],[-1,4],[-1,1],[-1,1],[-1,2],[0,3],[1,2],[2,1],[1,-1],[5,2],[2,2],[3,1],[0,-4]],[[2931,2353],[0,-8],[0,-9],[-1,-10],[0,-3],[1,0],[0,-1],[0,-6],[-1,-4],[-1,-3],[-1,-5],[0,-1],[-3,0],[-2,0],[-1,5],[-1,3],[0,4],[-1,5],[0,2],[0,3],[2,2],[0,5],[0,1],[2,2],[0,1],[0,1],[-1,0],[-6,-6],[0,-2],[0,-2],[0,-9],[-1,-5],[-1,-1],[-3,0],[-4,1],[-4,4],[-3,-1],[0,5],[1,5],[5,-1],[1,8],[-2,2],[-2,3],[-1,3],[1,2],[3,3],[2,0],[1,-1],[4,1],[0,5],[-3,2],[0,4],[4,3],[3,4],[0,4],[-1,4],[0,1],[2,4],[3,1],[1,0],[3,-2],[2,0],[1,-1],[0,-3],[2,-19]],[[2902,2375],[-3,0],[-1,10],[4,15],[0,6],[-1,4],[0,4],[0,1],[5,3],[1,-3],[2,-9],[3,-11],[0,-12],[-2,-3],[-6,-2],[-2,-3]],[[2928,2385],[0,-1],[-4,0],[-5,-1],[-3,5],[-1,9],[-1,1],[-1,5],[-1,3],[-2,5],[0,5],[0,2],[1,3],[6,3],[2,4],[2,0],[0,-10],[1,-3],[2,-3],[0,-1],[1,-4],[1,-5],[1,-3],[0,-1],[0,-2],[0,-1],[1,-10]],[[2913,2428],[-2,0],[0,2],[-2,3],[2,2],[3,2],[2,0],[2,-2],[1,-2],[-4,-2],[-1,-2],[-1,-1]],[[2935,2552],[-1,-3],[-3,-1],[-2,2],[-4,-1],[0,5],[1,3],[3,5],[1,5],[0,8],[2,2],[0,3],[4,2],[0,-6],[-1,-11],[2,-6],[1,-2],[-1,-3],[-2,-2]],[[2915,2598],[0,-1],[-1,1],[-1,1],[-1,3],[1,2],[1,0],[1,-2],[0,-3],[0,-1]],[[2954,2602],[-1,-1],[0,1],[-1,2],[0,2],[-2,4],[-1,2],[0,2],[1,3],[2,1],[1,0],[1,-4],[0,-4],[1,-4],[-1,-4]],[[2972,2605],[-6,-5],[-4,1],[-1,4],[-1,3],[0,5],[1,2],[2,4],[1,2],[1,3],[-1,3],[1,2],[1,1],[5,-3],[5,-4],[2,-3],[0,-2],[-2,-5],[-1,-5],[-3,-3]],[[2952,2627],[-2,-3],[-2,0],[-3,-3],[-1,-3],[0,-3],[2,-3],[2,-5],[1,-6],[1,-6],[0,-2],[0,-3],[2,-5],[0,-2],[0,-2],[-1,-4],[0,-1],[-2,0],[0,-3],[-1,-1],[-4,0],[-3,1],[1,8],[-3,3],[-2,4],[-3,9],[-1,3],[-3,6],[-3,6],[4,4],[-1,6],[2,2],[4,3],[2,-2],[2,1],[1,1],[0,7],[1,5],[2,2],[3,1],[1,-3],[1,-3],[3,-2],[0,-3],[0,-4]],[[2949,2659],[1,-2],[-1,-1],[-2,1],[-1,-3],[-1,0],[-4,2],[-1,1],[0,3],[5,0],[3,2],[1,0],[0,-3]],[[2926,2672],[-4,-1],[-1,2],[0,1],[0,1],[2,1],[2,-1],[0,-1],[1,-1],[0,-1]],[[2950,2687],[-2,-1],[-2,0],[-2,1],[-3,-1],[-3,3],[-4,3],[-1,2],[1,2],[2,6],[2,12],[2,17],[-1,6],[0,3],[0,3],[1,3],[-1,3],[1,3],[2,7],[1,2],[0,4],[1,6],[-1,2],[-1,2],[1,1],[9,-4],[5,-1],[1,-5],[1,-4],[0,-7],[1,-1],[0,-5],[-3,-2],[0,-5],[2,-4],[-2,-2],[-3,-1],[0,-1],[-2,-1],[-2,-2],[1,-2],[2,-5],[3,-3],[2,-5],[2,-5],[-1,-4],[-2,-4],[-3,-3],[-3,-2],[0,-8],[-1,-3]],[[2811,3246],[-5,-1],[0,1],[1,2],[1,2],[1,0],[1,-1],[1,-1],[1,-1],[0,-1],[-1,0]],[[1964,3621],[-4,-2],[0,3],[1,3],[3,-2],[2,0],[-2,-2]],[[3098,2168],[-15,6],[-4,3],[-3,0],[-5,-4],[-4,-9],[-1,-2],[-4,-2],[-4,-1],[-14,-8],[-4,-1],[-4,-2],[-3,-4],[-1,-7],[0,-4],[-3,-15],[-1,-8],[0,-5],[1,-7],[-1,-12],[-3,-2],[-6,-4],[-4,3],[-7,2],[-5,4],[-6,4],[-2,2],[-6,9],[0,3],[-1,4],[3,5],[2,1],[4,0],[4,1],[3,-3],[0,-7],[-1,-3],[-1,-2],[1,-2],[2,2],[2,15],[9,7],[3,4],[3,7],[1,2],[0,2],[-2,2],[-4,3],[-14,-14],[-7,-4],[-4,-4],[-5,-7],[-1,-2],[-1,-4],[-1,-5],[-4,2],[-8,7],[-2,3],[2,4],[2,3],[0,11],[1,3],[2,3],[2,4],[2,1],[1,-2],[0,-2],[5,0],[9,9],[4,0],[5,-2],[6,2],[1,1],[1,2],[-4,2],[-4,2],[-12,1],[-2,-1],[-3,-5],[-2,1],[0,2],[-4,2],[-2,0],[-2,-3],[0,-3],[-1,-4],[-3,-4],[-3,-7],[0,-5],[0,-2],[-1,-2],[-1,-1],[-6,1],[-4,5],[-1,4],[-4,3],[8,5],[3,3],[3,6],[2,4],[-2,3],[-1,0],[0,-5],[-2,-3],[-4,1],[-5,-5],[-4,2],[-5,-2],[-3,3],[-1,3],[1,4],[-1,6],[-1,2],[-2,0],[-1,3],[-1,7],[-1,2],[-1,3],[1,1],[2,-1],[1,-2],[3,0],[6,-5],[2,1],[1,1],[1,4],[0,3],[1,0],[3,-4],[2,0],[4,-1],[2,1],[3,1],[5,5],[3,5],[2,1],[1,-1],[1,-1],[0,-4],[2,-3],[1,-3],[1,-3],[-1,-3],[-3,-4],[0,-2],[1,-1],[1,0],[2,2],[1,3],[0,2],[0,2],[0,3],[-2,8],[-1,1],[0,4],[3,3],[1,2],[0,5],[-1,4],[-6,7],[-11,8],[-1,-1],[-1,-1],[1,-1],[2,-1],[9,-6],[2,-4],[2,-1],[2,-2],[-1,-4],[-9,-3],[-7,-8],[-6,-4],[-3,1],[-2,5],[-2,6],[-3,3],[-2,0],[-1,1],[-1,2],[-2,-2],[-5,4],[-1,2],[3,6],[4,-2],[1,16],[-1,4],[-5,4],[-3,-1],[-3,1],[-2,2],[-3,1],[-2,1],[-3,2],[-3,2],[-5,10],[-2,6],[-1,6],[7,0],[4,1],[1,2],[-1,5],[-2,4],[1,3],[2,3],[2,-1],[6,-6],[1,-4],[4,-13],[1,-1],[0,-1],[8,-7],[2,0],[-1,6],[2,8],[3,2],[1,0],[0,2],[-2,3],[1,5],[-1,0],[-2,-3],[-4,-14],[-2,-3],[-4,7],[-1,4],[-1,2],[0,7],[7,-2],[-3,3],[-7,4],[-2,2],[-2,1],[-2,5],[-3,4],[5,7],[3,5],[9,-2],[1,1],[-1,4],[-2,-1],[-3,2],[-4,7],[0,4],[1,7],[2,1],[3,1],[4,-2],[2,-1],[2,0],[-2,5],[-3,2],[-2,4],[0,4],[1,3],[1,3],[0,5],[0,4],[1,2],[1,1],[0,1],[-3,0],[-1,-5],[0,-4],[-2,-4],[-1,-4],[0,-5],[-1,-5],[-2,2],[-2,2],[0,1],[0,3],[0,18],[0,14],[1,12],[3,4],[1,2],[2,-1],[2,0],[1,2],[-5,2],[-2,-1],[-2,-2],[-4,1],[-1,6],[-2,5],[0,7],[0,9],[5,-1],[4,-2],[11,1],[9,-9],[4,1],[0,2],[-3,2],[-2,5],[-1,1],[-1,3],[0,4],[-2,13],[-1,0],[-1,-5],[-2,-7],[-2,-4],[-4,-1],[-4,-1],[-4,1],[0,3],[0,4],[-2,2],[-4,1],[-1,1],[-1,3],[2,5],[1,3],[2,-1],[2,-1],[2,-4],[2,0],[3,3],[0,2],[-1,1],[-2,0],[-2,2],[-4,6],[2,6],[5,7],[2,1],[-2,6],[2,6],[-2,5],[-3,6],[-3,1],[-1,-2],[0,-2],[0,-2],[0,-1],[-1,0],[-5,2],[-3,3],[-6,4],[0,2],[-1,4],[2,7],[-1,0],[-4,-5],[-5,-3],[-4,-1],[-2,-2],[0,-2],[1,-1],[2,0],[2,-6],[-1,-3],[-1,-2],[-1,0],[-4,5],[-2,5],[0,4],[1,5],[6,7],[2,4],[4,3],[4,8],[4,4],[-2,4],[-2,5],[1,7],[8,3],[4,-1],[4,0],[3,2],[2,1],[4,2],[1,3],[1,2],[0,2],[-1,2],[0,6],[0,2],[2,3],[2,1],[1,-1],[3,-2],[-1,-3],[-1,-4],[-2,-15],[-1,-4],[-2,-3],[2,-6],[-2,-4],[-8,-5],[-1,0],[1,-2],[4,0],[4,1],[3,4],[1,6],[2,12],[1,2],[3,0],[1,-3],[-1,-6],[0,-6],[-3,-17],[-3,-8],[0,-1],[0,-3],[2,1],[3,3],[1,5],[2,7],[-1,5],[1,3],[0,10],[1,5],[0,7],[-1,3],[-3,1],[-1,5],[2,8],[5,0],[4,6],[4,2],[1,-1],[7,-5],[1,0],[0,2],[-1,1],[-3,2],[-4,6],[-6,1],[1,8],[1,7],[3,1],[5,2],[9,11],[2,8],[0,9],[-4,3],[-5,6],[-4,3],[-3,4],[0,6],[1,9],[4,2],[2,14],[-3,10],[1,7],[4,7],[0,4],[1,5],[4,1],[0,2],[-1,5],[-2,6],[0,8],[2,10],[4,-1],[-2,6],[-2,6],[0,3],[2,2],[2,1],[2,-3],[4,-10],[0,2],[-1,11],[-1,13],[-4,-2],[-3,1],[-1,2],[-1,3],[1,3],[1,3],[2,3],[5,2],[4,4],[1,9],[-1,-1],[-2,-8],[-3,-3],[-2,1],[-2,1],[-4,7],[-2,1],[-2,1],[-1,-2],[-5,-12],[-2,-2],[-8,-1],[-2,2],[-3,1],[0,3],[1,3],[2,2],[0,2],[-3,0],[-3,3],[-1,5],[0,7],[-3,11],[0,9],[1,6],[4,23],[1,12],[2,10],[0,7],[6,6],[2,4],[4,21],[1,12],[-7,34],[-2,7],[0,8],[2,14],[0,5],[-1,7],[-4,12],[-1,7],[2,6],[-1,8],[0,5],[1,4],[7,-2],[2,1],[2,2],[1,7],[1,10],[0,4],[1,7],[3,2],[1,6],[2,9],[3,23],[3,6],[2,7],[-1,10],[2,5],[2,3],[1,6],[2,6],[4,8],[2,10],[3,18],[1,11],[1,8],[0,7],[2,9],[2,7],[0,4],[5,9],[1,8],[-2,5],[0,8],[-1,12],[3,4],[1,3],[4,18],[0,7],[1,8],[-3,11],[0,23],[-2,18],[-2,18],[0,11],[-1,13],[0,8],[1,17],[7,11],[2,12],[1,16],[-1,12],[0,5],[-4,9],[-1,16],[1,4],[3,4],[2,6],[1,10],[2,7],[1,18],[2,15],[1,5],[3,6],[1,2],[0,5],[0,11],[0,7],[3,13],[0,7],[3,14],[0,10],[1,5],[0,6],[1,14],[-2,7],[-1,5],[3,13],[1,4],[3,6],[1,7],[0,5],[-3,23],[-1,7],[1,18],[1,12],[0,9],[0,5],[1,6],[2,7],[0,5],[0,3],[-3,2],[-2,7],[0,6],[0,5],[1,7],[3,1],[1,4],[2,7],[2,17],[1,21],[1,12],[1,6],[1,13],[1,9],[0,8],[0,6],[-3,30],[0,11],[1,18],[0,24],[0,6],[-1,5],[-1,7],[-1,13],[-2,25],[0,14],[-1,11],[-1,3]],[[3044,4127],[1,1],[2,0],[3,0],[4,3],[3,4],[3,7],[1,6],[0,5],[-1,6],[-1,5],[2,2],[3,1],[3,5],[2,3]],[[8079,6335],[2,-2],[1,-4],[0,-7],[1,-6],[-3,-4],[-2,-2],[-5,-15],[-1,-5],[-1,-2],[-1,-2],[0,-2],[-1,-8],[-1,-9],[-1,-3],[-1,-3],[-2,-2],[-1,0],[-1,-1],[-3,-5],[-3,-3],[1,-2],[0,-2],[-2,-1],[-1,0],[-4,-2],[-2,-2],[-2,-6],[-3,-1],[-2,-1],[-3,4],[-2,1],[-4,1],[-4,3],[-3,3],[-6,6],[-1,13],[-1,6],[0,3],[0,20],[1,3],[0,2],[3,4],[3,4],[5,8],[3,3],[3,5],[-2,0],[-1,0],[1,5],[1,2],[2,1],[3,-1],[2,1],[2,4],[2,1],[7,-1],[5,1],[3,4],[1,0],[3,-1],[2,-4],[0,3],[0,2],[5,-5],[0,6],[0,1],[2,3],[1,0],[1,-5],[2,-2],[2,-2]],[[8065,6399],[1,-2],[3,1],[1,-2],[0,-2],[-1,-2],[-3,2],[-2,-1],[-1,0],[-1,2],[1,3],[2,1]],[[8128,6430],[-3,-1],[1,3],[2,2],[0,-4]],[[8132,6428],[0,-1],[-1,2],[0,3],[-1,2],[1,2],[1,2],[2,-1],[-1,-3],[0,-1],[-1,-5]],[[8154,6497],[0,-2],[-2,4],[-1,0],[-1,1],[-1,3],[2,0],[2,-3],[1,-3]],[[8282,6595],[-1,-4],[-2,1],[0,2],[0,1],[1,2],[0,1],[2,-2],[0,-1]],[[8328,6650],[-3,-3],[-1,2],[0,3],[1,3],[-1,3],[1,3],[1,0],[1,-1],[1,-1],[0,-1],[0,-2],[-1,-3],[1,-2],[0,-1]],[[8367,6802],[-2,-2],[-1,0],[0,4],[2,4],[1,-1],[0,-2],[0,-3]],[[8393,6893],[0,-1],[-3,4],[-1,1],[1,2],[1,0],[2,-4],[0,-2]],[[8399,6906],[0,-3],[-1,0],[-1,5],[1,1],[1,0],[0,-3]],[[8396,6910],[0,-1],[-4,3],[-3,1],[-2,2],[0,5],[4,0],[5,-4],[1,-2],[-1,-4]],[[8384,6998],[-2,-2],[-7,5],[-5,5],[-3,7],[-1,3],[4,-1],[3,-2],[1,-4],[1,-1],[1,-2],[7,-5],[1,-1],[0,-2]],[[8625,7634],[-1,2],[-1,0],[-3,3],[-2,3],[-1,4],[0,7],[0,1],[-3,2],[0,2],[-1,1],[-2,-1],[-1,1],[-1,1],[-2,0],[-1,-1],[0,-5],[-2,-6],[0,-4],[-1,-6],[-1,-8],[0,-1],[-2,0],[-1,-1],[-1,-2],[-1,-1],[-1,2],[-2,1],[-1,0],[-2,-1],[-2,-3],[0,-3],[-1,-2],[0,-3],[-2,-3],[-1,-2],[-4,-4],[-1,-2],[-2,0],[-2,0],[-4,-1],[-5,0],[-4,0],[-4,0],[-3,-2],[0,-2],[0,-3],[0,-2],[1,-1],[1,-4],[2,-4],[2,-3],[1,-3],[0,-2],[-1,-3],[-2,-5],[-1,-2],[-1,0],[-2,1],[-1,2],[-3,1],[-6,-1],[-3,1],[-2,1],[-2,0],[-5,2],[-2,1],[-1,1],[-1,3],[-1,2],[0,3],[-2,3],[-1,2],[-2,0],[-1,-2],[-2,-1],[-1,0],[-1,0],[0,-2],[-3,-3],[-1,-2],[-1,-6],[-1,-6],[0,-2],[-1,0],[-1,-2],[-3,-6],[-2,-5],[-3,-3],[-1,-3],[-1,-3],[-2,-4],[-3,-1],[-3,-1],[-1,0],[-2,-2],[0,-2],[-1,-1],[-1,0],[-2,-2],[-3,-5],[-3,-1],[-3,-3],[-4,-3],[-1,-1],[0,-2],[-1,-1],[-1,-1],[-2,0],[-3,-4],[-2,-4],[-6,-8],[-3,-4],[0,-6]],[[8454,7488],[-1,0],[-2,-5],[-4,-4],[-10,-1],[-3,3],[-1,-2],[-1,-4],[-3,-1],[-4,0],[-2,-2],[-1,-2],[-5,-1],[-2,-3],[-4,-1],[-14,-14],[-3,-5],[-3,-7],[-2,-3],[-1,-3],[-2,-1],[-2,-2],[-1,0],[-2,1],[-2,-1],[-1,-2],[1,-4],[-1,-2],[-3,-2],[-6,-1],[-2,-2],[-1,-2],[-1,0],[-1,4],[-1,7],[3,1],[2,1],[11,8],[-1,7],[1,3],[2,4],[2,2],[-1,1],[-7,-1],[-5,0],[-2,0],[1,4],[-1,4],[0,2],[4,4],[1,1],[2,0],[0,3],[-2,4],[2,5],[8,6],[1,5],[4,6],[5,12],[1,3],[1,6],[1,2],[-3,3],[-1,5],[-8,9],[-1,8],[-1,-6],[-1,-2],[-4,0],[-2,2],[-10,2],[-2,-4],[-3,-5],[-2,-4],[-2,-2],[-2,-3],[-8,-21],[-3,-2],[-15,-12],[-7,-5],[-5,-9],[-2,-5],[-2,-6],[-1,-8],[-5,-11],[-2,-2],[-2,-1],[-2,0],[-2,-1],[-4,1],[-4,-3],[-5,-3],[-4,7],[-3,2],[-5,-2],[-2,-3],[-5,-16],[-1,-10],[0,-3],[2,-12],[3,-7],[7,-7],[15,-5],[3,2],[4,0],[4,-5],[2,-8],[1,-5],[0,-2],[1,-2],[0,-3],[-1,-2],[-2,-1],[-1,-9],[0,-9],[2,-3],[3,-4],[5,-4],[4,-1],[9,2],[3,6],[0,2],[0,3],[8,8],[4,8],[-1,2],[0,1],[0,1],[3,0],[10,8],[9,-6],[4,-7],[5,-2],[3,-3],[4,-4],[5,0],[4,0],[1,2],[2,2],[1,0],[2,-4],[4,-3],[5,0],[3,2],[2,-2],[-3,-5],[0,-8],[-2,-2],[-2,-4],[2,-3],[1,-1],[-1,-3],[-1,-2],[-3,-5],[-2,0],[-1,1],[-1,2],[0,3],[-1,2],[-4,0],[-3,0],[-7,-7],[-7,-6],[-8,-5],[-2,-2],[-2,-1],[-3,2],[-2,0],[0,-2],[2,-4],[1,-3],[-1,-2],[-1,-1],[-2,2],[-2,-3],[-1,-4],[0,-10],[-1,-2],[-3,-1],[-4,-4],[-1,2],[0,2],[0,4],[0,2],[-2,0],[-2,-1],[-2,-3],[-1,-2],[3,-6],[2,0],[0,-2],[-1,-2],[-5,-5],[-1,-3],[-1,-4],[-2,-2],[-1,-3],[-2,-2],[-2,-1],[-3,-7],[-3,-7],[-2,-3],[-2,-11],[-4,-6],[-2,-9],[1,-6],[4,0],[3,-2],[4,-7],[5,-5],[5,-3],[7,-7],[2,-3],[1,-6],[3,-18],[2,-8],[1,-5],[3,-8],[3,-15],[4,-13],[0,-9],[-1,-5],[0,-6],[4,-5],[8,-7],[2,-2],[1,-3],[0,-9],[2,-3],[1,-2],[5,-4],[2,-3],[2,-6],[1,-5],[0,-6],[-3,0],[-2,0],[-9,9],[-2,0],[-4,-1],[-4,1],[-6,10],[-3,3],[-4,1],[-9,-8],[-3,1],[0,-1],[-1,-2],[4,-1],[4,2],[4,4],[6,-2],[1,-3],[1,-6],[5,-4],[3,-2],[4,-5],[4,-9],[9,-9],[3,-9],[1,-6],[2,-8],[-3,-3],[-3,0],[-4,-2],[-3,-3],[-3,-5],[-9,-8],[-1,-5],[-2,-5],[-2,-2],[-5,2],[-5,0],[-6,-6],[-1,-2],[1,0],[1,1],[2,-1],[4,3],[4,-10],[8,2],[7,8],[2,0],[3,-1],[2,-3],[7,-14],[4,-2],[4,-3],[2,-1],[1,-1],[-5,-5],[-6,-11],[-3,-3],[-2,-3],[5,2],[4,5],[2,1],[1,-1],[1,-7],[-1,-20],[-2,0],[-2,5],[-2,2],[-2,-1],[-3,0],[-1,-3],[-1,-3],[2,-1],[4,-6],[0,-4],[-1,-2],[-3,1],[4,-4],[-1,-5],[-1,-2],[-2,-1],[-2,-5],[2,-6],[2,-9],[0,-5],[-3,2],[-4,-5],[-2,-1],[-2,7],[-2,-1],[-1,-2],[-2,-7],[-2,-7],[-2,-2],[-2,0],[-2,0],[1,-2],[2,-2],[0,-3],[-4,-8],[-1,-3],[0,-3],[-2,-4],[1,-5],[-1,-4],[-2,-6],[-1,-3],[-3,-6],[-3,-3],[-4,-13],[-1,-6],[0,-6],[-1,-2],[-2,-3],[-3,2],[0,4],[-1,0],[0,3],[-1,3],[1,3],[-1,-1],[-1,-3],[-2,-3],[-1,1],[-2,3],[0,-4],[1,-3],[0,-3],[3,-1],[2,-3],[1,-6],[0,-2],[1,-2],[0,-2],[-2,-2],[-3,-4],[-4,-6],[-2,-4],[-3,-1],[-2,1],[-2,2],[-2,1],[3,-8],[2,-2],[2,1],[3,3],[3,0],[1,-5],[-1,-6],[-2,-7],[0,-6],[2,-9],[0,-3],[-1,-1],[-2,2],[-3,3],[-2,-1],[-2,2],[-2,-1],[-1,-2],[0,-4],[2,-3],[2,-4],[-2,-1],[-6,1],[-1,-1],[-2,-5],[1,-7],[-1,-4],[-2,-1],[-3,-4],[-2,-1],[0,-1],[1,-2],[1,-2],[-2,-7],[-2,-2],[-5,1],[-3,-2],[-3,3],[-3,0],[-2,-4],[0,-4],[-2,-1],[-1,1],[-1,-1],[0,-2],[1,-2],[4,-1],[0,-3],[1,-5],[-5,-8],[-2,-5],[-2,0],[-2,-4],[-1,-6],[-2,1],[-3,-1],[-1,-3],[1,-1],[0,-2],[-1,-7],[-2,-2],[0,3],[-1,4],[-1,1],[-2,-4],[-2,-3],[-2,-1],[-1,2],[-3,2],[-2,-11],[-2,-4],[-2,-2],[-2,0],[1,-2],[1,-2],[-1,-3],[-2,-1],[-2,-2],[0,-10],[-2,-4],[-3,0],[-3,2],[0,-1],[-1,-2],[-1,-2],[-3,0],[-6,-5],[-2,1],[-4,2],[-2,-2],[-1,-3],[-1,-3],[-3,0],[-2,4],[-3,2],[-3,-2],[-2,-4],[-3,-2],[0,-2],[-1,-2],[-3,1],[-1,7],[-2,0],[-2,-3],[0,-2],[-1,-2],[0,-6],[-1,0],[-2,4],[-3,0],[-2,-3]],[[8173,6482],[-1,1],[-1,1],[-2,0],[0,-1],[-2,-1],[-1,-1],[0,-1]],[[8166,6480],[-2,2],[-3,4],[-2,7],[-3,4],[-1,4],[0,6],[-1,3],[1,3],[0,3],[-2,-2],[-3,-2],[1,-4],[-1,-3],[-3,-2],[0,-1],[1,-1],[2,-5],[1,-3],[1,-2],[1,-6],[0,-11],[1,-3],[0,-3],[-1,-4],[0,1]],[[8153,6465],[-1,0],[-1,-2],[0,-1]],[[8151,6462],[-1,-1],[-2,-1],[-1,-1],[-2,-3],[-3,-1],[-1,8],[-3,-5],[0,-11],[-1,-1],[-2,-2],[-2,4],[-3,-3],[-1,-2],[-1,-2],[-1,-3],[-3,3],[-2,3],[1,3],[-1,2],[-1,1],[-1,0],[1,-4],[0,-6],[-1,-2],[-1,-2],[-3,1],[-2,3],[-3,2],[-2,0],[-1,-4],[-1,-3],[-2,-1],[-1,1],[-2,-4],[-1,-3],[-2,-2],[-6,-2],[-2,-3],[-2,1],[-2,-1],[-2,0],[-1,2],[-1,0],[-1,-5],[-3,-2],[-3,0],[-3,-7],[-2,-3],[-2,-1],[-2,2],[0,5],[-1,1],[0,-5],[-1,-5],[-1,-2],[-4,-5],[-1,-6],[1,-5],[5,-1],[1,-3],[-1,-2],[-1,-2],[-1,-3],[6,-8],[0,-4],[-1,-2],[-1,-4],[-3,-3],[-6,-2],[-5,2],[-2,4],[1,3],[1,-1],[1,0],[0,3],[-1,1],[-2,2],[-2,7],[0,5],[-1,4],[-1,3],[-1,2],[-1,3],[2,7],[-1,5],[2,6],[1,6],[4,2],[0,6],[-3,0],[-2,5],[0,-2],[-2,0],[-3,8],[0,1],[-2,0],[1,-9],[-3,-3],[-2,-1],[-4,-1],[-2,-1],[-2,1],[1,2],[1,4],[-1,2],[-2,2],[-3,0],[-2,1],[-2,0],[-1,1],[-2,4],[-2,3],[0,2],[0,3],[0,2],[-3,0],[0,-4],[0,-5],[1,-4],[-1,-2],[-1,-2],[-2,4],[-1,2],[-1,-1],[0,-4],[-2,-3],[-3,0],[-2,-2],[-3,-1]],[[7998,6423],[-1,3],[-3,5],[-1,0],[-4,-2],[-4,-1],[-2,2],[-2,-2],[-2,6],[-3,1],[-3,4],[-1,2],[0,4],[-1,2],[-2,-1],[-1,2],[-2,2],[-2,1],[-1,-1],[-1,0],[0,2],[0,7],[0,6],[-1,3],[-1,2],[-1,1],[0,3],[0,6],[1,4],[1,1],[2,3],[1,4],[1,4],[-4,5],[-2,2],[-3,-1],[-3,-1],[-2,-1],[0,1],[-2,5],[-1,1],[-2,0],[-2,0],[-1,-2],[-2,-1],[-2,0],[-1,3],[-3,3],[-4,3],[0,3],[-1,3],[-2,3],[-2,4],[-2,2],[-1,-1],[-2,-2],[-5,-5],[-3,-2],[-1,-2],[-1,-2],[0,-5],[-1,-6],[-1,-2],[-2,-3],[-1,0],[-2,0],[-1,-1],[-5,-5],[-2,0],[-1,3],[-1,3],[-2,-1],[-2,-3],[-2,-5],[0,-4],[-1,-2],[-1,-1],[-8,13],[0,1],[-2,-3],[-1,-7],[-1,-1],[-1,0],[-3,9],[-1,1],[-1,-3],[-2,-4],[-2,-3],[0,-3],[-2,-2],[-2,-3],[-1,1],[-2,3],[-1,4],[-3,3],[-4,3],[-2,3],[-1,0],[-2,-1],[0,-1],[-1,-4],[-2,-6],[-2,-4],[-2,-3],[-1,-2]],[[7836,6473],[-1,2],[-2,1],[-2,0],[-3,-3],[-2,6],[-1,0],[-1,0],[-1,-1],[0,-4],[-1,-4],[-1,-3],[-2,-1],[1,-3],[0,-3],[0,-2],[1,-4],[1,-4],[2,-6],[1,-3],[0,-3],[1,-10],[-1,-4],[0,-8],[0,-4],[1,-3],[1,-2],[0,-1],[0,-1],[-2,-3],[-1,0],[-1,1],[-1,1],[-1,1],[-1,2],[-3,0],[-4,-3],[-1,1],[-1,1],[0,3],[0,4],[-1,2],[0,2],[0,6],[-1,3]],[[7809,6426],[0,1],[-1,7],[0,2],[-1,1],[-2,-1],[-5,-5],[-4,-9],[-2,-1],[-2,-1],[-3,1],[-2,1],[-4,-2],[-2,1],[-1,2],[-1,3],[1,3],[0,2],[-2,2],[-2,1],[-1,3],[0,4],[0,4],[1,5],[-1,3],[-3,1],[-6,2],[-6,1],[-2,0],[-2,0],[-1,1],[-1,2],[0,2],[1,5],[1,5],[3,8],[0,5],[0,6],[1,7],[2,6],[1,2],[0,3],[-1,2],[-1,2],[-2,1],[-4,1],[-4,1],[-6,4],[1,6],[0,4],[-1,4],[-1,2],[0,3],[1,6],[-2,6],[-1,3],[-2,3],[0,4],[1,3],[4,7],[0,2],[-1,0],[-1,0],[-5,-3],[-1,2],[-2,1],[-3,0],[-5,0],[-5,-3],[-5,-5],[-2,-3],[-2,-2],[-2,0],[-2,1],[0,4],[4,9],[0,5],[-1,5],[0,4],[-1,3],[-2,1],[-1,2],[0,9],[2,8],[2,2],[2,2],[0,1],[-1,6],[1,4],[1,7],[1,5],[3,-1],[1,2],[2,2],[1,3],[1,4],[1,9],[1,1],[4,-1],[1,1],[2,5],[1,6],[3,2],[2,0],[1,3],[0,3],[-2,5],[-1,4],[0,2],[3,1],[0,3],[0,7],[1,7],[1,9],[0,7],[0,5],[0,5],[-1,10],[-1,8],[0,3],[0,10],[0,9],[-2,1],[-3,3],[-1,1],[-1,-1],[-1,-3],[-1,-3],[-1,1],[-1,2],[-1,4],[-3,18],[0,5],[-1,5],[-1,2],[-1,2],[-2,6],[-2,2],[-2,0],[-1,0],[-1,3],[-1,4],[-1,1],[-2,1],[-1,0],[-1,-3],[-1,-2],[-1,-4],[-2,-6],[-1,-2]],[[7703,6809],[-1,1],[-4,6],[-2,2],[-3,-2],[-4,1],[-2,1],[-3,4],[-1,1],[-5,-3],[-1,-2],[-1,0],[-1,1],[-1,1],[0,1],[1,3],[0,1],[0,2],[2,4],[5,10],[-1,3],[-2,8],[0,3],[-1,2],[-2,-1],[-6,-7],[0,1],[0,2],[-1,7],[2,2],[2,2],[2,3],[1,3],[-1,0],[-3,-1],[-1,2],[-2,6],[-1,3],[-1,1],[-4,-3],[-5,-5],[-6,-6],[0,-3],[0,-1],[-1,-2],[-1,-3],[-1,-1],[-1,0],[-2,1],[-4,3],[-4,3],[-1,-1],[-5,2],[0,2],[-1,3],[-2,2],[-1,1],[-5,-5],[-4,-5],[-3,-4],[-3,-5],[-2,-1],[0,-3],[-1,-3],[-2,-3],[-4,-4],[-3,-3],[-8,-2],[-3,-1],[-2,-2],[-1,-6],[-1,-5],[-2,-5],[-5,-5],[-5,-5],[-1,-3],[0,-2],[0,-1],[1,-1],[0,-2],[-1,-2],[-3,-4],[-2,-2],[-2,-2],[-2,0],[-2,1],[-1,0],[-2,-1],[-1,-1],[-4,-4],[-2,0],[-2,1],[-3,1],[-2,0]],[[7468,6757],[-1,3],[-2,4],[0,5],[2,14],[0,6],[0,2],[-1,6],[-1,2],[-4,3],[-1,0],[-2,-2],[-1,-1],[-1,-2],[-5,-2],[-3,-1],[-1,-1],[-1,-2],[1,-2]],[[7447,6789],[-3,1],[-2,0],[-2,0],[-5,-4],[-2,0],[-2,0],[-2,0],[-5,0],[-4,1],[-4,5],[-2,3],[-2,2],[-3,1],[-1,3],[-1,1],[-2,0],[-1,-1],[-1,-7],[-1,-1],[-2,-1],[-3,2],[-3,4],[-1,4],[-1,1],[-2,-2],[0,-5],[0,-3],[-2,-2],[-1,1],[-1,4],[-2,8],[-3,5],[-2,4],[-7,-1],[-6,1],[-2,2],[-1,3],[1,6],[1,5],[0,2],[-1,0],[-2,1],[-6,-4],[-1,1],[-1,1],[-2,1],[-1,1],[0,3],[-5,5],[-2,3],[-3,4],[-2,2],[-2,7],[-1,7],[-1,4],[-2,2],[-2,1],[-4,-3],[-4,-2],[-2,0],[-3,7],[-3,7],[-4,7],[-2,3],[-4,1],[-4,4],[-6,8],[-4,6],[-8,7],[-2,3],[0,3],[-1,5],[-2,5],[-5,2],[-6,1],[-6,-3],[-5,-14],[-2,-3],[-2,0],[-1,3],[-1,4]],[[7250,6921],[-1,4],[-3,3],[-4,5],[-2,3],[-2,2],[-1,0],[-4,3],[-4,3],[-2,0],[0,3],[0,4],[0,4],[-1,2],[-2,0]],[[7224,6957],[-5,6]],[[7219,6963],[0,0]],[[7219,6963],[-1,2],[-2,3],[-4,-1],[-3,-1],[-2,3],[-2,4],[-1,1]],[[7204,6974],[-1,1]],[[7203,6975],[-3,8],[-3,10],[-2,1],[-1,-1],[-1,-5],[-1,1],[-1,-1],[-2,-1],[-1,-1],[-1,1],[0,1],[0,6],[-1,3],[1,4],[1,4],[-1,3],[-2,4],[0,4],[1,4]],[[7186,7020],[0,5],[0,1],[-1,2],[-5,11],[-1,2],[0,3],[-1,6],[0,4],[-1,3],[0,1],[0,1],[4,1],[2,0],[2,1],[1,-2],[1,-3],[0,-2],[2,-3],[2,-3],[3,0],[2,1],[1,5],[1,2],[2,0]],[[7200,7056],[0,3]],[[7200,7059],[0,8],[0,4],[-1,3],[1,3],[-1,4],[-1,4],[-1,1],[0,2],[0,3],[0,3]],[[7197,7094],[0,3],[0,1]],[[7197,7098],[-1,1],[-2,2],[-2,4],[-1,2],[-1,2],[-2,4],[0,9],[0,9],[-1,5],[-1,7],[0,2],[1,2],[5,6],[1,2],[0,2],[0,3],[-1,2],[-2,3],[-3,3],[-2,4],[-5,2],[-5,3],[-1,3],[-1,6],[-3,11],[-2,11],[-2,6],[0,3],[1,9],[0,1],[-1,1],[-2,-1],[-1,-1],[-1,0],[-1,2]],[[7161,7228],[-1,0]],[[7160,7228],[-2,-1],[-4,0],[-1,0],[-2,0],[-5,2],[-5,3],[-6,3],[-3,3]],[[7132,7238],[-1,1],[-3,3],[-2,2],[0,7],[-2,-1],[-3,-2],[-4,-2],[-2,0],[0,1],[-2,7],[-1,2],[-1,1],[-2,1],[-1,2],[0,2],[1,3],[1,2],[0,12],[-1,5],[0,3],[-2,5],[-1,3],[-2,2],[-3,3],[-2,1],[-4,-2],[-1,1],[-1,8],[-1,2],[-5,3],[-3,1],[-3,-1],[-1,-1],[-2,2],[-2,2],[-2,1],[-2,0],[-2,-1]],[[7080,7328],[0,1],[3,3],[2,3],[1,2],[-1,4],[-3,4],[-2,3],[0,2],[0,5],[1,4],[-1,2],[0,2],[0,5],[-2,7],[-1,4],[-1,5],[0,4],[2,8],[-1,3],[-1,3],[-7,5],[-6,4],[-3,-1],[-1,1],[-2,-3],[-1,-4],[-2,-1],[-3,2],[-2,2],[-1,6],[-1,7],[-1,2],[1,2],[0,1],[2,2],[0,1],[0,2],[-1,3],[-2,3],[-2,7],[0,4],[1,6],[0,3]],[[7045,7456],[2,1],[3,1],[1,3],[1,2],[0,2],[0,6],[-2,3],[0,2],[1,2],[1,3],[1,6],[2,3],[0,1],[2,1],[5,1],[4,3],[6,7],[2,3],[2,1],[2,0],[0,1],[-1,4],[0,2],[1,2],[1,0],[4,-2],[3,0],[3,1],[8,9],[1,0],[1,-1],[1,-6],[1,-10],[0,-2],[6,0],[4,4],[1,1],[3,-1],[1,2],[2,2],[1,-5],[2,2],[3,4],[1,3],[1,4],[2,5],[0,4],[1,3],[1,2],[3,9],[3,3],[2,1],[5,-2],[3,0],[8,-1],[4,2],[3,2],[4,-1],[4,2],[7,12],[0,2],[0,3],[2,2],[3,3],[6,6],[11,9],[4,3],[2,0],[4,3],[7,4],[2,6],[2,1],[9,1],[0,1],[0,4],[-1,4]],[[7227,7614],[1,1],[1,1],[0,3],[-2,7],[-1,7],[0,6],[0,2],[1,4],[1,4],[5,3],[3,1],[1,2],[-3,2],[-2,2],[0,1],[0,2],[0,1],[4,2],[3,3],[3,-2],[1,1],[0,3],[0,2],[-1,4],[-2,2],[0,3],[1,4],[-1,8],[-2,7],[-3,12],[-2,3],[-1,6],[-1,3],[0,4],[1,3],[-1,6],[0,6],[0,7],[1,4],[0,2],[1,1],[1,1],[1,1],[-1,2],[-2,1],[-3,3],[-4,-1],[-4,0],[-1,2],[-2,2],[0,1],[2,4],[3,3],[5,2],[5,2],[3,2],[3,1],[4,1],[2,-1],[5,2],[9,5],[7,4],[3,2],[1,-2],[1,-5],[2,-3],[3,-1],[1,0],[3,2],[4,1],[2,0],[2,-3],[2,-2],[2,0],[1,2],[1,3],[0,5],[0,4],[0,3],[-1,1],[-3,2],[-4,3],[0,2],[0,2],[1,4],[2,8],[2,12],[1,8],[4,14],[3,13],[5,20],[1,4],[0,6],[1,3],[1,1],[3,-1],[7,-5],[5,-4],[3,-1],[3,-1],[5,-2],[3,1],[3,1],[3,0],[5,-1],[2,-1],[2,0],[2,-2],[0,-4],[1,-2],[2,1],[5,4],[2,3],[4,4],[3,1],[4,1],[1,2],[1,5],[3,4],[0,4],[-1,4],[-1,5],[0,4],[-1,11],[-1,10],[1,8],[2,8],[0,3],[2,3],[1,5],[2,1],[7,1],[6,2],[3,2],[3,1],[1,1],[4,6],[1,4],[1,9],[-1,5],[1,4],[2,2],[2,2],[1,1],[3,0],[5,0],[3,-1]],[[7425,8011],[3,0],[1,0],[1,2],[2,1],[2,1],[3,1],[2,-1]],[[7439,8015],[0,-2],[0,-2],[0,-3],[1,-2],[0,-2],[-2,-1],[-1,-2],[0,-2],[1,-2],[1,-3],[3,-1],[2,-2],[1,-2],[0,-2],[-1,-2],[-1,-2],[0,-1],[0,-2],[2,0],[3,-2],[4,-2],[3,-4],[3,-1],[1,-4],[1,-6],[3,-3],[4,-4],[2,0],[2,-3],[2,-2],[2,-1],[2,-1],[4,3],[4,0],[2,-1],[2,-6],[2,-1],[1,-2],[1,-1],[2,-1],[2,2],[1,2],[2,-1],[1,-1],[0,-3],[1,-3],[3,-3],[3,-1],[0,-1],[1,-4],[1,-2],[1,-3],[1,-6],[0,-4],[1,-3],[2,-4],[2,-6],[2,-6],[2,-1],[2,-2],[2,-4],[2,-8],[0,-5],[0,-3],[1,-2],[0,-2],[-2,-8],[-1,-4],[0,-3],[1,-5],[1,-5],[0,-4],[-1,-3],[-2,-3],[-1,-2],[-2,-2],[-2,-7],[-1,-8],[0,-4],[1,-3],[1,-3],[0,-3],[3,-6],[1,-4],[1,0],[1,1],[2,0],[3,-1],[2,-3],[3,-1],[3,0],[2,-2],[2,-1],[5,0],[3,0],[5,0],[4,-2],[7,-2],[4,0],[6,2],[3,-1],[11,-2],[6,-2],[4,-3],[3,-4],[3,-6],[2,-3],[7,-2],[4,-7],[4,-3],[6,-7],[4,-2],[6,-3],[8,1],[0,-1],[0,-4],[-1,-5],[0,-4],[1,-2],[3,-1],[2,-2],[1,-3],[1,-2],[2,-11],[5,-16],[0,-7],[1,-4],[5,-6],[3,-5],[3,-5],[1,-4],[1,-6],[1,-2],[6,2],[6,1],[10,1],[15,-3],[14,-3],[13,-2],[7,-2],[14,-2],[8,3],[7,3],[2,0],[12,-4],[7,-1],[9,-2],[6,-1],[6,0],[2,-1],[2,-1],[2,-2],[4,-10],[3,-5],[5,-3],[12,-4],[6,-2],[7,-3],[5,-4],[6,-4],[7,-6],[8,2],[9,3],[5,2],[0,-13],[8,-1],[2,0],[3,-2],[2,1],[2,3],[2,4],[4,2],[5,5],[2,1],[8,7],[12,8],[6,4],[2,1],[3,2],[2,2],[4,1],[5,0],[6,2],[12,3],[2,0],[7,2],[3,1],[4,-1],[6,0],[4,-1],[5,0],[8,1],[5,0],[3,1],[5,3],[2,3],[5,3],[5,3],[4,3],[3,2],[3,1],[1,3],[1,2],[1,2],[3,6],[2,5],[2,2],[2,5],[2,3],[3,5],[2,2],[3,1],[7,5],[2,1],[1,0],[2,4],[3,3],[1,3],[3,1],[1,2],[1,2],[-1,3],[-1,4],[-1,3],[-4,6],[-3,4],[-2,5],[-1,5],[-2,3],[0,2],[0,3],[2,6],[1,3],[1,6],[2,9],[1,4],[2,4],[4,5],[4,1],[2,-1],[5,0],[4,0],[2,-3],[3,-5],[3,-2],[9,-4],[5,-1],[2,0],[5,-2],[1,0],[2,-1],[2,1],[3,4],[3,4],[2,1],[3,1],[1,2],[3,5],[3,3],[3,5],[2,4],[1,3],[0,3],[1,1],[3,2],[2,0],[5,-2],[7,0],[2,1],[6,1],[3,1],[4,1],[3,5],[4,5],[3,3],[1,0],[3,3],[1,4],[0,2],[-1,3],[2,4],[2,8],[3,3],[2,3],[1,5],[2,1],[2,1],[2,3],[2,1],[4,-2],[5,0],[3,0],[1,0],[1,2],[0,2],[1,6],[0,2],[1,1],[3,0],[2,-2],[2,-2],[2,0],[2,1],[2,5],[5,3],[2,0],[5,3],[2,-1],[5,-1],[2,1],[2,-1],[2,3],[1,1],[4,-1],[2,-3],[3,-3],[5,-1],[4,0],[4,-1],[2,0],[1,1],[4,3],[1,4],[-1,3],[1,4],[-1,3],[-2,4],[-1,2],[0,4],[-2,4],[-3,4],[-2,2],[-4,7],[-1,2],[-1,1],[0,2],[-2,1],[-2,2],[-1,2],[-1,3],[0,3],[-2,1],[-2,1],[-2,2],[-3,2],[-2,3],[-3,7],[-2,3],[-7,0],[-3,2],[-3,0],[-2,-1],[-3,0],[-2,-1],[-3,-5],[-3,-6],[-3,-3],[-2,-4],[-1,-2],[-2,1],[-2,5],[-4,3],[-3,2],[-2,1],[-3,1],[-3,0],[-4,-2],[-4,1],[-2,0],[-2,0],[-5,-4],[-2,-4],[-2,-2],[-3,3],[-3,4],[-2,4],[-2,4],[-1,11],[3,3],[4,4],[1,5],[0,7],[0,7],[4,6],[2,6],[0,3],[2,5],[2,6],[2,8],[5,14],[5,16],[2,8]],[[8240,8054],[6,-5],[4,-3],[6,-4],[6,-1],[7,-4],[3,-1],[1,0],[9,10],[7,9],[9,7],[6,1],[5,1],[3,4],[2,5],[0,7],[-1,4],[-3,2],[-1,1],[2,2],[1,3],[1,4],[1,4],[3,4],[2,5],[0,4],[2,5],[3,5],[1,5],[1,4],[1,5],[5,9],[2,10],[5,7],[8,7],[4,7],[2,7],[0,7],[-2,5],[0,6],[1,5],[-1,5],[-4,2],[-4,1],[-6,-1],[-3,1],[0,5],[1,4],[4,3],[5,8],[8,11],[8,7],[12,2],[9,4],[10,4],[6,1],[2,-1],[3,0],[7,1],[6,1],[5,3],[4,1],[4,-2],[1,0],[2,0],[2,1],[3,-2],[7,-6],[5,-3],[2,1],[2,-2],[2,-4],[3,-2],[4,-1],[5,-5],[2,0],[1,2],[2,2],[2,0],[5,-2],[5,-5],[4,-2],[1,1],[1,-1],[2,-2],[0,-3],[-1,-1],[2,-3],[1,0],[3,-1],[2,-4],[1,-2],[1,-1],[1,-2],[0,-1],[-1,-1],[0,-2],[0,-2],[0,-2],[4,-2],[1,-1],[0,-2],[1,-2],[2,-3],[1,-2],[-1,-2],[1,-1],[1,-2],[0,-4],[0,-2],[2,-3],[0,-5],[1,-6],[4,-9],[2,-4],[-1,-6],[1,-2],[2,-1],[1,-3],[-1,-3],[1,-2],[1,-2],[-1,-4],[1,-3],[1,-1],[0,-4],[1,-4],[2,-6],[5,-10],[3,-7],[2,-4],[0,-5],[-2,-3],[0,-2],[1,-2],[1,-2],[-1,-2],[2,-3],[5,-5],[-2,-8],[0,-6],[0,-6],[1,-4],[3,-2],[1,-3],[1,-2],[3,-3],[5,-3],[6,-1],[8,2],[5,1],[2,-2],[1,-2],[-1,-2],[1,-2],[4,-1],[2,-2],[1,-2],[2,-1],[2,1],[1,0],[2,-1],[1,0],[1,2],[2,0],[1,0],[1,-4],[2,-2],[2,-1],[3,-4],[7,-13],[5,-5],[4,-2],[6,0],[1,-5],[-1,-5],[0,-5],[1,-1],[2,-6],[2,-3],[0,-2],[2,-3],[-1,-5],[-2,-7],[1,-6],[3,-6],[2,-5],[0,-4],[1,-3],[1,-1],[3,0],[6,2],[4,0],[2,-3],[7,0],[10,2],[6,1],[3,-1],[2,3],[2,7],[2,3],[2,0],[3,2],[4,5],[4,3],[4,-1],[5,0],[3,2],[2,4],[5,4],[10,5],[3,1],[1,0],[3,-1],[3,-2],[3,-4],[0,-2],[0,-4],[-1,-2],[-1,-2],[-1,-3],[1,-3],[1,-6],[2,-4],[1,-5],[0,-2],[-1,-3],[-3,-6],[-2,-2],[-1,-2],[-3,-1],[-1,0],[-2,-1],[0,-2],[-1,-2],[-2,-3],[0,-2],[1,-4],[0,-4],[-2,-3],[-1,-5],[-1,-2],[0,-4],[-1,-1],[0,-9],[-2,-5],[-2,-7],[0,-4],[1,-4],[-1,-1],[0,-2],[0,-3],[-1,-2],[-3,-2],[-1,-3],[0,-4],[0,-3],[-1,-3],[-2,-2],[-1,-2],[-1,-1],[-1,-4],[0,-3],[-1,-3],[1,-3],[-1,-2],[-3,-2],[-1,-1],[-1,-1],[-2,-3],[-2,-10],[-1,-6],[1,-5],[-3,-3],[-2,-3],[-2,1],[-1,1],[-3,1],[-2,1],[-3,2],[-5,2],[-5,2],[-3,2],[-3,1],[-2,1],[-1,4],[-2,-2],[-1,-3],[-3,-2],[-1,-4],[-1,-3],[-2,-5],[-2,-1],[-5,-3],[-1,-1],[-4,0],[-1,-2],[-1,-2],[-1,-3],[1,-2],[2,-6],[0,-4],[2,-7],[3,-23],[-1,-4],[-1,-17],[0,-3],[0,-5],[0,-3],[1,-1],[1,-1],[0,-3],[0,-3],[0,-2],[-1,-5],[-1,-6],[-1,-3],[-1,-2],[-1,-1],[0,-5],[0,-3],[-2,-1],[-2,-2],[-2,1],[-1,-1],[-3,-1],[-4,-1],[-2,-2],[-1,-2],[-1,-1],[0,-2],[0,-1],[3,0],[1,-3],[0,-3],[-1,-2]],[[4914,5479],[-1,-2]],[[4913,5477],[-4,1],[1,2],[4,-1]],[[4925,5730],[0,-3],[-1,-5],[0,-2],[1,-2],[0,-3],[-2,-7],[0,-3],[2,-1],[1,-4],[1,-7],[0,-2],[0,-2],[1,-16],[2,-16],[-1,-3],[-1,0],[-1,-1],[0,-1],[0,-3],[0,-2],[-2,-1],[-3,-5],[0,-2],[-1,-5],[-1,-3],[-1,-5],[-2,-13],[0,-11],[0,-3],[-1,-3],[-1,-3],[-4,-9],[-1,-8],[0,-3],[0,-4],[-1,-2],[1,-7],[0,-5],[1,-6],[2,-15],[2,-9],[0,-7],[1,-5],[1,-2],[0,-2],[4,-2],[1,-1],[1,-9],[0,-5],[-1,-1],[0,-4],[0,-5],[-1,-1],[-2,-1],[-1,-1],[-2,0]],[[4916,5479],[-1,1],[-1,1],[-3,2],[1,9],[-1,0],[-1,-1],[-2,-10],[-1,-2],[-15,6],[-3,4],[-4,1],[-7,-1],[-5,-1],[-2,-3],[14,2],[2,0],[0,-2],[-17,-3],[-7,-2],[-2,0],[-1,4],[-7,0],[-2,-1],[-1,-3],[3,1],[5,0],[1,-2],[-14,-2],[-10,-5],[-4,-3],[-13,-11],[-9,-5],[-2,-2],[-4,-5],[-4,-4],[-6,-6],[-3,-2]],[[4790,5434],[-1,2],[0,11],[0,15],[0,5],[0,5],[0,4],[2,2],[0,2],[1,5],[1,5],[0,9],[1,2],[0,3],[-1,5],[-1,11],[0,1],[0,-1],[-1,0],[-4,4],[-2,1],[-2,3],[0,4],[-1,2],[-1,4],[-1,5],[-2,3],[-3,1],[-1,-1],[-2,0],[-3,2],[-1,2],[-2,3],[-1,3],[-1,0],[-2,0],[-1,2],[0,1],[5,11],[2,6],[0,3],[0,3],[1,4],[0,5],[-3,20],[-1,6],[-1,1],[0,1]],[[4764,5619],[1,3],[3,-1],[3,-2],[1,2],[2,10],[0,3],[0,3],[1,7],[1,2],[1,3],[0,4],[-1,1],[-1,0],[-2,1],[-2,2],[-1,2],[1,9],[0,3],[0,1],[2,1],[3,0],[3,-1],[2,0],[1,0],[1,-3],[2,-3],[1,0],[0,2],[0,9],[-1,5],[-2,4],[-4,4],[0,5],[0,6],[1,2],[3,4],[0,2],[-1,2],[-2,2],[0,7],[0,6],[-2,-1],[-2,0],[-1,2],[-1,4],[-1,10],[0,12],[0,5],[1,3],[1,3],[2,3],[1,2]],[[4778,5769],[3,1],[1,3],[2,6],[3,5],[2,0],[1,1],[1,0],[1,-3],[2,-3],[1,-4],[5,-2],[2,-1],[2,-4],[1,0],[0,1],[1,1],[0,1],[-1,3],[1,3],[0,3],[2,0],[2,0],[2,0],[2,0],[0,2],[0,7],[0,4],[0,3],[1,2],[2,-4],[2,-2],[2,0],[1,1],[-1,4],[0,1],[1,1],[1,1],[3,1],[0,-7],[0,-2],[1,-5],[1,-4],[0,-2],[-1,-3],[-1,-2],[0,-1],[1,-2],[3,-2],[2,0],[1,3],[2,2],[0,1],[1,3],[1,2],[4,3],[4,0],[1,-1]],[[5449,5315],[0,-1],[0,-3],[-2,-2],[-1,-4],[0,-5],[0,-6],[2,-7],[0,-4],[-1,0],[-1,-2],[0,-1],[-3,5],[-2,3],[-4,6],[-4,2],[-5,1],[-2,-1],[-2,2],[-2,2],[-1,1],[-2,-2],[-1,0],[-2,1],[-3,0],[0,3],[0,1],[-3,-1],[-1,3],[-1,0],[-1,1],[-3,3],[-2,-2],[-6,0],[-7,0],[-7,0],[-7,0],[-6,0]],[[5369,5308],[-1,4],[-1,2],[-3,0],[-7,-1],[-6,1],[-1,0],[-2,1],[-5,1],[-6,-1],[-1,1],[-5,-1],[-10,1],[-6,0],[0,-2],[-1,-2],[0,-3]],[[5314,5309],[-6,0],[-9,0],[-8,0],[-5,0],[-9,0],[-3,2],[-1,2],[0,2],[-1,1],[0,1]],[[5272,5317],[0,13],[2,11],[0,11],[2,9],[-1,9],[-1,4],[-6,14],[3,5],[-4,-1],[0,5],[-2,6],[1,0],[1,4],[3,-1],[0,1],[-3,5],[1,3],[1,2],[-1,2],[-2,-3],[-1,0],[-1,2],[-1,0],[0,-4],[-1,-3],[-1,-1],[-1,0],[-2,1],[0,2],[-2,1],[-3,3],[-4,2],[0,8],[-1,4],[-1,4],[0,4],[0,7],[-1,1],[-1,1],[-1,-1],[-1,1],[-2,3],[-1,2],[1,-7],[-1,-2],[-2,1],[-1,2],[0,2],[1,9],[-1,0]],[[5237,5458],[1,4],[1,6],[3,6],[2,9],[2,16],[1,9],[1,9],[1,8],[2,5],[5,10],[4,8],[2,3],[1,3],[2,2],[3,4],[2,7],[1,6],[1,2],[2,1],[4,6],[3,5],[1,-2],[0,-3],[1,-1],[2,-1],[4,0],[2,1],[1,2],[1,6],[0,1],[1,1],[4,-5],[3,-6],[3,-6],[1,-2],[1,-2],[1,-11],[1,-3],[1,-1],[3,0],[2,2],[2,3],[2,4],[2,3],[0,3],[1,9],[0,2],[2,3],[4,6],[2,4],[0,1],[-2,4],[-1,4],[2,4],[1,3],[4,11],[0,4],[1,4],[3,12],[2,17],[0,3],[2,8],[3,10],[5,2],[2,2],[2,5],[2,4],[0,4],[1,7],[1,9],[0,8],[2,7],[2,3],[4,3],[1,2],[1,4],[0,10],[0,6],[1,2],[0,5],[4,8],[2,12],[1,13],[5,15],[5,15],[3,5],[2,1],[2,1],[2,1],[6,7],[2,3],[2,3],[0,2],[1,3],[-1,8],[1,6],[1,9],[0,7],[0,3],[-1,3],[-1,1],[-1,4],[-3,3],[-4,1],[-2,1],[-1,4],[0,2],[0,2],[0,5],[-3,27]],[[5390,5937],[5,0],[6,-3],[2,-3],[0,-9],[3,-5],[3,-4],[3,-9],[1,-14],[2,-8],[0,-1],[3,-11],[0,-4],[1,-7],[-1,-5],[2,-5],[-2,-10],[-1,-6],[0,-9],[1,-15],[2,-12],[2,-9],[2,-8],[3,-8],[4,-7],[3,-5],[-3,-3],[-6,0],[-4,2],[-1,0],[-2,-1],[-6,-2],[-7,1],[-6,2],[-4,0],[-3,-5],[-2,-7],[-2,-5],[0,-6],[2,-3],[3,-7],[3,-7],[2,-5],[5,-10],[6,-10],[1,-1],[1,-2],[1,0],[3,-6],[4,-8],[4,-14],[3,-14],[2,-13],[2,-2],[1,-2],[1,-3],[-1,-4],[0,-3],[-2,-5]],[[5761,5478],[1,-4],[1,-4],[5,-7],[1,-4],[2,-4],[0,-4],[2,-2],[2,-2],[2,-2],[1,-3],[1,-3],[4,-5],[1,0],[2,0],[1,-1],[2,0],[3,3],[3,4],[2,3],[6,-1],[4,-2],[2,-3],[2,0],[5,6],[2,6],[2,2],[4,-3],[3,-6],[2,-9],[2,-3],[2,-6],[5,-11],[6,-5],[3,-3],[1,-3],[0,-4],[0,-4],[1,-1],[2,0],[1,1],[2,-1],[1,-3],[0,-3],[1,-2]],[[5856,5385],[2,-2],[0,-3],[-1,-4],[-1,-3],[-2,-7],[0,-7],[1,-2],[1,-2],[0,-2],[0,-3],[0,-2],[-2,-10],[-1,-8],[0,-5],[3,-3],[3,0],[2,-2],[1,-3],[1,-1],[1,0],[1,-1],[1,-3],[1,-2],[1,-3],[0,-3],[0,-2],[-3,-7],[-6,-14],[-13,-26],[-4,-3],[-3,-5],[-1,-7],[-4,-6],[-3,-3],[0,-2],[0,-6],[0,-10],[-1,-5],[-2,-9],[-1,-6],[-1,-1],[-1,-3],[-1,-9],[0,-3],[-1,-19],[0,-5],[-1,-9],[0,-5],[-1,-6],[0,-5],[0,-9],[0,-13],[0,-2]],[[5821,5104],[-1,-1],[-2,-4],[-2,-2],[-1,-1],[-3,-6],[-2,-5],[-1,-6],[0,-2],[0,-8],[0,-8],[0,-4],[-1,-2],[-3,-4],[-2,-4],[-1,-1],[-1,-3],[1,-6],[0,-5],[1,-3],[2,-2]],[[5816,4928],[0,-3],[-1,-10],[-1,-10],[0,-3],[1,-5],[2,-11],[1,-8],[1,-5],[1,-6],[1,-9],[1,-4],[0,-3],[-3,-11],[-1,-3],[1,-9],[1,-8],[1,-5],[4,-12],[2,-5],[5,-6],[4,-6],[1,-4],[2,-4],[2,-9],[2,-8],[1,-7],[2,-10],[2,-8],[3,-11],[2,-8],[1,-5]],[[5854,4712],[-5,-2],[-7,-2],[-8,-2],[-8,-3],[-8,-2],[-7,-3],[-7,-2],[-2,-1],[1,-6],[0,-6],[-2,-5],[-2,-6],[-1,-3],[-2,-4],[-2,-4],[-3,-5],[-3,-4],[0,-2],[4,-14],[2,-10],[1,-8],[0,-6],[0,-10],[-1,-12],[0,-5],[1,-9],[0,-7],[-3,-7],[0,-8],[-2,-10],[-2,-14],[-1,-8],[1,-4],[1,-4],[0,-4],[2,-7],[1,-3],[1,-2],[6,-8],[2,-4],[3,-8],[3,-5],[3,-2],[5,-2],[2,-1],[1,1],[1,1],[0,4],[0,3],[0,2],[2,2],[3,0],[2,2],[1,1],[0,-9],[0,-8],[0,-10],[0,-12],[0,-10],[0,-10],[0,-11],[0,-2],[0,-2],[-2,-1],[-2,2],[0,3],[-1,4],[0,2],[-2,1],[-2,-1],[-2,-4],[-4,-2],[-1,-2],[-3,0],[-3,2],[-2,3],[0,6],[-2,5],[-2,8],[-2,3],[-1,4],[-2,0],[-1,1],[-2,6],[-1,7],[0,2],[-1,4],[-2,2],[-3,3],[-5,3],[-6,5],[-3,0],[-3,1],[-2,3],[-1,1],[-1,7],[-2,8],[-5,9],[-1,10],[-1,2],[-2,-1],[-1,-1],[-1,-3],[-1,-9],[-1,-5],[0,-1],[-2,-1],[-1,-1],[-3,-1],[-4,0],[-4,2],[-3,1],[-7,1],[-2,1],[-2,2],[-2,2],[-7,4],[-3,0],[-1,3],[-2,1],[-1,3],[-1,4],[-1,9],[0,4],[1,6],[-1,1],[-1,0],[-2,-2],[-3,-1],[-6,-2],[-1,-1],[-3,-1],[-1,-1],[-4,-5],[-2,-1],[-2,2],[-2,3],[2,3],[0,4],[-1,7],[-1,3],[-4,2],[-1,1],[-1,4],[-1,3],[-2,1],[-1,1]],[[5362,4846],[-1,2],[-4,-1],[-2,-2],[-3,-5],[-5,-2],[-2,0],[-1,1],[-2,5],[-3,5],[0,3]],[[5363,4917],[0,2],[1,0],[1,-1],[0,-2],[2,-3],[2,-4],[2,-3],[1,-1],[2,2],[2,3],[3,2],[1,2],[0,4],[0,4],[0,5],[1,1],[1,0],[2,-1],[1,-2],[2,0],[1,2],[2,2],[2,1],[3,3],[2,3],[1,0],[2,-4],[1,-3],[0,-1],[-1,-4],[-1,-4],[1,-6],[0,-5],[0,-3],[1,-2],[1,0],[2,0],[2,-2],[2,1],[2,2],[4,8],[5,14],[5,9],[3,3],[2,5],[2,4],[2,4],[4,2],[3,3],[4,10],[4,17],[1,16],[1,9],[0,33],[-1,11],[1,5],[2,4],[4,9],[3,7],[2,8],[5,19],[1,6],[1,2],[3,5],[4,4],[4,4],[8,13],[6,13],[-1,16],[1,13],[3,16],[1,18],[-1,18],[1,15],[3,18],[1,6],[0,11],[0,17],[4,23],[4,14],[4,15],[2,10],[2,12],[-1,10]],[[5333,4896],[0,1],[-1,1],[-2,6],[-2,6],[-1,3],[0,1],[0,7],[-3,7],[-8,14],[-1,4],[-6,12]],[[5309,4958],[1,9],[2,4],[1,3],[6,7],[1,0],[4,-9],[1,-1],[2,0],[2,0],[0,2],[1,2],[-2,3],[0,2],[1,3],[1,4],[1,4],[0,2],[-1,2],[-3,3],[-2,3],[-1,3],[1,3],[1,3],[0,2],[-1,3],[-1,3],[-1,1],[-3,1],[1,4],[1,6],[0,4],[-1,12],[0,2],[1,1],[2,-1],[1,-2],[5,2],[1,1],[2,-2],[2,-2],[10,5],[0,4],[1,5],[0,3],[0,2],[-1,2],[0,3],[0,4],[1,1],[3,5],[1,-1],[3,-2],[2,-3],[2,-8],[1,-7],[2,-7],[5,-4],[6,-2],[2,1],[5,7],[2,5],[1,3],[1,-2],[2,-7],[1,-2],[0,-3],[0,-3],[0,-2],[3,-2],[3,2],[1,3],[2,3],[0,3],[-1,2],[0,3],[1,2],[1,6],[0,5],[1,2],[2,2],[1,2],[1,10],[0,4],[0,3],[1,4],[0,6],[-1,11],[0,7],[0,8],[1,10],[1,10],[0,3],[-2,3],[-2,3],[-4,2],[-2,4],[-1,4],[-1,1],[-4,2],[-2,2],[1,7],[0,9],[0,7],[1,5],[1,4],[2,4],[1,5],[1,2],[4,1],[1,2],[1,2],[1,3],[1,4],[1,4],[1,2],[-1,3],[-1,6],[-1,5],[-1,1],[-2,12],[-2,3],[-3,1],[-6,2],[-3,-3],[-6,-3],[-4,-3],[-3,-2],[-1,1],[-1,1],[1,2],[0,4],[0,5],[-1,4],[-1,7],[0,8],[1,7],[3,10],[0,4]],[[563,3960],[-1,0],[-1,0],[-1,1],[0,2],[1,0],[1,0],[1,-1],[0,-2]],[[2830,5330],[-1,-1],[-1,2],[-1,3],[1,2],[1,0],[1,-2],[0,-4]],[[3019,5867],[-1,-1],[-2,-1],[-3,-3],[-6,-3],[-6,-3],[-2,-4],[-6,-23],[-6,-5],[-2,-4],[-1,-4],[-3,-8],[-2,-6],[-3,-14],[-2,-17],[-1,-10],[-1,-13],[-2,-7],[-2,-7],[-2,-6],[-2,-7],[-2,-6],[0,-2],[1,-1],[4,1],[1,2],[2,2],[2,-1],[1,-6],[2,-1],[1,1],[2,-2],[2,-15],[1,-12],[4,-8],[3,-6],[1,-6],[1,-8],[0,-3],[-1,-3],[-2,-4],[0,-9],[0,-3],[-1,-9],[1,-5],[0,-4],[2,-2],[2,-1],[3,-2],[1,-7],[2,-8],[3,-4],[3,-3],[2,1],[5,2],[5,0],[6,-3],[3,0],[3,1],[6,4],[2,1],[2,0],[3,-3],[2,-2],[2,-2],[4,-1],[2,0],[2,0],[1,-1],[5,-13],[5,-12],[4,-10],[4,-11],[2,1],[1,-1],[2,-2],[2,1],[3,4],[4,1],[5,-3],[8,0],[9,3],[6,2],[2,3],[3,0],[5,-3],[2,-3],[0,-4],[1,-5],[-1,-6],[-2,-5],[-2,-7],[0,-9],[-2,-6],[-2,-5],[-1,-6],[0,-8],[0,-11],[-1,-15],[0,-10],[1,-3],[0,-4],[0,-5],[1,-5],[1,-7],[2,-13],[2,-5],[1,-2],[2,-3],[4,-13],[1,-2],[0,-3],[-1,-2],[0,-1],[-5,-8],[-9,-17],[0,-2],[0,-3],[2,2],[3,-2],[1,0],[1,-2],[1,-4],[1,-1],[1,-2],[3,-5],[2,-5],[2,-2],[1,-3],[0,-3],[0,-3],[1,-8],[1,-2],[0,-3],[0,-3],[1,-3],[1,-7],[2,-8],[0,-5],[1,-2],[0,-6],[2,-6],[-1,-4],[1,-4]],[[3056,4940],[-1,4],[-2,4],[-2,3],[-1,3],[-1,6],[-2,2],[-1,2],[-1,0],[-1,-2],[-2,-1],[-1,0],[-5,5],[-1,0],[3,10],[6,18],[3,12],[4,13],[2,6],[0,2],[0,1],[0,3],[-2,1],[-3,2],[-1,3],[-2,1],[-1,2],[-3,3],[-2,2],[-2,0],[-1,4],[-6,7],[-2,1],[-1,-1],[-3,-2],[-2,-3],[-3,-2],[-3,0],[-1,3],[-1,1],[-2,3],[-3,2],[-2,2],[-2,-1],[-2,-4],[-1,-3],[-2,-2],[-2,0],[-2,-3],[-2,-1],[-3,-1],[-2,-1],[-3,2],[-3,2],[-1,0],[-1,0],[-1,-2],[-3,-1],[-2,0],[-1,1],[-2,3],[-2,2],[-2,2],[-1,4],[0,3],[1,4],[0,4],[-1,7],[-1,3],[0,3],[-1,1],[-3,-1],[-2,3],[-2,2],[-1,3],[1,6],[-1,5],[-1,3],[-1,5],[-2,4],[-2,2],[-1,0],[-2,1],[-2,4],[-1,2],[-2,4],[-4,1],[-2,2],[-1,2],[-1,5],[0,2],[-1,3],[0,4],[-1,6],[-2,4],[-1,3],[-1,2],[-2,3],[-2,2],[-2,3],[-1,3],[0,2],[-1,0],[-2,0],[-1,1],[-2,2],[-1,2],[-2,4],[-2,0],[-1,0],[-2,-3]],[[2908,5178],[-5,4],[-4,5],[-4,2],[-3,3],[-3,6],[-1,4],[-1,2],[-6,5],[-1,1],[-2,-3],[-1,-1],[0,-5],[0,-2],[-2,-2],[-3,1],[-2,1],[-2,0],[0,-1],[-1,0],[-1,0],[-3,1],[-2,2],[-3,3],[-2,0],[-3,1],[-3,1],[-1,2],[-1,12],[-1,1],[-1,1],[-2,2],[-1,1],[-1,4],[-1,3],[-3,-1],[-6,5],[-4,4],[-4,4],[-5,9],[-2,2],[-3,3],[-1,4],[-3,4],[-1,2]],[[2809,5268],[-1,4],[-3,5],[1,8],[5,5],[6,-4],[1,9],[-2,7],[0,15],[1,3],[1,3],[2,3],[1,1],[3,-1],[1,2],[5,-1],[1,1],[1,2],[1,2],[2,3],[1,4],[1,2],[1,-1],[0,2],[1,2],[3,6],[0,2],[-1,5],[1,2],[1,1],[2,1],[1,5],[2,4],[1,6],[2,1],[1,7],[2,6],[5,19],[-2,0],[-1,-3],[-1,1],[-1,1],[0,9],[-1,1],[-2,-7],[-2,7],[0,4],[1,4],[-1,2],[-3,-2],[1,3],[1,3],[1,2],[2,3],[1,5],[0,6],[1,8],[-1,3],[-1,3],[0,14],[0,8],[-1,6],[0,6],[-4,7],[6,8],[2,6],[-3,12],[-3,11],[0,6],[1,-1],[1,0],[1,13],[0,5],[-2,6],[-3,0],[-2,9],[-1,1],[-1,6],[-3,10],[-3,5]],[[2836,5600],[2,12],[2,3],[0,3],[-1,7],[1,2],[0,1],[1,-1],[2,-3],[1,-4],[1,-2],[1,2],[5,8],[0,2],[0,5],[2,4],[2,2],[0,2],[0,4],[-2,8],[-2,5],[-1,5],[0,4],[-2,4],[0,4],[2,5],[0,1]],[[2850,5683],[1,-2],[3,-8],[3,-5],[4,-9],[2,-6],[1,-1],[1,-2],[-1,-2],[-1,-1],[0,-4],[1,-2],[1,-1],[2,1],[1,4],[-1,17],[-1,9],[-2,3],[-1,4],[1,2],[2,1],[3,4],[12,17],[4,15],[3,6],[3,4],[4,-1],[4,2],[1,5],[-1,7],[-2,4],[2,6],[1,9],[0,8],[1,5],[0,1],[-2,-3],[-2,-2],[1,3],[3,8],[2,11],[1,5],[5,7],[0,3],[4,5],[6,11],[2,3],[11,-7],[3,0],[-1,-1],[-1,-1],[-3,-1],[0,-5],[1,-4],[2,-1],[1,3],[2,8],[2,8],[1,10],[1,3],[3,1],[4,-2],[3,-2],[3,0],[10,1],[17,24],[7,6],[5,5],[3,9],[1,8],[2,3],[3,0],[1,2],[0,2],[6,6],[3,1],[3,0],[6,-6],[3,-10],[1,-6],[-4,-8],[-1,-3]],[[6216,4475],[2,-4],[-6,2],[-1,3],[0,2],[2,0],[3,-3]],[[6235,4488],[1,-8],[0,-6],[0,-2],[-2,1],[-2,5],[-4,5],[2,0],[1,0],[1,0],[1,3],[0,1],[1,2],[1,-1]],[[6207,4498],[-1,0],[-2,3],[-2,1],[-2,5],[1,18],[1,3],[0,1],[1,0],[2,-2],[-1,-12],[2,-8],[1,-6],[0,-3]],[[4324,6039],[-2,-2],[-1,1],[-2,3],[0,3],[0,3],[3,3],[2,-1],[1,-5],[-1,-5]],[[4356,6056],[-1,-1],[-1,3],[0,4],[0,1],[1,3],[2,0],[0,-3],[0,-6],[-1,-1]],[[4348,6048],[-1,-5],[-4,0],[-2,3],[-2,6],[0,5],[1,5],[0,4],[0,1],[1,-1],[0,-3],[4,-6],[1,-1],[2,-8]],[[4363,6119],[2,-1],[1,0],[2,0],[1,-3],[1,-3],[-1,-4],[-3,-3],[-2,0],[-2,3],[1,6],[0,5]],[[4330,6141],[2,-1],[0,-2],[-2,0],[-4,2],[-1,-1],[-1,-5],[-2,7],[0,3],[3,-1],[5,-2]],[[4364,6143],[-1,-3],[-1,5],[-1,1],[0,6],[2,2],[0,-6],[1,-5]],[[4308,6152],[-2,-1],[-1,0],[-2,2],[0,3],[2,2],[2,0],[1,-4],[0,-2]],[[4300,6160],[-2,-1],[-1,0],[-1,5],[0,3],[0,1],[6,6],[2,-1],[2,-5],[-1,-2],[-5,-6]],[[2676,5813],[1,-3],[1,-3],[0,-5],[4,-15],[3,-9],[6,-16],[2,-3],[5,-12],[1,-3],[1,-3],[5,-3],[1,-3]],[[2706,5735],[0,-1],[0,-1],[-1,-1],[-1,-1],[-2,3],[-2,2],[-1,-1],[-1,-3],[-1,-2],[-1,-1],[0,-1],[0,-11],[0,-11],[1,-1],[3,-3],[1,-3],[1,-2],[-1,-1],[-2,-2],[-2,-3],[-1,-4],[2,-6],[1,-4],[-1,-4],[0,-2],[-4,-5],[-1,-2],[1,-1],[2,-4],[1,-3],[0,-4],[1,-3]],[[2698,5649],[-2,6],[-3,6],[-2,4],[0,9],[-1,4],[-4,5],[-3,3],[-2,-1],[1,-5],[4,-6],[0,-3],[0,-3],[-2,0],[-2,2],[-3,0],[-2,2],[-3,8],[2,7],[1,4],[0,9],[-1,4],[-2,7],[-5,7],[-6,6],[-3,5],[-7,3],[-3,3],[-2,4],[0,4],[1,5],[-2,6],[-9,12],[-5,5],[-1,3],[-1,1],[1,-9],[2,-5],[6,-5],[1,-3],[1,-4],[-3,-7],[-2,-1],[-1,-4],[-1,-1],[-1,2],[-4,11],[-9,5],[-1,3],[-3,10],[-2,10],[1,6],[3,9],[1,4],[0,3],[0,4],[-1,2],[-4,4],[-2,2],[1,2],[4,4],[0,3],[0,1]],[[2618,5821],[1,0],[0,1],[0,1],[1,3],[1,2],[1,0],[2,-1],[4,-3],[6,-4],[7,-6],[3,4],[3,2],[2,0],[4,-3],[2,-1],[2,0],[2,-4],[2,-4],[0,-2],[1,-1],[2,-1],[5,-2],[3,1],[2,2],[2,3],[0,5]],[[2706,6426],[-2,-3],[-6,-4],[-3,0],[-3,1],[-2,4],[-1,4],[0,1],[2,-3],[2,-1],[1,1],[1,1],[-3,12],[0,2],[2,7],[7,-2],[1,-1],[1,-4],[1,-3],[2,-9],[0,-3]],[[2842,6448],[-1,-2],[-1,3],[-1,0],[-1,1],[-2,3],[-1,3],[2,0],[2,0],[4,-2],[0,-3],[-1,-3]],[[2836,6458],[-1,0],[-2,3],[-1,2],[1,2],[0,3],[1,-3],[2,-2],[1,-3],[-1,-2]],[[2832,6467],[0,-1],[-2,3],[-2,1],[-1,3],[-1,1],[-1,1],[2,1],[2,0],[1,-3],[1,-4],[1,-2]],[[2816,6483],[3,-1],[2,0],[1,0],[1,0],[2,-5],[-1,0],[-2,0],[-1,0],[-3,1],[-2,1],[-2,1],[0,2],[2,1]],[[2796,6489],[0,-1],[-5,4],[-2,4],[-1,1],[1,0],[6,-7],[1,-1]],[[2726,6518],[8,-3],[6,1],[2,2],[0,-2],[3,-4],[1,0],[4,2],[9,1],[1,-2],[2,-3],[3,-3],[2,-2],[3,0],[3,1],[2,-1],[4,-4],[1,0],[2,1],[0,-3],[4,-5],[4,-10],[3,-4],[2,-3],[3,-3],[2,-1],[8,1],[2,-1],[2,-1],[1,0],[1,0],[15,-15],[5,-8],[3,-4],[6,-6],[3,-1],[1,1],[0,1],[-2,3],[0,2],[2,-1],[4,-7],[2,-3],[2,-2],[2,-2],[-1,-2],[-2,0],[-3,1],[2,-5],[1,-3],[1,0],[2,3],[1,3],[5,-7],[2,-4],[0,-2],[0,-2],[2,2],[1,0],[1,-1],[2,-3],[2,-1],[3,0],[5,-3],[6,-5],[4,-1],[5,0],[3,-3],[1,-4],[-1,-3],[-1,-2],[2,-4],[-4,-1],[-1,-3],[0,-2],[1,-1],[3,1],[3,-1],[5,-1],[3,1],[7,-2],[3,-2],[4,-4],[2,-3],[4,-8],[3,-3],[4,-1],[1,1],[1,-1],[1,-1],[0,-4],[0,-4],[-2,-2],[-1,-3],[-4,0],[-6,-1],[-6,-3],[-3,-3],[-2,-1],[-3,-2],[0,1],[0,2],[-1,3],[-1,-3],[-1,-2],[-2,-1],[-7,-1],[-3,3],[-3,1],[-11,2],[-2,0],[-8,-2],[-7,-1],[-3,-1],[-3,-1],[-6,0],[-7,-2],[-7,-1],[4,13],[10,13],[2,3],[1,3],[0,3],[0,2],[-2,4],[-1,3],[-1,2],[-3,1],[-3,1],[-4,1],[-7,1],[-4,0],[-3,3],[-6,9],[-2,3],[-2,2],[-1,2],[-1,14],[-1,7],[-2,6],[-2,5],[-3,1],[-10,-4],[-2,1],[-3,1],[-15,9],[-6,5],[-3,3],[-2,3],[-2,6],[-3,5],[0,-2],[0,-1],[-13,-1],[-2,1],[-2,2],[-1,2],[0,4],[-1,3],[-1,-3],[0,-4],[-2,-2],[-2,0],[-3,5],[-10,0],[-1,1],[-3,5],[-3,5],[3,2],[6,3],[1,2],[1,2],[-1,3],[-1,2],[-1,2],[-2,1],[-1,0],[-24,1],[-1,-2],[-2,-4],[-4,-4],[-3,-5],[-1,-3],[-1,-2],[-3,-3],[-2,-4],[-3,-2],[-2,1],[-2,0],[-1,-1],[-1,-1],[-6,0],[-1,-1],[-1,-4],[-1,-6],[0,-2],[-3,-1],[-3,-2],[-6,-6],[-2,-1],[1,5],[-1,4],[-1,0],[-2,-1],[-2,-1],[-2,-3],[-2,-1],[-1,2],[0,2],[10,8],[1,0],[1,0],[2,0],[1,2],[-1,11],[0,7],[3,5],[4,9],[2,2],[22,18],[2,1],[14,3],[3,1],[6,5],[7,3],[7,-2]],[[3090,5878],[-2,0],[-5,5],[-4,9],[0,5],[1,-1],[1,-1],[2,-7],[5,-4],[2,-6]],[[2739,6298],[1,-1],[1,1],[1,1],[4,-1],[1,-2],[-4,0],[-1,-2],[-1,0],[-3,0],[0,6],[1,0],[0,-2]],[[2778,6319],[-1,0],[-2,-2],[-1,0],[1,1],[0,1],[1,0],[1,1],[1,0],[0,-1]],[[2782,6319],[-1,-1],[-1,1],[2,2],[1,1],[1,0],[1,0],[0,-1],[-3,-2]],[[5944,7204],[-1,-1],[-2,2],[-1,0],[-1,-1],[-1,-1],[-1,-1],[-1,0],[-1,-1],[-2,0],[-2,1],[-2,-2],[0,6],[-1,2],[-1,1],[-2,0],[-2,0],[-2,1],[-3,-2],[-2,-2],[-2,-1],[-2,0],[-2,1],[-2,2],[0,2]],[[5908,7210],[2,-1],[3,1],[1,6],[0,6],[6,-2],[5,-1],[4,0],[4,1],[13,7],[3,4],[2,2],[4,3],[4,2],[-2,-4],[-15,-17],[-1,-6],[1,-3],[2,-4]],[[5944,7204],[1,-2],[0,-3],[-3,-1],[-3,0],[-2,0],[-1,0],[-6,-9],[-2,-4],[-4,-2],[-3,-1],[-2,0],[-1,-1],[-1,-2],[0,-2],[-1,-2],[-2,0],[0,4],[-2,1],[-3,-1],[-1,1],[-6,3],[-1,1],[-1,3],[-3,10],[0,8],[2,-2],[2,2],[3,4],[2,1],[2,0]],[[5411,8113],[2,0],[3,2],[0,2],[0,5],[4,-1],[3,-2],[1,-4],[1,-3],[1,-2],[1,0],[2,-1],[5,-2],[2,-1],[3,-1],[2,-2],[1,-1],[1,-2],[1,-1],[2,1],[6,1],[2,-1],[1,-3],[1,0],[-1,-2],[-1,-2],[-2,-1],[-1,-2],[-1,-2],[0,-2],[2,-1],[1,0],[1,-1],[3,-6],[3,-7],[2,-1],[1,-1],[1,1],[2,3],[1,1],[2,1],[2,2],[0,2],[-2,5],[-1,4],[3,0],[5,-2],[7,-8],[2,0],[2,1],[3,1],[1,1],[1,0],[0,-4],[-1,-2],[-3,-2],[0,-1],[1,-2],[2,0],[1,-3],[2,-3],[1,-1],[1,-1],[3,2],[1,1],[0,1],[1,0],[1,-2],[0,-1],[3,-1],[2,-2],[1,-1],[1,1],[5,-2],[1,-1],[0,-2],[0,-2],[1,-3],[6,-9],[0,-4],[1,-1]],[[5523,8036],[-1,-1],[-2,0],[-2,-1],[-2,0],[-2,-1],[-1,-3],[-2,-1],[-1,-2],[0,-2],[-6,-4],[-1,-2],[0,-3],[-1,-3],[0,-3],[-1,-2],[-3,-1],[-1,-1],[-1,-2],[-1,-2],[-2,-2],[-4,-3],[-4,-1],[-5,1],[-3,1],[-2,-1],[-2,-4],[-2,-5],[-1,-5]],[[5383,7993],[-1,3],[-2,3],[-4,5],[-3,0],[-1,1],[-1,2],[-1,3],[-1,2],[-2,1],[-3,2],[-3,6],[-3,4],[-3,0],[-1,2],[-2,3],[-2,3],[-2,6],[-1,4],[-2,2],[-1,2],[0,2],[1,3],[1,2],[1,1],[0,2],[0,1],[-1,3],[-3,3],[-3,2],[-1,3],[-1,3],[0,2],[-2,2],[-1,3],[0,2],[1,1],[1,0],[1,-2],[1,-2],[2,-4],[0,2],[2,3],[2,5],[3,2],[2,1],[2,0],[2,2],[3,-1],[2,-1],[1,1],[0,2],[1,2],[5,1],[1,4],[1,0],[1,0],[1,2],[1,1],[1,-1],[1,-1],[1,1],[1,5],[1,0],[4,1],[6,3],[2,2],[3,1],[3,2],[5,2],[0,1],[-2,3],[-1,1],[-1,1],[1,2],[1,0],[2,0],[3,-1],[2,-1],[0,-2],[1,-2],[1,-1],[-1,-3],[2,-1],[1,-1],[2,0],[1,1],[0,1]],[[5394,8287],[-1,0],[-3,-1],[-4,1],[0,4],[0,3],[-1,2],[-1,2],[-1,1],[1,2],[5,-5],[5,-5]],[[5394,8291],[0,-2],[0,-2]],[[5313,8318],[-4,0],[-2,2],[-2,1],[1,3],[1,1],[5,-2],[1,-4],[0,-1]],[[5380,8316],[1,-4],[-1,-2],[-3,4],[-3,0],[-2,-6],[-1,0],[-5,5],[-1,2],[0,2],[1,6],[-1,2],[2,3],[0,3],[3,3],[2,0],[1,-2],[1,-2],[4,-3],[1,-1],[0,-1],[-2,-3],[0,-1],[0,-2],[3,-3]],[[5238,8335],[-1,-1],[-3,0],[-1,1],[0,2],[2,1],[1,0],[2,-1],[0,-2]],[[5270,8342],[0,-1],[4,-2],[2,-2],[2,-4],[0,-5],[-2,-4],[-2,-3],[7,1],[1,-2],[1,-2],[4,1],[11,-7],[6,4],[1,0],[2,-6],[-2,-5],[-5,-7],[1,-3],[2,-1],[5,1],[8,-4],[2,1],[6,9],[3,1],[9,2],[1,3],[4,3],[2,4],[6,7],[5,-1],[4,-2],[3,0],[4,-8],[8,-8],[8,1],[2,-8],[2,-9],[2,-3],[2,-2],[6,-2],[1,0]],[[5396,8279],[0,-2],[0,-4],[1,-4],[3,-16],[0,-4],[0,-1],[-1,-5],[-3,-5],[-2,-3],[-2,-2],[0,-3],[3,-6],[8,-8],[3,-7],[-2,-5],[0,-4],[0,-3],[1,-2],[2,-2],[1,-2],[0,-3],[0,-3],[1,-1],[0,-1],[-1,-2],[0,-5],[-1,-3],[-2,-4],[1,-3],[1,-4],[1,-3],[1,-2],[-1,-4],[0,-2],[6,-3],[0,-2],[1,-3],[2,-7],[-2,-9],[-1,-5],[-3,-8],[0,-1]],[[5211,7925],[-1,1],[-1,4],[0,5],[1,8],[1,6],[-1,3],[1,6],[3,7],[1,7],[1,8],[1,5],[3,4],[5,10],[1,1],[-1,5],[-1,0],[-2,2],[-6,2],[-5,1],[-2,1],[-3,4],[-1,0],[-2,-1],[-4,-1],[-2,0],[-1,0],[-1,0],[-1,3],[-1,1],[-2,1],[-1,0],[-1,-2],[-1,-1],[-1,0],[-4,8],[-1,2],[0,1],[-1,3],[-2,3],[-2,1],[-1,-1]],[[5176,8032],[0,4],[1,5],[0,2],[2,2],[1,2],[0,3],[0,2],[-2,1],[-3,1],[-2,2],[-1,3],[-2,3],[-1,4],[0,3],[0,2]],[[5166,8107],[2,9],[-2,2],[-1,2],[-2,0],[-1,2],[0,1],[0,1],[2,0],[1,1],[5,5],[0,1],[-1,0],[-1,1],[0,1],[0,1],[3,8],[1,3],[0,2],[0,2],[-2,4],[-1,3],[0,2],[-1,1],[-3,6],[0,3],[1,1],[3,2],[2,1],[3,-2],[2,-1],[2,2],[3,0],[6,3],[1,1],[0,2],[0,1],[-2,3],[0,1],[0,2],[1,1],[1,0],[2,2],[3,4],[1,3],[1,4],[0,3],[-1,2],[-1,1],[-1,0],[-3,0],[-2,2],[-1,2],[-1,1],[1,2],[0,1],[0,1],[0,2],[1,0],[7,0],[1,1],[0,6],[2,8],[2,5],[0,1],[0,11],[0,6]],[[5199,8253],[-1,2],[-3,3],[1,6],[1,5],[3,5],[2,2],[9,1],[11,-1],[4,-8],[-1,-5],[2,-2],[2,1],[0,4],[1,4],[1,1],[3,-3],[1,-2],[0,-7],[2,10],[-1,6],[0,7],[2,3],[1,2],[8,-2],[8,1],[3,-3],[8,-12],[2,-2],[3,-1],[-4,3],[-9,15],[-3,2],[-4,0],[-2,2],[-2,2],[0,2],[0,15],[-2,2],[-2,1],[-1,-1],[-2,0],[-1,4],[1,2],[5,2],[3,2],[0,4],[-2,3],[-2,6],[-3,6],[-1,6]],[[5240,8346],[6,0],[1,0],[8,-3],[2,-2],[2,0],[4,2],[4,0],[1,-1],[2,0]],[[5230,8339],[0,-1],[0,8],[3,9],[1,0],[-1,-2],[0,-2],[-1,-3],[0,-2],[7,-1],[-1,-1],[-7,-1],[-1,-4]],[[6201,5846],[-3,-8],[-3,-9],[-3,-12]],[[6192,5817],[-2,0],[-2,1],[-1,2],[-3,2],[-2,0],[-3,-2],[-4,-2],[-4,-1],[-3,-1],[-3,-2],[-2,1],[-3,1],[0,12],[0,13],[0,10],[0,6],[1,2],[4,8],[1,3],[4,13],[4,11],[3,8]],[[6177,5902],[0,1],[2,2],[6,-8],[1,0],[1,2],[2,9],[1,3],[1,0],[3,2],[3,3]],[[6197,5916],[0,-3],[5,-11],[2,-6],[1,-10],[-1,-6],[-1,-3],[-2,-4],[-6,-8],[-7,-5],[-4,-10],[-3,0],[0,-4],[1,0],[2,1],[4,3],[3,1],[4,0],[3,-1],[3,-4]],[[3297,6062],[-2,-1],[-1,10],[-2,7],[0,5],[1,1],[3,-3],[2,-3],[0,-9],[-1,-7]],[[5315,8345],[5,-3],[3,0],[3,-1],[0,-3],[0,-5],[-2,-1],[-3,0],[-3,-2],[-12,9],[0,7],[1,2],[5,1],[3,-4]],[[5291,8343],[-2,-1],[-2,2],[-4,4],[0,2],[2,-1],[2,-3],[2,0],[2,-2],[0,-1]],[[5348,8350],[-1,-1],[-4,1],[-5,-4],[-2,1],[1,2],[0,1],[2,1],[1,2],[0,2],[1,-1],[3,0],[2,-1],[1,-1],[1,-2]],[[5279,8345],[-3,-1],[-1,2],[-3,0],[-1,9],[0,1],[2,-1],[4,-4],[2,-5],[0,-1]],[[5298,8337],[-2,0],[-1,5],[0,1],[1,3],[2,4],[3,5],[2,6],[1,0],[-1,-6],[-4,-15],[-1,-3]],[[5419,8353],[-1,-1],[-5,2],[-6,4],[1,7],[2,4],[10,-9],[0,-3],[-1,-4]],[[5295,8387],[1,-3],[2,-7],[2,-7],[-1,-3],[1,-4],[-1,-4],[-4,-4],[-5,0],[-6,2],[-7,4],[-1,3],[-1,1],[-2,7],[0,9],[4,2],[8,4],[2,-1],[2,-2],[2,0],[4,3]],[[5351,8386],[-2,-2],[-1,0],[-1,3],[2,2],[0,2],[1,0],[1,-2],[0,-3]],[[5294,8397],[0,-1],[-2,1],[0,4],[0,3],[0,3],[0,2],[3,-5],[1,-2],[-1,-2],[-1,-3]],[[5349,8397],[0,-6],[-1,-2],[-1,-1],[-3,-1],[-2,-1],[-2,-3],[-1,-4],[1,-3],[4,-2],[0,-6],[-2,-3],[-7,-2],[0,-7],[0,-6],[0,-4],[-1,-5],[-5,-2],[-3,8],[0,3],[-1,4],[-1,3],[-1,5],[-5,2],[-2,0],[-2,-1],[-1,0],[-3,8],[0,8],[-1,4],[-1,1],[0,2],[-1,2],[-2,1],[-1,4],[2,1],[5,0],[2,0],[1,1],[4,7],[0,2],[0,2],[4,1],[2,-3],[0,-5],[0,-5],[3,-2],[1,0],[1,4],[1,2],[1,1],[0,4],[-1,3],[-1,1],[5,5],[5,4],[3,0],[3,-1],[2,-1],[2,-1],[1,-2],[-2,-4],[-1,-2],[2,-8]],[[5306,8481],[-1,-1],[-3,2],[1,3],[4,1],[3,0],[-3,-3],[-1,-2]],[[5240,8346],[0,5],[-1,3],[-1,5],[2,2],[0,10],[-1,5],[-8,5],[-6,5],[2,18],[0,4],[-2,9],[0,11],[1,16],[2,1],[2,0],[5,-3],[2,0],[2,-3],[1,-1],[2,3],[0,4],[4,7],[3,2],[2,1],[2,-2],[2,-3],[0,6],[2,12],[-4,1],[-4,-1],[-3,-8],[-3,-9],[-5,-1],[-3,-2],[-4,2],[-2,3],[0,3],[1,2],[4,8],[5,7],[5,0],[4,3],[2,0],[8,-1],[4,2],[3,3],[7,14],[4,6],[8,2],[8,7],[2,0],[-3,-5],[-1,-2],[0,-3],[2,-6],[0,-4],[0,-8],[-3,-4],[-2,-9],[-2,-1],[0,-10],[0,-3],[0,-9],[3,-4],[3,-2],[10,0],[1,-1],[1,-3],[-1,-5],[-1,-4],[-3,-3],[-3,-2],[-3,0],[-3,4],[-1,-1],[-2,-2],[-2,-12],[-2,-8],[0,-1],[-2,1],[-2,0],[-3,-2],[1,-1],[2,-3],[-1,-2],[-3,-2],[-2,-3],[-1,-2],[-3,-3],[-2,-4],[1,-4],[0,-4],[1,-5],[-1,-3],[-3,-6],[-2,-4],[3,0],[2,-1],[2,-1],[1,-2],[-1,-2],[1,-6]],[[3006,6223],[0,9],[1,4],[-1,4],[-3,5],[-2,5],[-1,5],[0,1],[3,0],[2,2],[2,5],[0,4],[0,3],[-1,4],[-1,3],[2,4],[2,5],[1,2],[0,1],[-3,6],[0,2],[1,5],[0,4],[-2,12],[0,2]],[[3006,6320],[1,1],[1,3],[1,3],[1,2],[2,1],[3,0],[5,-3],[1,0],[4,2],[4,2],[3,-2],[1,-2],[3,-3],[2,-1],[4,0],[1,0],[4,-6],[3,-2],[2,0],[3,2],[1,0],[2,-5],[1,-7],[1,-6],[2,-4],[12,2],[3,-3],[-1,-3],[-2,-1],[-5,0],[-3,0],[0,-3],[0,-2],[3,-1],[3,-1],[3,-2],[4,-1],[3,-1],[4,-1],[6,-5],[6,-11],[2,-3],[1,-3],[0,-4],[-3,-7],[-1,-3],[-2,-1],[-1,-3],[-1,-5],[-1,0],[-1,0],[-2,3],[-1,4],[-3,4],[-4,0],[-6,2],[-3,-1],[-3,0],[-4,1],[-3,0],[-4,-1],[-3,-3],[-2,-2],[-2,-3],[-1,-2],[-8,-2],[-2,3],[-3,4],[-3,0],[-4,-3],[-3,-1],[-1,-1],[-1,-2],[0,-5],[0,-3],[-5,-13],[-2,-9],[-2,-3],[-1,0],[-2,5],[-1,2],[-2,1],[-1,2],[0,4],[0,4],[-1,3],[-2,2]],[[5238,7311],[0,-3],[0,-3],[-2,-2],[-2,-2],[-2,-7],[-4,-5],[-1,-2],[1,-1],[2,-2],[1,-3],[0,-2],[-1,-11],[-1,-8],[0,-10],[0,-4],[1,-5],[1,-4],[0,-4],[-1,-10],[2,-6],[1,-6],[-3,-6],[-1,-6],[0,-9],[0,-6],[-2,-5],[-2,-4],[-2,-3],[-3,-3],[-3,-3],[-2,-9],[-6,-8],[-1,-2],[0,-6],[0,-9],[1,-6],[2,-10],[3,-11],[0,-5],[1,-2],[3,-4],[6,-4],[1,-2],[3,-8],[2,-13],[1,-9],[5,-7],[5,-6],[4,-6],[5,-6],[1,-2],[1,-13],[2,-13],[2,-14],[1,-14],[3,-17],[1,-10],[1,-11],[2,-14]],[[5264,6925],[-3,-3],[-3,-4],[2,-7],[5,-11],[2,-9],[1,-4],[2,-12],[2,-11],[0,-3],[1,-9],[-1,-23],[1,-30],[2,-15],[-3,-13],[-2,-13],[0,-6],[2,-10],[1,-8],[1,-4],[0,-12],[-1,-5],[-4,-6],[-6,-6],[-1,-6],[-1,-5],[1,-5],[4,-10],[5,-15],[6,-17],[1,-4],[0,-12],[3,-15],[2,-7],[1,-5],[2,-3],[2,-3],[1,0],[7,4],[12,-7],[11,-7],[1,-1],[2,-9],[4,-14],[3,-11],[3,-11]],[[5332,6538],[-14,-17],[-15,-18],[-14,-17],[-15,-18],[-14,-18],[-14,-17],[-15,-18],[-14,-17],[-10,-12],[-6,-10],[-7,-13],[-8,-13],[-5,-10],[-8,-13],[-3,-7],[-8,-14],[-3,-3],[-11,-4],[-10,-4],[-9,-4],[-6,-2],[-6,-3]],[[5117,6286],[-9,-3],[-6,-2],[-7,-3],[-1,0],[-1,-1],[-1,1],[-2,1],[-2,3],[-2,2],[0,3],[1,3],[1,4],[0,2],[1,2],[1,2],[0,2],[-1,3],[-1,5],[0,10],[0,3],[0,1],[-2,3],[-3,4],[-4,2],[-2,1],[-3,1],[-6,3],[-2,1],[-3,9],[-2,2],[-8,1],[-3,2],[-2,2],[-2,3],[-1,4],[0,4],[-1,2],[-9,9],[-2,3],[-1,3],[0,4],[0,5],[0,5],[-1,2],[-4,6],[-9,12],[-9,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-10,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-8,10],[-8,12]],[[4866,6624],[-7,8],[-6,8],[-7,8],[-4,6],[-5,6],[-6,6],[-5,7],[-5,6],[-5,6],[-5,7],[-6,6],[-5,6],[-5,7],[-5,6],[-6,7],[-5,6],[-5,6],[-5,7],[-5,6],[-6,6]],[[4758,6755],[0,12],[0,10]],[[4758,6777],[0,14],[0,12],[0,12],[0,9],[0,8],[0,4],[1,2],[3,3],[4,6],[2,3],[2,3],[7,9],[2,2],[7,10],[2,2],[4,1],[1,2],[2,4],[4,4],[2,2],[0,1],[1,0],[7,-1],[3,-1],[3,-1],[1,1],[1,1],[1,3],[1,4],[0,3],[0,2],[1,0],[1,0],[2,0],[4,0],[1,0],[5,1],[6,2],[5,3],[4,2],[4,6],[4,6],[3,10],[3,8],[5,5],[4,3],[3,1],[5,4],[5,6],[5,6],[3,1],[5,1],[1,1],[1,2],[0,4],[-1,3],[-2,1],[-1,2],[-1,0],[-1,2],[0,3],[1,3],[0,3],[0,5],[-1,4],[0,3],[0,3],[0,2],[2,2],[2,1],[2,-1],[5,1],[12,7],[1,3],[0,5],[1,4],[1,2],[1,0],[4,1],[5,2],[3,0],[6,0],[4,0],[7,-1],[5,0],[4,-1],[6,0],[1,1],[0,3],[-1,7],[1,3],[2,4],[3,4],[-1,5],[-2,3],[-4,4],[-1,1],[-3,5],[-1,5],[-2,12],[-2,6],[-1,8],[1,14],[-2,9],[0,4],[0,4],[0,8],[0,10],[-2,11],[1,4],[0,2],[0,2],[-2,3],[-1,3],[1,3],[1,4],[0,1],[-4,5],[-6,8],[-1,3],[-1,5]],[[4938,7206],[5,-1],[3,0],[7,5],[5,7],[4,4],[4,7],[3,5],[5,5],[14,11],[2,0],[4,-2],[4,1],[3,4],[3,9],[4,6],[6,5],[7,6],[5,5],[8,4],[20,3],[11,2],[7,0],[7,8],[3,3],[15,0],[7,6],[28,0],[3,-2],[3,-3],[6,-8],[3,-1],[3,1],[9,7],[9,4],[5,4],[2,7],[5,2],[2,-5],[10,-5],[6,2],[3,1],[-1,7],[6,-2],[5,-3],[5,-7],[3,-1],[6,3],[13,1]],[[2774,5013],[-1,-3],[-2,1],[-1,0],[0,3],[1,8],[0,3],[2,3],[2,2],[3,0],[2,-3],[-3,-6],[-1,0],[-1,-1],[-1,-7]],[[2488,5107],[-1,0],[-2,2],[2,4],[1,-1],[1,-1],[0,-2],[-1,-2]],[[2516,5131],[-3,-2],[-2,1],[0,1],[0,2],[1,3],[2,2],[2,4],[3,3],[1,-1],[0,-1],[0,-1],[-1,-3],[-1,-3],[-2,-5]],[[2490,5139],[-1,0],[-4,6],[0,5],[2,4],[5,2],[3,-4],[-1,-6],[-1,-5],[-2,-1],[-1,-1]],[[2460,5157],[-3,-1],[-2,2],[-1,3],[0,5],[0,1],[5,2],[2,-4],[0,-5],[-1,-3]],[[2484,5165],[-1,-2],[-6,2],[-1,3],[1,5],[1,2],[3,-2],[3,-5],[0,-3]],[[2464,5185],[2,-3],[1,-11],[6,-11],[0,-6],[0,-3],[0,-1],[3,-5],[2,-5],[-3,-10],[-7,-5],[-6,0],[-2,1],[-1,5],[-1,3],[1,4],[4,5],[5,5],[1,4],[-2,3],[-2,7],[-3,5],[-2,15],[-1,1],[-2,-2],[-1,2],[-1,1],[3,3],[0,3],[4,1],[1,-2],[1,-4]],[[2808,5256],[-2,0],[0,2],[1,3],[1,1],[0,-6]],[[2908,5178],[-1,-2],[-2,-1],[-2,0],[-3,2],[-1,0],[0,-2],[2,-3],[2,-3],[0,-4],[2,-5],[2,-5],[2,-3],[0,-2],[0,-4],[0,-3],[0,-14],[0,-1],[-1,0],[-1,0],[-1,2],[-1,1],[0,-3],[-1,-6],[-2,-14],[-1,-12],[-2,-5],[-3,-7],[-4,-9],[-6,-14],[-4,-6],[-3,-5],[-4,-6],[-5,-8],[-6,-4],[-8,-6],[-5,-4],[-4,-3],[-4,-3],[-6,-4],[-2,-4],[-4,-9],[-2,-4],[-1,-4],[0,-2],[0,-1],[1,-2],[0,-2],[-1,-1],[-1,0],[-1,1],[0,2],[-1,2],[-1,1],[-1,-1],[0,-2],[-1,-9],[0,-5],[-1,-2],[0,-4],[-1,-4],[-1,-3],[0,-3],[-1,-2],[-1,-3],[-1,-7],[-1,-5],[-1,-4],[0,-4],[1,-2],[0,-2],[-1,-3],[0,-3],[-2,-2],[-3,-4],[-1,-3],[-1,-3],[1,-3],[0,-2],[-2,-1],[-1,-2],[-1,-3],[-1,-2],[-3,2],[-2,0],[-2,2],[-2,5],[-1,4],[-2,6],[0,7],[-2,3],[-1,2],[-2,-1],[-3,0],[-1,2],[-3,3],[-3,4],[-2,1],[-2,-1],[-1,-2],[-2,-4],[-2,-2],[-1,0],[-2,2],[0,2],[1,3],[3,7],[-3,1],[-1,2],[0,3],[-1,2],[1,4],[1,2],[3,-2],[1,0],[1,3],[1,2],[1,1],[1,1],[-2,6],[0,2],[0,2],[0,3],[0,3],[0,2],[0,3],[-1,2],[0,1],[0,3],[-1,1],[-1,1]],[[2768,4989],[1,0],[4,3],[2,3],[2,3],[2,4],[1,4],[2,18],[3,11],[0,6],[-3,7],[0,11],[0,3],[0,3],[-2,-5],[1,-16],[-1,-7],[-2,-2],[-1,2],[0,11],[-1,-2],[-2,-8],[-3,-6],[-1,-2],[0,-2],[-3,2],[-2,3],[-7,13],[-4,3],[-2,4],[-1,2],[0,3],[2,2],[3,4],[0,8],[0,7],[-2,11],[1,14],[0,6],[-3,12],[2,6],[6,4],[2,3],[1,9],[2,6],[3,-2],[2,0],[-3,2],[-3,9],[0,4],[5,11],[2,3],[3,6],[2,10],[1,14],[-1,11],[-1,11],[2,3],[3,1],[3,4],[2,3],[3,0],[4,5],[7,2],[9,6],[2,5],[-1,10]],[[5949,6988],[1,-2],[1,-5]],[[5951,6981],[2,-12],[2,-10],[2,-13],[1,-5],[1,-4],[3,-14],[2,-12],[2,-10],[2,-14],[1,-5]],[[5969,6882],[-2,-3],[-3,-9],[-3,-30],[-5,-23],[0,-14],[-1,-6],[-2,-7],[-3,-7],[-5,4],[-8,12],[-4,12],[-5,8],[-5,10],[-1,8],[0,4],[-2,12],[-2,5],[-6,13],[-1,6],[-1,3],[-2,4],[-2,16],[-2,10],[-3,-3],[1,-4],[-2,-6],[-2,-7],[1,-5],[5,-9],[1,-3],[1,-8],[0,-11],[1,-4],[3,-8],[1,-5],[1,-4],[1,-4],[4,-7],[5,-13],[4,-10],[4,-4],[1,-4],[1,-12],[-1,-5],[3,-10],[1,-5],[3,-5],[2,-4],[1,-8],[2,-23],[2,-6],[8,-30],[7,-19],[3,-15],[5,-17],[9,-38],[6,-12],[2,-7],[4,-5],[4,-7],[-4,0],[-1,0],[-1,-1],[-1,-5],[0,-4],[0,-19],[1,-10],[4,-19],[3,-5],[1,-4],[2,-2],[9,-7],[5,-13],[11,-17],[2,-5],[0,-1]],[[6024,6451],[-10,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-10,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-5,0],[0,5],[1,3],[-1,3],[-1,1],[-2,-1],[-2,-11],[-2,0],[-3,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0]],[[5693,6451],[0,13],[0,13],[0,13],[0,12],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,12],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,2],[-1,9],[-2,11],[-1,14],[-1,4],[-2,14],[0,4],[0,3],[4,12],[2,6],[1,7],[0,5],[-1,9],[-2,8],[0,8],[0,8],[2,5],[3,5],[0,3],[2,3],[1,2]],[[5698,7007],[2,-7],[4,-1],[15,6],[15,-6],[9,-3],[13,-5],[8,-9],[3,-2],[5,1],[4,-6],[16,-3],[8,-6],[4,-5],[3,-1],[2,0],[4,2],[4,3],[4,5],[10,12],[3,3],[2,-1],[3,0],[1,4],[1,2],[1,3],[2,3],[5,1],[9,5],[-1,-3],[-9,-6],[4,0],[4,2],[5,1],[0,3],[1,4],[1,1],[3,-1],[9,-7],[2,0],[7,4],[1,1],[2,-3],[5,-9],[-2,0],[-5,8],[0,-4],[-3,-7],[4,-3],[3,-1],[1,-4],[1,-3],[3,1],[2,5],[-1,3],[-1,2],[1,0],[2,-2],[6,-9],[2,-2],[2,1],[5,2],[1,0],[7,3],[0,-2],[1,-3],[6,3],[8,0],[6,3],[8,7],[0,1]],[[6114,6088],[2,-3],[1,1],[0,2],[5,-4],[0,-3],[-3,0],[-3,1],[-3,0],[-3,1],[-1,5],[2,-2],[1,0],[0,1],[-1,3],[-2,1],[0,2],[1,1],[1,1],[-2,4],[3,-1],[1,-2],[1,-2],[0,-6]],[[6113,6110],[1,-5],[-3,2],[-1,1],[2,2],[0,1],[1,-1]],[[6072,6221],[8,-33],[4,-20],[3,-21],[2,-30],[2,-16],[3,-8],[3,-15],[2,0],[1,-4],[3,-14],[2,-5],[0,4],[0,3],[0,4],[0,6],[2,3],[3,-5],[2,-3],[0,-7],[1,-3],[3,-8],[3,-3],[4,0],[3,-2],[2,-3],[5,-8],[10,-7],[9,-22],[5,-15],[16,-23],[3,-10],[1,-11],[4,0],[5,-11],[2,-9],[5,-3],[1,5],[2,-5],[1,-6]],[[6177,5902],[-3,6],[-2,5],[-2,6],[-3,3],[-2,4],[-3,8],[-2,9],[-4,8],[-8,10],[-6,14],[-5,14],[-4,8],[-1,1],[-7,5],[-5,7],[-3,5],[-3,1],[-2,1],[-4,-1],[-4,3],[-2,0],[-2,1],[-2,1],[-3,-1],[-5,-3],[-2,1],[-1,3],[-1,3],[-1,2],[-2,0],[0,-2],[-5,-6],[-9,-3],[-2,0],[-2,2],[-4,11],[-1,1],[-1,0],[-2,2],[-2,2],[-2,4],[-1,2],[-2,-8],[-3,-14],[-2,-8],[-2,-10],[-1,-1],[-1,1],[-4,13],[-3,4],[-2,0],[-1,-2],[-1,-5],[-1,-2],[-1,-1],[-2,0],[-4,2],[-4,0],[-4,-3]],[[6014,6005],[-1,17],[-1,11],[0,11],[-1,11],[3,7],[1,7],[3,21],[2,4],[2,11],[0,3],[3,14],[0,10],[-1,9],[1,6],[2,4],[0,4],[0,9],[0,2],[2,1],[3,-2],[2,1],[3,0],[2,1],[1,2],[1,11],[1,2],[1,0],[2,2],[2,3],[2,2],[0,1],[2,0],[2,1],[1,2],[2,1],[2,-1],[1,2],[1,0],[1,0],[1,2],[0,1],[1,2],[2,2],[0,2],[1,2],[0,2],[1,2],[2,7],[3,4]],[[4503,6786],[-3,-10],[-3,4],[-1,1],[-1,2],[3,0],[4,5],[1,-2]],[[4572,6805],[0,-4],[0,-5],[0,-7],[-1,-3],[-4,-4],[-2,1],[-2,1],[-3,6],[0,6],[3,4],[1,5],[6,-1],[1,1],[0,1],[1,-1]],[[4522,6798],[-1,-1],[-1,2],[-2,4],[1,4],[1,1],[1,0],[3,-2],[0,-3],[1,-2],[-3,-3]],[[4546,6818],[-3,-13],[-2,-5],[-1,-2],[-3,-1],[-4,8],[-2,8],[-1,3],[2,2],[2,0],[6,2],[1,0],[5,9],[6,1],[0,-3],[-6,-9]],[[4605,6806],[-4,-6],[-3,1],[-1,1],[4,2],[3,5],[2,11],[4,12],[1,5],[1,2],[2,0],[1,0],[0,-3],[0,-6],[-1,-10],[-1,-9],[-8,-5]],[[4504,6825],[-1,0],[0,4],[-3,11],[2,5],[3,0],[2,-3],[0,-4],[-1,-2],[1,-4],[-1,-3],[-2,-4]],[[4619,6849],[-2,-4],[-2,2],[1,8],[1,2],[3,4],[4,1],[1,4],[1,2],[1,-2],[-1,-3],[-1,-8],[-2,-3],[-4,-3]],[[5044,7411],[-1,-1],[-2,1],[-2,0],[-1,3],[1,1],[0,2],[2,-3],[3,-1],[0,-2]],[[5040,7425],[-1,-3],[-5,1],[-1,2],[1,4],[2,0],[0,3],[1,3],[6,2],[1,-2],[1,-3],[-4,-6],[-1,-1]],[[5087,7476],[3,-2],[2,1],[2,0],[1,-1],[1,-4],[-2,-4],[-1,-4],[-2,-4],[-1,-6],[-3,-3],[-2,-2],[-5,4],[-3,1],[-1,2],[0,6],[-1,1],[-2,1],[-2,-1],[-2,-3],[-1,3],[-2,0],[-1,2],[0,2],[12,14],[3,3],[7,4],[1,-1],[-1,-2],[0,-1],[1,-1],[0,-1],[-1,-2],[0,-2]],[[5119,7479],[-1,-1],[-8,7],[-3,0],[-1,1],[0,4],[1,1],[5,1],[5,-2],[2,-7],[1,-1],[-1,-3]],[[4950,7684],[0,-2],[1,-3],[1,-1],[2,-1],[2,0],[3,-1],[1,-2],[0,-2],[0,-3],[-1,-2],[-1,-2],[1,-1],[1,-1],[1,-1],[0,1],[1,1],[1,2],[0,-1],[1,-1],[3,-2],[7,-4],[2,0],[2,-1],[1,-2],[4,-6],[1,0],[2,0],[2,0],[2,2],[1,-1],[1,-1],[2,-1],[2,-2],[1,-3],[1,0],[7,1],[2,-1],[1,0],[2,0],[4,-1],[3,1],[1,6],[0,2],[1,1],[2,-1],[7,-3],[2,-2],[3,-2],[2,0],[2,-1],[2,-6]],[[5047,7632],[4,-3],[2,-2],[1,-1],[1,-2],[1,-1],[2,2],[3,2],[4,-2],[6,-2],[2,0],[0,1],[1,2],[1,0],[1,1],[2,1],[2,1],[2,1],[2,-1],[3,-1],[2,0]],[[5089,7628],[0,-4],[2,-1],[0,-3],[-2,-2],[-2,0],[0,-6],[1,-1],[1,-2],[0,-1],[1,-8],[-3,-5],[-4,-5],[-19,-18],[-5,-8],[-2,-2],[-14,-5],[-10,-6],[-5,-2],[-6,-10],[-3,-4],[3,-1],[2,-5],[-1,-2],[-3,-3],[-2,-1],[-1,1],[-1,-1],[-6,-17],[-6,-12],[-3,-5],[-4,-8],[-7,-21],[0,-6],[4,-20],[2,-6],[3,-4],[5,-4],[1,-4],[-2,-3],[-5,-7],[-9,-8],[-4,-7],[-1,-7],[-2,-3],[-1,-9],[-2,-6],[0,-2],[-2,-5],[0,-3],[2,-5],[-1,-2],[-1,-1],[-4,0],[-10,-1],[-9,-10],[-4,-9],[-4,-16],[-5,-10],[-2,-2],[-4,5],[-4,0],[-4,-1],[-2,-4],[-3,-1],[-3,1],[-7,1],[-3,0],[-5,-3],[-4,2],[-7,1],[-15,-2],[-2,-1],[-2,-4],[-4,-7],[-8,-1],[-6,-4],[-2,-3],[-3,-8],[0,-6],[-1,0],[-1,1],[-1,0],[0,-4],[-3,-2],[-2,-1],[-5,3],[-4,6],[-2,0],[-4,9],[-1,5],[-2,6],[1,2],[-1,2],[-3,2],[-1,5],[3,7],[2,3],[1,1],[-3,0],[-2,-5],[-3,7],[-11,14],[1,3],[0,2],[-2,-4],[-1,-1],[-6,1],[-6,-2]],[[4794,7325],[-2,15],[-1,5],[0,4],[2,8],[2,3],[2,7],[3,6],[3,1],[1,1],[2,5],[0,3],[0,1],[-4,-1],[-6,16],[0,2],[1,4],[0,5],[0,4],[2,3],[3,3],[2,5],[1,4],[0,4],[-1,3],[-4,2],[-3,12],[-1,7],[-1,1],[-2,3],[-2,6],[-1,1],[2,1],[10,0],[2,2],[2,5],[2,8],[0,5],[-1,2],[-3,5],[0,1],[1,3],[2,2],[2,3],[1,2],[0,2],[-1,2],[0,2],[1,3],[0,7],[0,2],[0,8],[-1,5],[-2,8],[0,2],[1,1],[3,3],[3,6],[3,5],[5,4],[3,5],[1,3],[1,1],[0,2],[-1,2],[-2,2],[-2,2],[-3,0],[-1,0],[-1,2],[1,5],[-1,5],[0,2],[-1,2],[-3,-1],[-2,2],[-1,0],[-1,-1],[-5,0],[-2,1],[-1,1],[-1,-1],[0,-1],[0,-1],[-1,-2],[-1,-2],[-4,-2],[-3,0],[-3,2],[-1,1],[-1,1],[-6,-2],[0,1],[-2,-2],[-3,-2],[-2,0],[-1,1],[0,1],[-1,3],[0,2],[3,5],[-1,1],[-1,2],[0,2],[-1,2],[-1,0],[-2,-1],[-6,-3],[-1,-1],[-3,-3],[-2,-3]],[[4756,7600],[-2,-1],[-1,1],[0,9],[3,6],[2,4],[-1,0],[-2,0],[0,3],[1,2],[1,3],[-1,1],[-1,2],[0,5],[0,2],[0,3],[-5,-3],[-1,0],[0,4],[2,6],[1,2],[-4,1],[-2,3],[-1,2],[-2,4],[0,4],[2,8],[2,2],[2,1],[4,6],[6,-1],[3,1],[4,3],[1,0],[3,3],[0,3],[-1,3],[1,2],[3,3],[4,4],[4,0],[5,4],[3,-3],[2,1],[3,-2],[4,-6],[5,-3],[5,2],[8,1],[4,-1],[7,1],[4,0],[6,3],[5,-4],[10,-2],[6,-3],[16,-5],[6,0],[8,3],[3,2],[4,-1],[4,2],[3,0],[3,-3],[10,-5],[3,4],[2,1],[7,-3],[8,-5],[3,0],[6,1],[5,4],[1,0]],[[5628,8560],[2,-1],[1,0],[2,1],[4,-1],[9,-7],[1,-2],[-5,0],[-1,-3],[-2,-1],[-1,-1],[-3,-3],[-3,-2],[-1,-2],[-7,0],[-3,-1],[-3,-3],[-1,-7],[-2,-4],[-2,-2],[-3,0],[0,1],[0,2],[5,7],[1,2],[-3,1],[-1,3],[-5,3],[0,2],[1,0],[0,1],[2,2],[0,2],[-3,6],[1,1],[3,0],[2,-2],[2,2],[1,1],[2,-1],[2,4],[4,1],[2,2],[2,-1]],[[5648,8556],[-2,0],[-6,4],[1,2],[2,2],[5,-2],[0,-4],[0,-2]],[[5636,8572],[-2,-3],[-1,1],[-1,2],[-3,-7],[-3,-1],[-2,2],[0,2],[-2,6],[-3,2],[-4,0],[-3,3],[11,2],[2,3],[2,3],[2,0],[1,-1],[0,-2],[1,-1],[5,-1],[2,-5],[1,-4],[-3,-1]],[[5778,8610],[1,-2],[2,-3],[0,-1],[0,-1],[-2,-1],[-1,-1],[0,-2],[-3,0],[-1,-1],[-1,-5],[-3,-8],[-3,-6],[-3,-3],[-2,-3],[-1,-3],[0,-3],[3,-17],[0,-4],[-1,-3],[0,-3],[0,-3],[2,-5],[2,-7],[1,-4],[1,-2],[2,-1],[0,-1],[0,-1],[-1,-1],[-6,-2],[0,-2],[-1,-2],[-2,-4],[-1,-3],[-1,-3],[0,-2]],[[5759,8497],[-4,1],[-5,2],[-2,2],[-1,0],[-3,-1],[-8,-4],[-2,1],[-4,4],[-2,3],[-6,7],[0,2],[-1,1],[-5,2],[-2,3],[-2,0],[-2,1],[-7,6],[-1,0],[-1,-1],[0,-1],[0,-1],[-1,0],[-1,2],[-2,2],[-6,-3],[-2,-1],[-1,0],[-9,-5],[-3,-2],[-1,0]],[[5675,8517],[0,2],[4,12],[1,9],[1,1],[0,1],[0,3],[-4,2],[-2,-1],[-1,-3],[-1,-2],[-4,-1],[-3,2],[-6,3],[-2,4],[0,5],[-4,4],[-2,4],[1,4],[3,2],[1,2],[-4,0],[-1,0],[0,2],[-2,6],[2,2],[1,2],[-2,2],[1,2],[1,2],[-1,5],[4,3],[4,2],[8,1],[0,5],[3,0],[6,5],[5,-1],[8,4],[16,0],[2,2],[0,3],[0,2],[3,-1],[5,1],[18,-5],[5,0],[6,-5],[4,-1],[10,0],[15,-2],[3,3],[1,1]],[[6192,5817],[-1,-2],[-1,-3],[-1,-3],[-2,-4],[-3,-9],[0,-2],[1,-2],[1,-4],[2,-7],[1,-6],[0,-4],[2,-3],[3,-7],[2,-5],[3,-3],[1,-6],[2,-10],[3,-7],[2,-6],[3,-2],[1,0],[6,-11],[4,-8],[1,-2],[8,-5],[9,-6],[7,-5],[10,-6],[9,-7],[8,-6],[12,-8],[10,-7],[8,-5],[1,-2],[9,0],[10,0],[9,0]],[[6332,5644],[-7,-13],[-7,-16],[-9,-16],[-5,-11],[-8,-16],[-7,-14],[-7,-15],[-7,-14],[-8,-19],[-5,-12],[-9,-19],[-5,-12],[-1,-1],[-8,1],[-7,1],[-10,1],[-1,0],[-2,-1],[-2,-1],[-7,-4],[-1,0],[-6,-6],[-6,-6],[-3,-4],[-2,-7],[-1,-5],[-1,-2],[-2,-2],[-12,-5],[-4,0],[-5,-4],[-3,-6],[-1,-3]],[[6163,5413],[-4,0],[-7,-1],[-3,-1],[-2,0],[-3,0],[-2,1],[-1,2],[-2,4],[-4,7],[-3,5],[-7,-6],[-6,-5],[-8,-8],[-5,-5],[-1,-6],[-4,-10],[-3,-6],[-2,-1],[-7,1],[-3,1],[-4,2],[-6,2],[-4,2],[-5,0],[-6,1],[-4,2],[-4,6],[-5,6],[-5,7],[-5,8],[-7,8],[-6,9],[-2,1],[-1,0],[-7,0],[-8,1],[-5,0],[-2,1],[-1,2],[-2,7],[-2,5],[-2,6],[0,8],[0,9],[1,3],[0,3],[0,4],[-2,4],[-7,4],[-2,0],[-1,-2],[-1,-1],[-1,1],[-1,2],[0,2],[0,2]],[[5979,5500],[0,1],[-3,4],[-2,6],[-1,5],[-2,5],[-1,11],[-1,7],[-2,8],[-2,15],[-1,5],[-2,4],[-3,3],[-2,7],[-5,6],[-3,5],[-3,8],[-1,4],[-1,4],[-1,4],[-2,4],[-6,10],[-2,1],[-3,1],[-3,1],[-5,2],[-4,3],[-2,3],[0,2],[0,3],[2,5],[3,12],[2,8],[1,3],[3,0],[4,0],[3,0],[4,-1],[5,1],[1,3],[2,3],[0,2],[1,6],[0,4],[-1,17],[0,10],[0,11],[0,3]],[[5946,5729],[0,3],[1,12],[1,7],[1,4],[3,12],[0,4],[1,3],[-1,16],[1,8],[3,7],[2,3],[2,2],[1,0],[2,-4],[2,-3],[2,1],[1,2],[2,4],[0,5],[1,12],[0,6],[1,9],[1,11],[1,7],[1,4],[4,9],[3,11],[2,8],[4,14],[2,5],[2,2],[2,1],[5,2],[3,1],[1,2],[0,2],[0,6],[1,11],[1,10],[2,8],[1,3],[1,4],[1,6],[2,12],[0,9],[2,15]],[[5600,8646],[-2,-1],[-2,2],[1,1],[2,2],[1,-1],[1,-1],[-1,-2]],[[5606,8648],[-3,-2],[-1,0],[0,4],[2,1],[3,0],[-1,-3]],[[5615,8661],[4,-1],[1,0],[2,-3],[-3,-2],[0,-2],[1,-2],[1,-2],[-3,0],[-2,2],[0,2],[-2,2],[-1,1],[1,2],[0,2],[1,1]],[[5610,8659],[-2,0],[-2,3],[-1,1],[1,0],[0,3],[0,1],[2,-2],[1,-2],[-1,-1],[2,-2],[0,-1]],[[5595,8670],[0,-2],[-2,0],[-2,-1],[-1,3],[-1,4],[0,1],[1,1],[1,-2],[4,-4]],[[5589,8826],[0,-1],[2,1],[2,2],[2,-1],[-1,-3],[-1,0],[-1,-1],[-1,-1],[-1,-1],[-3,3],[-2,4],[4,0],[0,-1],[0,-1]],[[5690,8927],[-4,-2],[-4,1],[0,4],[2,2],[4,1],[5,-2],[1,-1],[-3,-1],[-1,-2]],[[5804,9159],[-2,0],[-6,-3],[-3,-2],[-4,-1],[1,-2],[7,-1],[1,0],[1,-1],[0,-2],[-1,-2],[-7,-14],[-1,-2],[3,-8],[3,-10],[11,-4],[8,-3],[5,-8],[8,-10],[4,-3],[0,-2],[-1,-7],[-5,-7],[-5,-5],[-5,-8],[-4,-6],[-5,-7],[0,-2],[0,-2],[1,-3],[5,-9],[2,-4],[3,-5],[2,-5],[1,-5],[3,-5],[1,-2],[2,-4],[3,-4],[1,-4],[4,-14],[1,-3],[-1,-3],[-1,-1],[-5,0],[-4,-2],[3,-4],[-3,-5],[0,-8],[-3,-4],[0,-1],[0,-1],[5,-2],[1,-1],[0,-2],[0,-2],[-3,-2],[-3,-2],[0,-2],[0,-2],[1,-3],[1,-4],[3,-3],[8,-2],[1,-2],[0,-2],[0,-3],[-4,-5],[0,-2],[2,-4],[2,-5],[8,-5],[2,-2],[1,-2],[0,-4],[0,-3],[0,-4],[-3,-4],[-5,-8],[-6,-3],[0,-1],[1,-3],[10,-10],[7,-5],[9,-7],[6,-6],[1,-3],[3,-5],[3,-3],[2,-3],[0,-2],[0,-2],[-2,-6],[-2,-5],[-3,-7],[-2,-5],[-7,-9],[-11,-12],[-2,-3],[-5,-6],[-8,-12],[-2,-3],[-7,-9],[-3,-3],[-2,-3],[-7,-9],[-7,-7],[-7,-6],[-2,-4],[-3,-2],[-3,-2],[-1,-2],[-8,-8],[-9,-12]],[[5772,8671],[-1,-1],[-3,-2],[-4,0],[-2,-2],[-6,5],[-1,0],[-3,-1],[-4,-3],[-6,-1],[-3,-1],[-2,-2],[-1,4],[1,4],[1,3],[0,2],[-1,0],[-2,-5],[-1,-4],[-2,-3],[-5,-1],[-4,4],[-3,0],[2,-3],[1,-3],[0,-2],[-3,1],[-3,-2],[-2,-3],[-1,0],[-2,4],[-3,-2],[-2,-2],[-6,-1],[-3,-3],[-5,-2],[-3,0],[-7,-3],[-3,-4],[-2,-1],[-2,1],[-9,-2],[-9,-2],[-3,0],[-4,1],[-4,-4],[-4,-4],[-4,-2],[-2,1],[2,2],[3,3],[2,3],[0,3],[-2,1],[-1,0],[-3,3],[-2,7],[-1,0],[-1,-2],[-1,-4],[0,-2],[-2,-1],[-1,-1],[-1,-1],[-6,0],[0,3],[0,1],[1,3],[-1,1],[1,2],[1,0],[1,1],[1,1],[0,1],[-2,1],[0,1],[2,4],[0,2],[-1,0],[-1,-1],[-7,2],[-9,6],[-2,0],[-2,5],[-2,-1],[-3,-3],[-3,3],[-2,1],[-1,2],[0,4],[0,4],[-1,5],[0,6],[0,6],[2,4],[1,2],[1,7],[0,7],[0,3],[0,1],[1,0],[0,2],[-1,0],[0,2],[0,1],[2,0],[0,1],[1,0],[-2,5],[0,2],[-2,6],[-3,6],[-3,4],[1,7],[2,7],[-1,3],[0,4],[-5,4],[0,6],[-1,6],[0,4],[1,3],[1,2],[7,10],[1,4],[5,1],[-2,4],[-1,2],[0,3],[7,2],[3,-1],[6,2],[5,3],[0,2],[-1,2],[-1,4],[1,1],[2,-1],[-1,2],[0,2],[3,-1],[3,5],[0,4],[7,2],[7,8],[3,2],[3,2],[7,8],[3,0],[1,6],[6,7],[2,1],[3,6],[7,8],[4,9],[3,4],[1,3],[2,1],[3,2],[5,2],[6,0],[2,-2],[2,1],[0,3],[-2,2],[1,2],[3,1],[0,3],[-1,2],[-2,3],[1,6],[0,6],[2,7],[-3,4],[-12,7],[-2,0],[-2,0],[-3,5],[1,5],[1,1],[-1,0],[-2,-2],[-4,-2],[-4,1],[-3,0]],[[5670,8974],[-3,11],[-1,4],[-2,5],[-5,2],[-1,2],[0,2],[0,3],[-1,4],[0,4],[1,2],[2,1],[2,5],[1,2],[0,5],[1,4],[2,2],[-1,2],[-1,2],[-2,3],[-3,4],[-2,4],[-1,3],[0,3],[0,3],[1,2],[2,3],[1,1],[-1,5],[-2,1],[-4,1],[-2,0],[0,1],[0,3],[1,2],[1,2],[0,1],[-1,5],[0,6],[0,4],[4,4],[0,1],[-4,3],[-4,5],[-1,2],[-4,0],[-2,7],[-3,4],[-4,3],[-2,1],[-11,4],[-5,1],[-6,2],[-4,4],[-3,2],[-3,2],[-4,2],[-1,2],[-5,4],[-2,2],[-7,5],[-1,2],[0,1],[0,1],[-8,3]],[[5572,9160],[2,2],[6,0],[5,-2],[1,1],[0,2],[-2,6],[1,1],[2,2],[3,2],[6,0],[3,0],[1,0],[6,-7],[4,-7],[3,-2],[6,-8],[2,-5],[1,-3],[2,0],[9,-1],[7,-2],[2,-1],[5,0],[4,2],[7,2],[2,2],[2,3],[4,-1],[4,-2],[5,-3],[5,-1],[6,-2],[2,-3],[4,0],[4,2],[3,8],[2,3],[3,2],[3,1],[3,1],[2,1],[3,5],[0,4],[0,9],[0,3],[2,5],[4,13],[1,4],[2,2],[2,1],[4,4],[6,8],[2,0],[4,1],[6,0],[4,-2],[1,0],[2,1],[4,2],[7,5],[4,1],[4,0],[5,-5],[6,-6],[4,-3],[10,-5],[10,-3],[5,-12],[-2,-4],[-2,-2],[-4,-4],[-5,-7],[-1,-3],[2,-3],[2,-3]],[[9850,3934],[-1,0],[0,1],[0,1],[1,-1],[0,-1]],[[36,3993],[-1,0],[0,1],[0,1],[1,-1],[0,-1]],[[41,4080],[-1,-1],[0,1],[-1,1],[0,1],[0,1],[1,0],[0,-1],[0,-1],[1,-1]],[[9957,4091],[0,-3],[-4,-1],[-1,2],[-1,0],[-2,-3],[0,-2],[0,-1],[-1,-1],[-4,-1],[-2,1],[1,2],[2,2],[1,0],[2,2],[1,3],[2,1],[2,1],[2,-1],[2,-1]],[[6,4093],[0,-2],[-1,0],[0,1],[-1,0],[0,-1],[0,-1],[0,-1],[0,1],[0,1],[0,2],[1,1],[1,-1]],[[34,4134],[0,-2],[-1,2],[-1,1],[2,1],[0,-2]],[[9981,4141],[-3,4],[0,2],[1,2],[1,1],[1,-2],[0,-5],[0,-2]],[[28,4148],[-1,0],[-1,1],[0,1],[0,2],[2,-2],[0,-2]],[[49,4150],[-2,-1],[-1,3],[1,2],[1,0],[0,-3],[1,-1]],[[9966,4163],[-1,-1],[-1,3],[1,4],[2,0],[0,-4],[-1,-2]],[[9951,4183],[0,-2],[1,-1],[1,-1],[2,-4],[3,-5],[2,-3],[0,-3],[-1,-3],[1,-5],[1,-5],[1,-9],[-2,-1],[-3,0],[-1,-2],[-1,1],[-2,-1],[-3,-3],[-2,-3],[-3,0],[-3,-1],[-3,0],[-2,2],[-4,3],[-5,1],[-2,2],[-1,3],[-2,6],[0,3],[0,3],[1,1],[2,1],[0,2],[0,2],[1,0],[0,1],[0,3],[0,3],[3,6],[3,4],[5,4],[4,0],[5,3],[2,2],[1,-1],[1,-3]],[[9983,4184],[-1,-2],[0,8],[1,0],[0,-1],[1,-2],[-1,-3]],[[29,4189],[-1,-2],[0,1],[0,3],[1,1],[-2,2],[0,1],[1,1],[1,-2],[1,-1],[0,-1],[0,-2],[-1,-1]],[[9922,4196],[-1,-1],[1,5],[0,1],[1,1],[1,0],[-1,-3],[-1,-3]],[[9999,4207],[-2,-2],[-1,2],[1,5],[-9997,5],[9999,-10]],[[0,4217],[3,5],[1,1],[1,-5],[-1,-5],[-3,-4],[-1,-2],[0,10]],[[9999,4231],[0,1],[-9999,2],[2,3],[1,0],[-1,-2],[0,-2],[-2,-2],[9999,0]],[[9999,4253],[-4,-8],[-2,-4],[-1,-4],[-4,-5],[-1,-6],[0,-7],[4,7],[4,5],[1,1],[1,0],[0,-2],[-1,-1],[0,-5],[1,-5],[-3,1],[-3,-1],[-3,-2],[-4,-1],[-1,0],[-1,1],[-1,1],[-1,3],[-3,0],[-4,-6],[-2,-5],[-1,0],[-2,1],[-2,-4],[-3,-1],[-1,3],[-1,4],[-1,3],[-3,1],[1,3],[1,2],[0,2],[1,2],[1,-1],[2,-1],[1,2],[2,0],[2,5],[2,3],[4,3],[3,2],[2,0],[2,1],[3,5],[3,3],[2,1],[2,1],[2,-1],[2,1],[-9995,3],[1,2],[1,0],[-1,-1],[-1,-1],[9999,0]],[[9919,4464],[-1,-1],[-2,0],[0,1],[0,1],[2,0],[1,0],[0,-1]],[[3342,2175],[-2,-1],[0,1],[-1,2],[0,3],[0,1],[1,0],[2,-3],[0,-3]],[[3376,2188],[1,-5],[-3,2],[0,2],[1,2],[1,0],[0,-1]],[[3305,2201],[2,-1],[2,1],[-1,-6],[-1,-3],[-3,0],[-2,4],[-1,2],[3,1],[1,2]],[[3325,2220],[4,-1],[4,4],[2,1],[2,-1],[2,-2],[2,0],[6,2],[1,0],[2,3],[2,-2],[1,-2],[0,-3],[-2,-2],[-1,-3],[-1,-2],[-3,-2],[-1,-3],[-4,-7],[-6,-10],[-2,0],[-4,-1],[-1,1],[-2,-1],[-1,-5],[-2,-3],[-1,-1],[-2,-1],[-1,-2],[-5,1],[-4,2],[-4,5],[6,7],[5,-1],[4,5],[3,2],[1,2],[1,2],[0,2],[-1,1],[-1,0],[-2,-1],[-3,-1],[-2,2],[1,1],[2,0],[5,2],[1,1],[-1,4],[-4,2],[-2,3],[-1,2],[1,2],[-2,4],[2,0],[2,-3],[4,-3]],[[3330,2223],[-4,0],[-1,2],[0,5],[3,1],[3,-2],[0,-2],[-1,-4]],[[3365,2231],[4,-4],[5,2],[3,-1],[1,-3],[-1,-3],[-1,1],[-2,-1],[0,-4],[1,-1],[6,-4],[1,0],[0,2],[-1,2],[0,3],[0,2],[2,1],[6,1],[2,-1],[3,-7],[-3,0],[-1,-3],[2,-2],[2,-1],[-1,-3],[0,-2],[-5,-2],[-4,-1],[-1,-3],[-4,-2],[-9,-5],[1,-3],[0,-2],[-1,-4],[-13,5],[-2,0],[4,-9],[-3,-2],[-2,1],[-3,-1],[-1,-6],[-4,4],[-3,6],[0,3],[3,6],[-1,3],[7,8],[2,3],[2,1],[2,1],[1,1],[0,2],[-1,3],[0,6],[6,8],[-1,5],[2,0]],[[6549,3955],[-4,-2],[-2,1],[-6,4],[-1,4],[-2,9],[0,3],[2,6],[4,2],[4,-1],[2,-1],[2,-7],[2,-7],[0,-8],[-1,-3]],[[6254,4436],[-1,0],[-1,1],[-1,4],[1,4],[0,2],[-1,5],[1,3],[1,-3],[1,0],[2,-3],[-1,-4],[0,-1],[-1,-4],[0,-4]],[[3483,5318],[1,1],[1,0],[1,4],[2,3],[5,14],[1,6],[0,3],[1,7],[-1,9],[0,2],[4,10],[1,5],[0,5],[1,4],[-1,1],[0,1],[-2,4],[0,4],[-3,4],[-1,3],[-3,9],[0,5],[-1,2],[0,2],[0,2],[-1,6],[-1,5],[0,3],[1,6],[-1,6],[0,3],[-1,5],[1,5],[0,2],[0,4],[3,10],[3,5],[2,4]],[[3495,5492],[2,4],[3,15],[2,5],[2,1],[11,-13],[5,-1],[10,-7],[4,-8],[9,-15],[4,-5],[0,-3],[-1,-6],[3,5],[5,-8],[1,-5],[1,-7],[0,-5],[-1,-3],[0,-2],[1,3],[1,2],[0,5],[2,7],[1,0],[1,-4],[3,-16],[0,-4],[1,-5],[0,-2],[0,-2]],[[3310,6019],[0,-4],[-1,0],[-1,2],[-5,0],[0,3],[0,1],[2,4],[-3,1],[-1,2],[-2,9],[0,2],[1,1],[2,1],[2,-3],[3,-4],[0,-1],[0,-3],[1,-3],[1,-1],[1,-7]],[[3299,6099],[-2,0],[-1,4],[2,2],[0,1],[1,-3],[1,-2],[-1,-2]],[[3289,6106],[-2,-3],[-1,1],[-2,5],[-1,14],[1,2],[0,1],[3,-2],[2,-2],[1,-1],[-1,-3],[1,-10],[-1,-2]],[[3296,6119],[-3,-1],[-2,1],[-1,4],[1,3],[0,4],[0,3],[1,2],[2,-3],[0,-3],[1,-3],[5,-6],[-4,-1]],[[5263,7649],[-1,-8],[1,-3],[1,-1],[0,-2],[1,-23],[0,-2],[-4,-9],[0,-2],[-1,-12],[0,-3],[-1,-3],[-2,-9],[-2,-4],[-5,5],[-3,2],[-2,3],[-1,1],[1,2],[1,3],[0,2],[-3,2],[-1,1],[0,3],[1,3],[-1,4],[-2,-1],[-1,1],[0,2],[1,2],[1,2],[0,3],[-1,2],[-2,2],[-1,4],[2,2],[1,1],[-1,4],[-1,0],[-1,1],[1,1],[1,3],[3,7],[2,3],[5,2],[2,1],[1,3],[1,1],[2,0],[2,-1],[0,-1],[1,1],[1,3],[-1,3],[1,7],[1,5],[1,0],[1,-3],[0,-2],[1,-5],[0,-3]],[[4967,7828],[-1,-5],[-2,4],[-3,4],[0,4],[0,1],[3,-3],[3,-5]],[[5160,8037],[1,-2],[2,-1],[1,0],[1,-2],[1,0],[2,0],[1,2],[2,1],[2,0],[1,-1],[2,-2]],[[5195,7829],[-3,-3],[-4,-3],[0,-2],[0,-3],[1,-1],[2,-3],[2,-5],[1,-4],[3,-5],[1,-1],[0,-1],[-1,-2],[-1,-6],[-1,-1],[-2,-1],[-3,-4],[-2,0],[-3,0],[-1,-1],[0,-3],[1,-3],[1,-3],[1,-3],[1,-2],[3,-1],[1,0],[1,-1],[1,-1],[1,-7],[-1,-1],[-1,-1],[-1,-2],[-2,-4],[0,-3],[1,-3],[0,-2],[-1,-2],[1,-4],[2,-3],[5,-4],[5,-4],[1,-1],[7,3],[1,0],[0,-3],[1,-2],[-1,-3],[-2,-4],[-2,-3],[-1,-3],[1,-2],[0,-3]],[[5208,7705],[-2,-1]],[[5206,7704],[-1,1],[-1,-1],[0,-1]],[[5204,7703],[-3,-2],[-2,-3],[-9,-12],[-4,-4],[-1,-2],[-1,-4],[-2,-4],[-2,-2],[-5,-1],[-6,-4],[-2,1],[-6,0],[-4,5],[-7,3],[-3,6],[-3,1],[-2,0],[-2,1],[0,2],[0,2],[-2,-1],[-2,0],[-1,-1],[-1,-1],[-1,1],[-1,0],[1,-2],[-3,0],[-2,1],[-6,3],[-1,1],[-4,1],[-2,2],[-1,3],[-1,1],[-1,1],[-4,-2],[-1,-3],[-2,-3],[-15,-15],[-3,-7],[-3,-9],[0,-5],[1,-14],[3,-8],[1,-1]],[[4950,7684],[4,2],[4,7],[4,26],[3,31],[2,6],[3,2],[-3,4],[-1,-2],[0,-2],[-1,-1],[1,28],[2,10],[1,11],[4,-4],[4,-4],[1,-4],[2,-13],[2,-3],[2,-2],[-1,3],[-1,2],[-3,17],[-1,5],[-3,4],[-8,8],[-1,2],[0,3],[3,0],[2,-2],[0,2],[-1,2],[-1,7],[-1,16],[0,3],[0,3],[-3,1],[-2,0],[-2,1],[-11,10],[-4,10],[-4,7],[-1,3],[0,3],[2,7],[-1,4],[-2,1],[-2,2],[2,4],[1,2],[2,1],[3,-1],[3,-2],[2,-1],[-6,6],[-11,-2],[-2,1],[-2,1],[-1,4],[2,2],[1,3],[-1,2],[-2,1],[-4,0],[-2,0],[-1,1],[2,4],[-2,1],[-2,-1],[-3,0],[-3,1],[-2,4],[-2,0],[-1,-1],[-2,2],[-2,0],[-1,0],[-2,2],[-11,5],[-5,1],[-4,-2],[-2,0],[-2,3],[-1,6],[-7,4],[1,2],[3,1],[4,2],[1,2],[-3,3],[-2,1],[-1,1],[-1,2],[2,1],[1,0],[2,-1],[5,1],[-2,3],[-2,0],[-1,1],[-3,0],[-2,-1],[-4,0],[0,3],[-1,2],[1,6],[6,4],[13,5],[5,0],[4,0],[5,4],[2,2],[7,2],[6,-3],[6,-11],[3,-4],[7,7],[10,0],[2,-4],[1,3],[2,4],[1,-2],[1,-2],[11,0],[1,1],[-3,3],[-2,6],[0,23],[-3,6],[-4,10],[-1,6],[-1,2],[1,4],[4,-1],[3,0],[7,2],[3,-2],[-1,-4],[1,-6],[1,-3],[2,-4],[5,1],[5,-2],[7,0],[10,-4],[4,2],[4,4],[8,3],[1,1],[-5,0],[-4,2],[0,3],[0,3],[2,6],[12,9],[8,3],[9,5],[5,5],[3,7],[1,1],[1,1],[-1,3],[0,25],[1,5],[2,4],[3,3],[4,3],[14,4],[3,2]],[[4813,8723],[1,-2],[-1,0],[-2,2],[-3,5],[-1,4],[0,2],[1,0],[0,-2],[3,-1],[1,-1],[0,-2],[1,-2],[0,-3]],[[4816,8744],[-1,-2],[-1,0],[-2,2],[-2,2],[-1,1],[-1,2],[1,0],[2,0],[3,-2],[1,-2],[1,-1]],[[4800,8763],[2,-2],[1,-2],[-1,-1],[-2,-1],[-2,1],[-3,1],[-2,4],[3,0],[3,1],[1,-1]],[[4815,8768],[0,-8],[-1,0],[-3,2],[-1,1],[0,-1],[0,-2],[3,-6],[0,-1],[0,-1],[-3,2],[-5,6],[-5,11],[6,2],[5,-3],[4,-2]],[[4822,8770],[-2,-4],[-2,0],[0,1],[-1,1],[1,3],[-1,4],[3,-3],[2,-2]],[[9526,5491],[1,-3],[-2,1],[0,1],[1,1]],[[9397,5576],[-2,-1],[-2,1],[-1,4],[0,1],[0,3],[1,2],[3,-2],[1,-3],[0,-2],[0,-3]],[[9212,5607],[-1,-1],[-1,0],[-1,1],[1,0],[0,1],[0,1],[1,0],[1,-1],[0,-1]],[[9218,5612],[-1,0],[0,1],[1,1],[1,-1],[-1,-1]],[[8836,5731],[-2,-5],[0,2],[1,3],[1,3],[1,2],[1,0],[0,-2],[0,-3],[-2,0]],[[5309,4958],[-3,5],[-2,10],[-3,6],[-6,9],[-1,7],[-7,15],[-10,16],[-6,13],[-1,3],[1,-1],[6,-6],[1,0],[1,2],[-3,3],[-3,3],[-2,2],[-3,0],[-1,2],[-1,5],[-1,3],[-1,4],[-3,8],[-1,3],[-2,4],[1,1],[4,-4],[0,1],[0,3],[-4,3],[-2,1],[-1,2],[1,3],[-3,12],[-3,8],[-1,4],[8,-18],[1,-1],[2,1],[3,2],[-1,2],[-1,3],[-1,-1],[-2,-1],[-1,2],[-1,1],[2,9],[-1,0],[0,-2],[-1,0],[-2,-1],[-4,5],[-3,13],[-1,3],[-1,4],[-1,2],[-4,19],[2,-2],[2,-5],[3,1],[1,3],[2,0],[1,1],[1,3],[5,13],[1,16],[0,10],[-1,10],[1,4],[1,-3],[0,-3],[1,-3],[1,-2],[3,-1],[5,-3],[2,-3],[0,5],[5,4],[-1,1],[-5,-1],[-6,6],[-2,4],[-2,7],[-2,4],[0,3],[4,3],[1,0],[1,-4],[1,-1],[1,0],[0,3],[0,9],[-2,12],[1,2]],[[5266,5243],[1,1],[1,2],[1,0],[2,0],[0,-3],[1,-2],[1,0],[2,-2],[1,1],[1,1],[1,1],[4,0],[4,0],[8,0],[7,-1],[8,0],[5,0],[0,7],[0,11],[0,13],[0,12],[0,11],[0,14]],[[4970,8103],[-2,-2],[-1,-2],[-1,-1],[-1,0],[-2,0],[-6,4],[-1,0],[1,2],[4,2],[2,2],[5,-2],[2,-3]],[[4883,8255],[1,-1],[3,0],[-1,-2],[-3,-3],[-2,-3],[-3,-2],[-1,3],[-2,0],[-2,5],[0,7],[3,2],[4,0],[3,-6]],[[4827,8299],[-3,1],[-1,-1],[-1,-1],[-1,0],[-3,-1],[-3,0],[-1,2],[1,5],[-1,1],[-2,0],[-1,1],[-2,4],[0,1],[-1,2],[-1,3],[-2,2],[-1,0],[-3,-3],[-2,-4],[1,-1],[1,-2],[-1,-2],[-3,-3],[-1,-1],[-1,-1],[-1,1],[-4,0],[-2,0],[-2,3],[-5,2],[0,3],[-1,1],[-6,7],[-1,2],[1,2],[2,2],[7,3],[1,1],[0,2],[-2,1],[-2,1],[0,1],[0,1],[1,1],[2,1],[2,-1],[1,1],[2,1],[2,1],[1,4],[2,3],[0,1],[1,6],[1,1],[4,4]],[[4799,8357],[1,-2],[2,-1],[2,2],[3,6],[1,1],[2,-1],[3,1],[7,3],[2,0],[4,-2],[3,0],[3,-4],[1,-7],[3,-6],[5,-6],[0,-3],[-2,-2],[-3,-2],[0,-3],[2,1],[2,1],[4,-1],[2,-2],[1,-4],[1,-3],[-1,-3],[-1,1],[-1,3],[-1,1],[-2,1],[1,-4],[-1,-6],[1,0],[2,-1],[-1,-5],[-3,-2],[-3,0],[-1,-2],[-1,-3],[-1,-4],[-3,-2],[-2,1],[-3,1]],[[4858,8378],[-4,0],[-1,0],[-2,1],[-1,8],[0,3],[1,1],[1,2],[2,0],[1,-1],[1,-2],[2,-5],[0,-5],[0,-2]],[[4829,8405],[1,-7],[1,-5],[0,-1],[-1,-2],[-4,-3],[-2,0],[1,3],[-1,4],[1,2],[-1,1],[0,-1],[-4,-4],[-1,0],[0,1],[1,3],[0,2],[0,2],[1,1],[1,1],[1,0],[1,-1],[3,3],[2,1]],[[4834,8399],[-1,-1],[-1,0],[-1,1],[0,2],[0,2],[1,2],[3,3],[-1,1],[0,1],[1,2],[3,4],[1,0],[1,0],[-2,-6],[-4,-11]],[[4839,8429],[-11,-3],[-4,0],[0,2],[1,1],[3,1],[1,8],[-5,3],[0,1],[0,2],[1,1],[3,1],[1,1],[1,-1],[2,-2],[2,-4],[3,-1],[2,-1],[0,-9]],[[4816,8443],[-2,0],[0,1],[3,3],[2,1],[-1,-3],[-2,-2]],[[4794,8465],[-3,-1],[-1,1],[1,2],[1,1],[2,-1],[0,-1],[0,-1]],[[4825,8465],[-1,-1],[-1,0],[-1,1],[-1,3],[3,2],[1,-1],[1,-2],[0,-1],[-1,-1]],[[4798,8474],[-1,-1],[-2,1],[-1,0],[0,4],[-1,2],[1,4],[0,5],[3,0],[1,-1],[0,-14]],[[4829,8496],[0,-3],[-1,-3],[1,-3],[0,-2],[1,-1],[1,-1],[5,-1],[5,0],[1,-1],[0,-1],[-1,-2],[-2,-3],[-4,-4],[-1,-1],[-1,-1],[-1,1],[0,8],[-4,-1],[-3,1],[-1,1],[-1,2],[-2,5],[-7,2],[-2,3],[0,1],[0,1],[1,2],[2,0],[1,0],[1,1],[0,1],[-1,2],[6,3],[1,3],[1,1],[2,-2],[2,-3],[1,-5]],[[4799,8506],[4,-3],[-3,-5],[-4,0],[-5,4],[0,2],[1,0],[1,1],[1,-1],[2,1],[2,0],[1,1]],[[4827,8545],[-3,-10],[-2,0],[-1,-2],[-4,-3],[4,0],[1,-1],[0,-2],[-1,-1],[-4,-5],[-3,-2],[-3,-4],[-2,0],[-1,-4],[-2,-1],[-1,1],[-2,3],[3,3],[1,1],[2,2],[0,1],[-4,2],[-2,2],[1,1],[1,1],[0,1],[-1,1],[-1,0],[0,1],[-1,2],[1,3],[1,1],[0,1],[1,1],[1,-1],[2,-2],[2,1],[3,-1],[0,1],[-2,5],[0,1],[1,1],[6,4],[7,6],[1,0],[1,0],[0,-3],[0,-5]],[[4913,8554],[0,-5],[0,-1],[-1,-2],[-2,-3],[-5,-5],[-10,-10],[-6,-6],[-1,-2],[-1,-4],[4,-1],[1,-1],[0,-2],[-6,-6],[-1,-6],[4,0],[3,1],[7,4],[6,3],[3,0],[6,-2],[1,0],[3,1],[2,0],[17,-1],[5,1],[3,-1],[3,-4],[2,-7],[0,-1],[-1,-3],[-3,-4],[-3,-5],[0,-3],[-1,-3],[-1,-3],[-4,-14],[-5,-8],[-2,-5],[-3,-4],[-2,-3],[-3,-2],[-7,-2],[-2,-1],[-3,-3],[-2,-1],[3,0],[3,2],[5,0],[7,-4],[-1,-4],[-2,-3],[-6,-1],[-6,-6],[-2,-2],[-3,-1],[-3,0],[-6,2],[-3,2],[3,-3],[2,-2],[16,-3],[1,0],[5,4],[6,0],[13,-7],[3,-6],[6,-8],[2,-3],[3,-2],[1,-5],[2,-13],[3,-14],[4,-14],[1,-4],[2,-3],[11,-7],[3,-2],[4,-6],[4,-7],[4,-5],[4,-4],[-2,-2],[-1,-4],[1,-4],[1,-5],[4,-7],[3,-7],[-1,1],[-1,0],[-2,0],[-2,1],[-2,2],[-3,3],[-5,-1],[-3,0],[-3,0],[5,-1],[5,-1],[12,-13],[4,-7],[2,-10],[-1,-5],[-3,-3],[-2,-3],[-2,-4],[6,-6],[2,1],[1,0],[1,2],[3,5],[1,2],[4,0],[3,0],[4,-1],[3,0],[6,-2],[3,-2],[8,-8],[1,-4],[1,-6],[0,-6],[-1,-6],[-2,-5],[-1,-7],[0,-2],[-1,-2],[-4,-5],[-3,-3],[-1,1],[-1,0],[0,-1],[1,-3],[0,-3],[-2,-2],[-3,-1],[-4,1],[-6,-5],[4,-2],[1,-2],[-1,-5],[-2,-2],[-3,-1],[-3,0],[-2,-1],[-3,-2],[3,1],[2,-1],[1,-3],[2,-1],[5,-2],[4,0],[6,1],[4,0],[1,-1],[0,-3],[-1,-7],[-1,-2],[-8,-6],[-2,-4],[-1,-3],[-5,1],[-2,-3],[-5,-2],[-3,-2],[-3,-3],[-3,0],[-11,3],[-7,-1],[-9,-2],[-3,0],[-3,3],[-4,1],[-4,1],[-4,2],[2,-4],[-5,-4],[-2,-1],[-2,0],[-5,-1],[-5,1],[1,-4],[1,-2],[-1,-1],[-1,-1],[-9,2],[-1,0],[-1,-2],[-3,1],[-3,3],[-4,2],[-3,1],[-3,0],[-11,-5],[-2,-5],[-1,-7],[-2,-6],[-3,-4],[-3,-1],[-3,3],[-5,4],[-2,2],[-1,0],[-1,0],[-2,-2],[-2,0],[-4,-1],[-6,-3],[-2,-2],[-6,-5],[-1,-2],[-2,-5],[-3,-1],[-2,3],[-3,2],[-4,-1],[-2,-2],[-1,1],[0,3],[3,4],[6,3],[6,7],[2,5],[2,2],[1,2],[2,0],[0,3],[8,11],[1,3],[0,5],[1,4],[6,3],[3,9],[1,1],[9,2],[6,-1],[7,-1],[3,0],[3,0],[3,3],[4,9],[3,4],[3,3],[3,4],[4,8],[-3,-3],[-4,-4],[-2,-2],[-6,-3],[-3,-2],[-5,-6],[-1,0],[-7,1],[-6,7],[-4,3],[-1,1],[-2,-1],[-3,-1],[-3,0],[2,3],[2,2],[-5,2],[-2,1],[-1,2],[-4,0],[-2,0],[-4,-3],[-5,-4],[-6,5],[-1,2],[0,4],[-1,3],[-2,1],[3,4],[2,3],[6,2],[9,7],[5,2],[4,5],[2,3],[2,4],[1,4],[2,4],[-2,1],[-1,3],[0,3],[1,2],[0,4],[-2,3],[0,3],[1,3],[-4,-1],[-3,0],[-4,-2],[-3,-3],[-3,-1],[0,3],[2,2],[3,4],[3,3],[1,3],[1,3],[2,2],[4,4],[9,5],[1,0],[3,0],[3,0],[3,2],[3,1],[6,-5],[-1,7],[2,2],[4,-7],[2,-1],[3,1],[-1,2],[-2,0],[-1,1],[-2,2],[-3,7],[1,4],[1,5],[2,4],[-1,1],[-2,1],[0,4],[0,4],[4,3],[1,5],[0,5],[0,2],[-4,0],[-1,-1],[-2,-2],[-1,0],[-5,6],[-2,5],[-5,9],[0,6],[3,12],[6,7],[6,3],[-1,1],[-10,0],[-3,-1],[-3,-3],[-2,-1],[-2,-1],[-1,-1],[-2,-3],[-1,-1],[-4,0],[-1,0],[-1,1],[-1,2],[-2,1],[-1,-1],[-3,-3],[-3,-1],[-4,2],[-4,3],[-1,-1],[-1,-3],[-1,-5],[-3,4],[-3,6],[-1,3],[0,4],[1,1],[2,-1],[3,9],[5,12],[1,4],[2,5],[-1,3],[-1,2],[-4,6],[0,5],[0,5],[1,3],[1,1],[6,0],[-2,1],[-5,5],[0,2],[1,4],[-1,-2],[-2,-5],[-2,-1],[-3,-1],[-1,-3],[0,-1],[-2,0],[0,-2],[-1,0],[0,2],[0,4],[0,4],[2,3],[5,7],[-3,-2],[-5,-7],[-3,-4],[-1,-1],[0,-1],[0,-1],[1,-8],[0,-3],[-5,-22],[-1,-2],[-1,-1],[-3,0],[-1,2],[0,1],[1,3],[2,11],[1,3],[1,2],[3,5],[-2,-1],[-1,1],[-1,1],[1,13],[1,5],[1,7],[1,5],[2,5],[1,5],[1,2],[1,4],[2,4],[1,4],[-10,-11],[-2,-2],[-4,0],[-2,2],[-2,2],[-1,5],[-3,0],[-2,1],[0,1],[3,2],[4,1],[4,4],[-3,3],[0,1],[3,3],[4,8],[1,7],[-2,4],[-1,2],[-3,3],[-1,3],[0,2],[2,2],[2,1],[2,1],[-2,2],[-1,2],[-1,2],[0,1],[1,7],[1,2],[2,4],[7,-1],[1,2],[1,0],[3,-1],[0,1],[-6,8],[-1,2],[2,4],[0,2],[0,2],[0,1],[2,1],[6,0],[1,1],[0,2],[-2,2],[0,3],[0,2],[1,4],[0,1],[1,3],[1,1],[2,0],[3,0],[1,-2],[2,-2],[1,0],[4,3],[1,0],[1,-3],[7,3],[9,1],[6,1],[6,1],[5,2],[6,-1],[0,-1],[0,-2],[-2,-4]],[[4918,8567],[-1,1],[-2,4],[3,1],[1,-1],[0,-1],[-1,-4]],[[4912,8570],[-2,-1],[-2,1],[-2,3],[-1,2],[0,2],[1,0],[3,0],[1,-3],[0,-2],[0,-1],[2,0],[0,-1]],[[4915,8584],[-1,-2],[2,0],[3,-1],[2,0],[2,-1],[-1,-3],[-1,-1],[-1,0],[-4,3],[-4,-2],[-1,1],[-1,1],[0,1],[0,2],[-1,0],[-1,-2],[-1,0],[0,1],[-1,2],[1,3],[1,4],[1,0],[3,0],[3,-2],[1,-2],[0,-1],[-1,-1]],[[4929,8595],[-3,0],[1,4],[2,1],[4,-1],[-1,-1],[-3,-3]],[[4924,8593],[-3,-2],[-1,2],[0,3],[-3,2],[-1,1],[-1,2],[2,1],[3,-3],[1,-3],[3,-1],[0,-2]],[[4963,8671],[1,-4],[1,1],[2,-4],[1,0],[2,1],[0,-3],[-2,-10],[-1,-2],[0,-3],[0,-1],[-1,-6],[-1,-2],[-1,-5],[-1,0],[-1,2],[1,7],[1,4],[0,3],[-1,2],[-3,0],[-2,-1],[0,1],[0,1],[-1,1],[-2,0],[-1,0],[-1,2],[0,1],[3,1],[2,0],[3,2],[-2,8],[-3,0],[0,1],[0,2],[2,0],[2,4],[2,1],[1,0],[0,-4]],[[4971,8669],[-1,0],[-3,5],[2,7],[3,0],[0,-2],[0,-1],[-2,-1],[1,-3],[0,-4],[0,-1]],[[4978,8686],[-1,-5],[0,-2],[-3,0],[0,1],[-1,3],[1,3],[1,1],[0,-1],[2,2],[1,-2]],[[6206,7552],[0,1],[0,1],[-1,2],[-1,0],[-2,0],[-2,1],[-2,2],[0,2],[1,1],[-1,1],[-3,3],[-4,6],[-2,2],[-1,4],[-1,1],[-2,0],[-2,0],[-1,-1],[-2,-6],[-1,-1],[-3,0],[-2,2],[-2,0],[-4,1],[-4,0],[-3,-4],[-1,1],[-2,1],[-4,2],[-2,1]],[[6152,7575],[6,11],[1,6],[0,4],[0,5],[-2,10],[-3,15],[-2,15],[-2,4],[-8,6],[-2,6],[-6,7],[-9,4],[-2,1],[-7,10],[-6,6]],[[6110,7685],[1,3],[2,4],[2,1],[5,-1],[5,-2],[4,1],[4,-3],[4,-3],[4,-3],[7,-2],[3,-4],[3,-3],[13,-2],[1,1],[1,0],[5,2],[4,-1],[4,-4],[2,1],[3,0],[4,-2],[3,-2],[0,-3],[2,-3],[7,-5],[6,-3],[2,-3],[5,-3],[0,-1],[0,-2],[-1,-2],[-1,-3],[1,-1],[2,-1],[3,0],[2,1],[2,1],[3,3],[4,2],[5,3],[2,0],[2,-1],[1,-1],[2,-6],[2,8],[1,1],[2,-2],[3,-2],[3,-1],[1,-2],[4,-7],[6,1],[3,-1],[1,-1],[1,-2],[-2,-6],[-1,-8],[0,-1],[3,-3],[3,-3],[2,-2],[1,-2],[3,-2],[3,-1],[1,0],[2,-1],[4,-4]],[[4930,8035],[-1,-4],[-3,1],[0,1],[3,2],[1,0]],[[4998,5824],[1,-3],[1,-2],[-1,-8],[-1,-5],[-1,-5],[0,-2],[1,-3],[3,-4],[1,-2],[2,-4],[2,-4],[3,-5],[1,0],[0,-2],[0,-2],[-1,-18],[0,-4],[0,-3],[0,-6],[-1,-1],[-1,0],[0,-2],[0,-1],[2,-1],[0,-1],[-2,-1],[-1,-2],[1,-2],[-1,-2],[0,-1],[1,-1],[1,0],[2,3],[1,0],[1,0],[2,-5],[0,-2],[-1,-8],[-1,-6],[0,-8],[1,-5],[0,-2],[-1,-3],[-2,-3],[0,-2],[1,-4],[2,-4],[4,-6],[2,-7],[0,-3],[-2,-3],[-1,-2],[0,-4],[0,-24],[-3,-11],[0,-2],[1,-4],[0,-2],[2,-1],[1,-2],[0,-7],[-1,-7],[0,-4],[0,-2],[-2,-1],[0,-3],[0,-2],[0,-3],[1,-2],[1,-4],[2,-8],[1,-1],[0,-2],[0,-2],[1,-4],[2,-3],[3,-4],[2,0],[0,-3],[2,-4],[1,-2],[1,-1],[1,0],[0,-3]],[[5032,5535],[-2,-3],[-1,-3],[-1,-5],[-2,-6],[-6,-2],[-2,0],[-11,-1],[-11,-10],[-6,-4],[-4,-7],[-5,-4],[-4,-5],[-7,-3],[-12,-8],[-4,-3],[-4,-6],[-6,-7],[-3,0],[-4,7],[-4,3],[-9,5],[-7,1],[-3,3],[-1,0]],[[4914,5479],[2,0]],[[4683,5898],[-1,-1],[0,-4],[-1,-4],[-1,-3],[0,-1],[2,-4],[4,-5],[1,-1],[1,1],[2,4],[2,5],[2,2],[2,0],[1,-3],[2,-7],[2,-6],[0,-1],[1,-1],[1,0],[1,2],[1,1],[0,2],[4,9],[2,2],[1,1],[2,1],[3,-2],[4,-3],[6,-5],[2,0],[1,0],[1,6],[2,2],[3,3],[2,2],[2,0],[0,1],[0,3],[0,2],[-1,4],[0,2],[0,1],[2,0],[3,0],[2,-2],[2,-3],[2,-3],[1,-7],[1,-7],[3,-10],[0,-7],[-1,-8],[2,-1],[1,-1],[1,-1],[1,-6],[1,-2],[2,0],[2,-4],[2,-1],[0,-2],[0,-1],[-1,-2],[-1,-1],[-1,-3],[-1,-3],[-3,-9],[0,-1],[0,-1],[1,0],[2,0],[2,3],[2,-1],[2,-2],[1,-3],[0,-3],[-1,-4],[0,-4],[1,-8],[1,-7],[1,-3],[6,-7],[1,-2],[0,-3],[0,-4]],[[4764,5619],[-1,2],[-1,2],[-1,3],[-1,1],[-1,0],[-1,-2],[-1,-3],[0,-4],[0,-2],[-1,-2],[-2,-4],[0,-4],[-1,-4],[-2,0],[0,1],[-1,-1],[-2,-2],[-2,-1],[0,2],[-1,2],[-1,3],[-2,3],[-2,2],[-1,-1],[-2,0],[0,1],[0,1],[1,4],[1,4],[0,4],[0,4],[0,5],[-2,4],[0,2],[0,4],[0,3],[0,2],[-1,3],[0,3],[-1,1],[0,5],[0,5],[-1,1],[-1,2],[-1,2],[-1,2],[-1,0],[0,-1],[-1,0],[-1,4],[0,1],[-1,-2],[-7,-5],[0,2],[-1,3],[-1,1],[-3,-2],[-1,0]],[[4714,5673],[-2,0],[-1,-1],[-3,-7],[-2,-2],[-1,0],[-1,1],[-1,-1],[-1,1],[0,2],[1,2],[1,7],[4,8],[0,1],[-2,5],[-1,6],[0,6],[0,5],[-3,1],[-1,1],[0,1],[1,4],[1,4],[0,2],[0,1],[-2,4],[-3,8],[-3,8],[-2,7],[-2,4],[-2,4],[-1,4],[-2,1],[-5,0],[-7,-1],[-5,0],[-1,-4],[-6,-2],[-4,3],[-4,-2],[-2,-2],[0,-4],[-1,-5],[-1,-2],[-1,-2],[0,-2],[-1,-2],[-1,-5],[-2,-6],[-2,-4],[-3,-3],[-2,-6],[0,-3],[-2,-2],[-1,-1],[-2,1],[-1,0],[-2,-1]],[[4630,5705],[0,2],[1,5],[-1,3],[-3,5],[0,3],[-1,3],[-3,7],[-4,0],[1,6],[0,8],[-1,4],[0,5],[0,-1],[-2,-3],[-1,1],[-4,5],[-2,5],[0,3],[-1,2],[-1,-1],[-2,0],[-7,7],[-5,17],[0,4],[0,7],[0,2],[-2,-5],[-1,3],[-1,7],[-1,4],[-2,2],[-1,1],[-1,-2],[-1,-8],[-1,0],[-2,2],[1,6]],[[4582,5814],[1,3],[1,5],[5,19],[2,4],[1,2],[2,0],[4,2],[4,5],[1,1],[4,0],[5,1],[6,4],[0,5],[0,8],[0,3],[-2,2],[-2,2],[-1,3],[-1,2],[0,2],[2,2],[1,1],[2,0],[1,1],[1,2],[0,5],[1,5],[-2,6],[0,5]],[[4618,5914],[9,-1],[1,0],[4,-1],[3,0],[1,-1],[1,-1],[0,-2],[-1,-2],[1,-3],[1,-1],[1,1],[1,2],[0,1],[2,-1],[2,-4],[2,-1],[3,-2],[2,-1],[3,0],[1,-2],[3,-1],[4,3],[3,1],[4,0],[3,-1],[6,3],[3,-1],[2,-1]],[[4534,5936],[0,5],[-2,11],[2,5],[3,3],[1,-2],[0,-5],[2,-3],[4,-2],[4,2],[2,-1],[0,2],[1,4],[4,1],[6,1],[5,2],[4,0],[1,1],[-4,1],[-8,-2],[-8,-1],[-6,-6],[-2,1],[-3,6],[-1,7]],[[4539,5966],[8,1],[8,0],[9,-1],[5,0],[2,8],[4,4],[5,1],[2,0],[3,-1],[4,-7],[3,-1],[3,-2],[2,-3],[2,-3],[3,-1],[1,0],[2,1],[2,1],[4,1],[4,-4],[0,-4],[0,-4],[-5,-2],[-6,-4],[-6,2],[-6,5],[-4,3],[-1,2],[-3,2],[-2,2],[-2,2],[-1,1],[-1,-2],[-1,-2],[-1,-4],[-1,-2],[-6,-1],[-4,-1],[-3,-1],[-2,-1],[0,-9],[-6,0],[-5,0],[-6,0],[-6,-1],[-1,-2],[-2,-3]],[[4558,5822],[0,-1],[-2,0],[0,1],[0,1],[1,5],[1,-1],[0,-1],[0,-4]],[[4552,5821],[-2,-1],[-1,3],[0,1],[1,1],[1,2],[1,1],[1,1],[1,-5],[-1,-2],[-1,-1]],[[4563,5830],[0,-3],[-1,1],[-1,1],[1,4],[1,2],[1,-1],[1,0],[-1,-2],[0,-1],[-1,-1]],[[4558,5844],[-1,-2],[-2,1],[-1,2],[1,3],[1,4],[1,-1],[1,-7]],[[4568,5848],[-1,-1],[-1,1],[2,5],[1,1],[0,-4],[-1,-1],[0,-1]],[[4555,5868],[-1,-7],[-2,1],[-1,4],[0,2],[3,0],[1,0]],[[4582,5814],[-2,4],[1,8],[-1,-1],[-2,-6],[-1,0],[0,7],[-1,1],[-2,-1],[-2,4],[0,3],[0,4],[1,2],[0,1],[-1,1],[-2,-1],[0,1],[1,5],[5,4],[2,1],[3,1],[-2,3],[-3,2],[-2,-1],[-1,-3],[-2,0],[-2,6],[0,3],[1,4],[1,2],[6,0],[2,2],[1,0],[1,2],[0,1],[-1,0],[-2,-2],[-7,1],[-2,-2],[-4,-5],[-5,-4],[-3,2],[1,7],[-1,1],[-1,2],[-5,-3],[-4,4],[-1,4],[0,5],[2,4],[0,2],[-2,0],[-3,-2],[-8,8]],[[4535,5895],[2,1],[4,-1],[3,1],[2,2],[2,3],[3,0],[9,-1],[7,3],[5,6],[5,5],[7,0],[7,0],[10,0],[8,0],[9,0]],[[5266,5243],[0,2],[-2,3],[-2,0],[-2,1],[2,9],[1,8],[3,7],[1,1],[0,3],[2,10],[3,8],[-1,8],[1,14]],[[5242,5400],[1,0],[4,0],[1,-3],[0,-4],[-4,-13],[-1,-6],[-2,-5],[-1,0],[-5,3],[-1,2],[0,2],[0,5],[1,2],[2,1],[1,0],[1,6],[0,5],[1,4],[2,1]],[[5662,7231],[2,-1],[2,0],[1,1],[2,3],[2,0],[1,-3],[-2,-2],[-1,-1],[1,0],[1,-2],[2,1],[0,-3],[1,-2],[1,-1],[1,-1],[2,1],[3,1],[3,1],[2,1],[8,-1],[3,-3],[5,-1],[5,-2],[3,2],[4,1],[1,-1],[-1,-9],[1,-2],[1,-1],[1,0],[2,3],[3,2],[4,0],[4,6],[1,0],[-1,-3],[-1,-6],[0,-4],[-1,-3],[-2,-1],[-3,0],[-6,0],[-6,-1],[-11,-3],[-12,-1],[-1,1],[0,4],[0,2],[-1,2],[-4,1],[-3,3],[-13,4],[-3,1],[-5,-1],[-2,0],[-1,2],[-1,2],[0,7],[0,7],[1,1],[1,-2],[1,-1],[1,2],[0,4],[1,3],[1,-2],[0,-4],[2,-1]],[[5754,7227],[-1,-4],[-1,3],[1,3],[-2,5],[3,8],[0,3],[2,2],[-1,-6],[-1,-5],[1,-4],[1,-5],[-2,0]],[[5640,7268],[0,-2],[-3,1],[-1,3],[0,6],[0,3],[1,0],[1,-3],[3,-4],[-1,-4]],[[5773,7253],[-2,-1],[-1,0],[-1,3],[1,6],[-1,4],[0,2],[2,3],[1,3],[3,4],[7,5],[2,0],[0,-3],[-3,-10],[-2,-4],[1,-4],[-4,-1],[-3,-7]],[[5707,7280],[-1,-3],[-2,1],[1,1],[0,2],[0,2],[0,1],[0,1],[2,-3],[0,-2]],[[5734,7291],[-2,-1],[-1,-3],[-2,2],[0,3],[2,-1],[1,1],[0,2],[1,-1],[1,-2]],[[5773,7289],[0,-1],[-2,3],[0,1],[2,2],[1,-1],[0,-2],[-1,-2]],[[5681,7301],[0,-3],[0,-1],[-6,-2],[1,4],[0,1],[2,-2],[1,1],[0,1],[2,1]],[[5704,7296],[0,-1],[-2,4],[-1,2],[1,2],[3,-4],[-1,-3]],[[5748,7299],[-1,0],[1,3],[3,4],[4,3],[2,0],[2,-2],[-4,-3],[-1,-2],[-4,0],[-2,-3]],[[5718,7303],[-3,-1],[0,1],[1,1],[1,1],[1,1],[2,2],[2,3],[1,-2],[-2,-1],[-3,-5]],[[5686,7310],[-1,3],[0,2],[0,1],[1,0],[1,-4],[-1,-2]],[[5750,7313],[-3,-1],[1,4],[-2,4],[3,-2],[1,-3],[1,0],[-1,-1],[0,-1]],[[5702,7319],[-3,-5],[-1,1],[-1,2],[1,4],[2,2],[2,0],[-1,-3],[1,-1]],[[5709,7313],[-2,-2],[-2,3],[-1,5],[4,7],[2,0],[0,-2],[0,-7],[-1,-4]],[[5681,7322],[-1,-1],[-2,2],[0,3],[2,1],[1,-1],[0,-1],[0,-3]],[[5678,7335],[-1,-2],[0,4],[-1,2],[1,2],[1,1],[1,-1],[0,-3],[-1,-3]],[[5692,7343],[0,-6],[-1,0],[0,1],[0,3],[0,3],[1,-1]],[[5705,7339],[-3,0],[1,4],[1,1],[3,-2],[0,-1],[-2,-2]],[[5722,7345],[-1,0],[1,3],[2,4],[4,0],[3,2],[-1,-3],[-3,-3],[-5,-3]],[[5701,7349],[-1,-3],[-2,0],[-3,4],[-1,2],[0,2],[1,0],[1,-2],[4,-1],[1,-2]],[[5676,7348],[-2,-3],[0,5],[1,4],[2,0],[0,-2],[-1,-4]],[[5745,7362],[3,-2],[1,0],[2,-1],[0,-3],[-2,-1],[-4,-3],[-1,1],[-2,3],[-3,0],[-1,1],[1,3],[3,2],[3,0]],[[5580,7361],[3,-5],[-3,1],[-2,-4],[-3,5],[-2,4],[-1,2],[2,4],[2,-4],[2,-1],[2,-2]],[[5694,7359],[-1,-4],[-2,4],[-3,3],[-1,3],[-1,2],[0,3],[1,2],[1,0],[2,-4],[3,-1],[-1,-3],[1,-3],[1,-2]],[[5654,7368],[-1,-1],[-2,0],[-1,0],[0,2],[1,0],[0,2],[1,1],[1,0],[0,-1],[1,-3]],[[5572,7395],[0,-7],[2,-1],[3,-6],[0,-3],[-1,-1],[-4,2],[-1,-1],[-1,1],[-1,3],[0,1],[-1,2],[0,1],[-2,-3],[-1,0],[0,2],[1,7],[1,1],[1,-2],[1,1],[1,3],[0,4],[1,1],[1,-5]],[[5576,7392],[-1,-1],[-2,5],[-1,4],[1,0],[1,0],[0,-1],[0,-2],[1,-1],[1,-2],[0,-2]],[[5724,7385],[-2,-3],[-3,5],[-1,1],[2,2],[1,3],[0,4],[-3,5],[-1,4],[5,1],[3,-3],[1,0],[0,-3],[0,-1],[0,-10],[-1,-1],[0,-3],[-1,-1]],[[5574,7408],[-1,-1],[-1,0],[-1,0],[-1,-1],[1,5],[0,5],[2,4],[1,1],[1,-2],[0,-10],[-1,-1]],[[5685,7419],[-3,-1],[-1,0],[1,2],[-3,4],[0,4],[1,1],[2,-2],[0,-4],[3,-4]],[[5650,7428],[1,-6],[2,-3],[3,-2],[1,0],[6,-5],[6,-1],[1,-1],[0,-4],[2,-2],[0,-2],[-1,-3],[1,-7],[2,-7],[2,-3],[3,-1],[3,0],[0,-1],[0,-6],[-1,-3],[-1,0],[-1,0],[-1,2],[-2,1],[-1,2],[-3,3],[-1,2],[0,3],[-1,3],[-1,4],[-1,1],[-1,2],[0,1],[-4,1],[-4,0],[-3,2],[-1,6],[-1,2],[-2,2],[-1,2],[-3,5],[-3,4],[-3,2],[-3,2],[-2,-2],[-2,0],[0,2],[3,2],[4,5],[4,2],[1,0],[3,-4]],[[5660,7437],[-1,-2],[-2,1],[-2,6],[5,-5]],[[5663,7439],[-1,0],[1,4],[2,3],[-1,-4],[-1,-3]],[[5733,7449],[0,-3],[3,-6],[2,-4],[0,-3],[0,-1],[-2,2],[-1,0],[1,-2],[1,-2],[-2,-1],[-3,0],[-6,3],[-1,3],[3,5],[1,2],[-2,-1],[-3,-5],[-5,2],[-1,2],[-1,2],[2,5],[3,0],[2,1],[2,1],[0,3],[5,0],[2,-3]],[[5557,7455],[1,-3],[-4,2],[-2,3],[-2,7],[-5,8],[0,2],[2,2],[4,1],[1,-1],[1,-1],[0,-2],[-2,-3],[0,-1],[1,-3],[0,-1],[1,-6],[1,-2],[2,-1],[1,-1]],[[5706,7487],[-1,-2],[-1,-4],[0,-4],[-2,0],[-1,1],[0,1],[0,3],[-1,0],[0,-3],[-1,-1],[-2,0],[-1,1],[0,4],[-1,3],[0,2],[5,0],[2,-3],[2,2],[0,2],[2,1],[0,-3]],[[5713,7512],[-3,-1],[-4,5],[4,1],[1,-1],[1,-2],[1,-2]],[[5688,7523],[-4,-2],[-4,4],[0,2],[2,5],[1,1],[3,0],[2,-3],[0,-2],[-1,-2],[1,-3]],[[5723,7530],[-1,2],[-4,4],[-10,3],[-5,3],[-2,-1],[-4,4],[-3,-2],[-6,-6],[-3,1],[-3,4],[-3,0],[-2,-2],[-4,-7],[-5,-4],[-3,2],[-5,0],[-1,-4],[1,-3],[3,-5],[-2,-4],[1,-3],[2,-1],[3,0],[5,-4],[2,-5],[2,-6],[-3,4],[-2,4],[-3,1],[-4,3],[-3,1],[-2,-2],[-1,-3],[3,-4],[3,-3],[1,-3],[1,-5],[0,-2],[-1,-1],[-3,3],[-5,12],[-7,2],[-1,-2],[1,-7],[1,-2],[6,-7],[0,-1],[-1,-1],[-7,4],[-2,6],[0,7],[-6,5],[-6,6],[-1,5],[1,2],[1,4],[-3,-1],[-2,-2],[-3,-3],[0,-4],[0,-3],[-1,-5],[-1,-9],[1,-5],[7,-14],[2,-10],[2,-3],[3,-5],[4,-7],[1,-4],[1,-7],[-3,-4],[-1,0],[-1,2],[1,4],[0,3],[-5,4],[-2,-1],[-2,-3],[1,-5],[2,-3],[0,-5],[3,0],[-4,-5],[-3,-3],[-4,0],[-2,0],[-1,-1],[2,-1],[2,-1],[2,-2],[7,-4],[3,-4],[3,0],[4,-8],[5,-2],[3,-8],[5,-2],[3,-3],[1,-2],[1,-5],[0,-11],[1,-8],[0,-2],[0,-4],[-1,-2],[-2,0],[-2,6],[-4,6],[-5,7],[-1,1],[-1,1],[-2,-3],[-6,-2],[-3,-2],[-1,-1],[-1,-1],[2,-2],[1,-3],[0,-5],[2,-5],[2,-2],[2,0],[1,-1],[1,-2],[1,-2],[1,-2],[0,-2],[-7,-3],[-1,-2],[-1,-1],[-2,2],[0,4],[-2,3],[-2,2],[-3,1],[-2,3],[-1,-3],[1,-8],[2,-6],[4,-16],[2,-9],[0,-5],[-1,-8],[2,-5],[2,-6],[-2,0],[-1,2],[-2,3],[-4,9],[-2,6],[-2,0],[-3,-1],[-3,-12],[0,-7],[-2,2],[-1,2],[0,8],[0,3],[-4,10],[-2,1],[-1,4],[-1,4],[-2,-1],[-2,-2],[0,-5],[0,-5],[-1,-4],[-5,7],[-4,13],[0,6],[3,7],[0,4],[-3,9],[-5,6],[-2,1],[-1,7],[-3,3],[-1,1],[-1,2],[1,2],[4,6],[3,10],[1,0],[3,-2],[3,1],[3,5],[2,3],[3,0],[8,-8],[9,-4],[4,-4],[3,-4],[1,0],[2,-1],[0,3],[-1,2],[2,2],[5,0],[1,1],[0,2],[-1,3],[-1,1],[-2,0],[-1,1],[-2,-1],[-2,2],[-2,2],[-1,1],[-4,3],[-5,6],[-1,-3],[-2,-2],[-2,0],[-7,3],[-5,-2],[-2,-1],[-2,0],[-2,-1],[-3,-1],[-2,5],[-1,4],[-1,1],[0,-4],[-1,-3],[-3,-2],[-2,3],[-2,7],[-1,8],[-4,7],[-2,2],[-1,4],[1,3],[3,1],[5,-3],[1,0],[1,2],[0,3],[-1,3],[-1,0],[-1,0],[-3,0],[-4,-1],[-2,1],[-1,2],[-3,5],[-3,6],[-5,4],[-3,13],[-2,5],[-3,4]],[[5582,7537],[4,0],[1,0],[5,1],[2,2],[2,0],[3,-2],[1,1],[4,3],[5,10],[1,1],[4,0],[2,1],[1,0],[5,-2],[2,0],[3,1],[4,3],[1,7],[0,1],[2,1],[2,0]],[[5731,7587],[2,-2],[2,-1],[0,-2],[2,-2],[1,0],[1,-5],[0,-7],[-1,-2],[-1,-1],[-6,-6],[0,-5],[0,-3],[0,-2],[0,-2],[0,-2],[0,-2],[-3,-4],[-1,-4],[-2,-4],[-1,-1],[-1,0]],[[3285,5876],[-1,-1],[0,3],[0,3],[1,5],[2,3],[1,-1],[0,-10],[-3,-2]],[[3714,8685],[-3,-7],[-3,1],[-2,3],[-3,2],[-3,-1],[0,2],[11,7],[5,2],[0,-3],[-1,-3],[-1,-3]],[[3971,8958],[-4,0],[-2,5],[1,5],[5,1],[2,-3],[-1,-5],[-1,-3]],[[3583,9190],[-5,-2],[-1,0],[-1,2],[-2,7],[0,3],[0,4],[-1,3],[4,4],[3,0],[5,-1],[7,-3],[-1,-1],[-1,-2],[-5,-2],[-1,-6],[0,-2],[0,-2],[-1,-2]],[[3535,9213],[9,-5],[10,-3],[1,-2],[1,-2],[0,-1],[0,-1],[-1,-1],[1,-2],[2,-1],[0,-2],[-2,-3],[-4,-4],[-18,-7],[-7,-1],[-16,-5],[-5,0],[-1,0],[-3,2],[-4,3],[-2,1],[-1,2],[0,2],[3,0],[5,0],[6,2],[-2,1],[-1,1],[-1,2],[-3,0],[-2,1],[-4,1],[-10,0],[-7,2],[-2,1],[-1,2],[-2,3],[2,11],[2,3],[3,1],[9,-3],[1,1],[-9,4],[-4,3],[-1,2],[0,2],[0,2],[0,2],[1,1],[2,2],[9,4],[10,-1],[18,-5],[2,0],[6,-4],[10,-11]],[[3564,9265],[-3,0],[-9,1],[-1,1],[0,1],[1,3],[4,1],[5,-2],[4,-3],[1,-1],[-2,-1]],[[4293,9269],[1,-4],[0,-1],[0,-2],[-1,-1],[-1,0],[3,-3],[0,-1],[1,-1],[-2,-3],[-11,-3],[-3,-1],[-4,-4],[-5,-3],[-1,0],[-2,3],[-7,3],[-14,-2],[-17,-3],[-5,-1],[-3,1],[-1,1],[0,1],[2,5],[0,1],[4,2],[3,4],[-1,4],[1,6],[2,1],[7,-2],[4,0],[7,-1],[10,1],[8,3],[14,7],[3,0],[2,-3],[1,-1],[4,-2],[1,-1]],[[3513,9276],[-3,-1],[-7,3],[-2,1],[0,2],[0,1],[2,3],[5,5],[3,0],[2,-2],[2,-4],[0,-2],[0,-2],[0,-2],[-1,-1],[-1,-1]],[[3471,9376],[-4,-3],[-3,-3],[-7,-6],[-1,-1],[-2,1],[-1,2],[-3,0],[-1,2],[-1,1],[-2,0],[-3,0],[-3,0],[-2,3],[4,2],[2,2],[9,1],[3,-1],[2,0],[2,0],[5,2],[1,1],[5,-1],[0,-2]],[[4500,9527],[2,-6],[1,-6],[3,-3],[8,0],[2,-6],[-5,-3],[-21,1],[-9,0],[-6,4],[0,7],[1,7],[6,4],[5,-3],[6,2],[7,2]],[[4483,9564],[-3,-2],[-11,24],[0,9],[1,6],[5,1],[4,-4],[2,-13],[2,-21]],[[3009,9638],[-10,-1],[-10,2],[-3,2],[0,3],[2,1],[5,1],[4,0],[3,-1],[7,-1],[5,-2],[3,0],[0,-3],[-6,-1]],[[4501,9656],[-6,0],[-2,1],[2,3],[7,9],[3,0],[3,-1],[2,-4],[-3,-4],[-6,-4]],[[4472,9675],[-4,-2],[-2,6],[-2,8],[-1,9],[6,5],[3,1],[2,-1],[-1,-4],[0,-8],[2,-6],[-3,-8]],[[4510,9782],[-11,-7],[-18,1],[-10,3],[-3,4],[4,5],[12,4],[16,3],[14,-2],[2,-5],[-6,-6]],[[4481,9898],[-3,-2],[-7,1],[-9,5],[-7,4],[0,5],[3,3],[5,0],[7,-4],[7,-6],[4,-6]],[[3753,9912],[-5,-1],[-12,6],[-19,6],[-16,4],[-15,11],[-2,3],[3,4],[13,0],[11,2],[27,-7],[14,-5],[5,-5],[-1,-9],[-3,-9]],[[4168,9997],[26,-3],[14,-4],[3,0],[19,-2],[19,-2],[30,-5],[4,-1],[-3,-2],[-8,-1],[-38,-1],[-70,-2],[-40,-4],[-13,-1],[-1,-5],[5,-1],[9,1],[32,6],[11,1],[22,-1],[29,-2],[11,1],[21,-1],[23,2],[29,4],[7,-8],[11,-9],[8,1],[7,0],[3,-3],[3,-1],[8,1],[25,-3],[17,-4],[6,-2],[3,-3],[2,-2],[-3,-3],[-10,-4],[-14,-5],[-18,-3],[-20,-3],[-159,-7],[-5,-2],[-4,-4],[3,-6],[7,-1],[17,4],[30,3],[22,0],[53,-3],[16,-7],[8,-10],[18,2],[4,2],[3,3],[2,3],[2,4],[2,2],[2,2],[4,1],[11,1],[27,1],[7,0],[5,-5],[1,-3],[0,-4],[0,-4],[-1,-6],[-2,-5],[-8,-10],[-6,-5],[-6,-3],[-13,-9],[-4,-2],[-14,-10],[-4,-5],[0,-3],[2,-1],[4,4],[2,2],[3,2],[20,6],[4,2],[14,8],[8,2],[7,3],[4,2],[21,15],[10,4],[12,0],[2,-7],[13,-1],[6,0],[9,-2],[4,-1],[7,-1],[8,-2],[6,2],[2,1],[6,6],[8,4],[8,6],[3,2],[4,1],[4,1],[11,2],[3,0],[7,0],[27,-1],[15,-1],[21,-4],[14,-2],[7,-2],[10,-4],[7,-5],[4,-1],[0,-1],[-3,-2],[-19,-7],[-7,-4],[-18,-9],[-9,-3],[-10,-1],[-11,0],[-7,-1],[-1,-1],[5,-4],[2,-2],[0,-2],[-5,-4],[-2,0],[-20,-3],[-9,-4],[-13,0],[-9,0],[-12,-4],[5,-4],[4,-1],[14,-4],[0,-2],[-7,-3],[-8,-5],[-11,-3],[-4,0],[-5,0],[-5,0],[-10,-1],[-9,0],[-18,2],[-9,2],[-5,1],[-6,0],[-3,-1],[-9,-6],[-5,-4],[-3,-4],[-1,-4],[0,-5],[1,-3],[2,-1],[2,-1],[4,-1],[9,1],[4,-1],[1,-1],[2,-3],[0,-2],[-2,-4],[-1,-5],[-1,-5],[0,-3],[4,0],[2,0],[2,-1],[2,-2],[1,-2],[2,-3],[-1,-2],[-2,-1],[-6,-2],[-12,-3],[-2,-1],[-1,-2],[0,-3],[-2,-3],[-2,-3],[-2,-1],[-5,-1],[-5,0],[-6,-1],[-14,-9],[-1,-1],[6,-2],[-1,-3],[-6,-10],[-2,-5],[-1,-7],[-3,-5],[-3,-5],[-3,-5],[-4,-7],[1,-4],[4,-4],[6,3],[7,9],[7,3],[8,-1],[7,-1],[9,-4],[8,-2],[6,-3],[3,-2],[3,-3],[0,-2],[-5,-2],[-2,1],[-12,5],[-5,2],[-8,-2],[-7,-2],[6,-10],[7,-5],[11,-2],[6,-2],[5,-3],[3,-1],[5,0],[6,3],[9,0],[4,-1],[3,-3],[1,-4],[0,-7],[-1,-6],[-1,-3],[-4,-5],[-2,-1],[-4,0],[-3,1],[-4,2],[-5,1],[-9,2],[-10,3],[-6,1],[-12,-1],[-12,-2],[-1,-2],[-18,-9],[-4,0],[-5,3],[-7,3],[-4,0],[-6,-4],[-1,-1],[0,-2],[4,-3],[2,0],[2,-1],[8,-1],[4,-1],[3,-10],[5,-6],[3,-1],[2,-1],[6,1],[8,2],[3,-2],[6,-2],[4,0],[4,0],[5,-1],[7,-6],[-3,-7],[4,-6],[7,-6],[2,-2],[0,-4],[0,-2],[1,-3],[1,-2],[1,-4],[1,-6],[-1,-5],[-1,-4],[-3,-3],[-4,-2],[-3,1],[-3,2],[-4,3],[-5,3],[-7,1],[-12,-9],[-5,-1],[-5,-1],[-4,-4],[-7,-2],[-6,1],[-10,5],[4,-3],[5,-4],[3,-2],[3,0],[3,0],[4,2],[8,4],[3,0],[2,0],[1,-1],[2,-4],[2,-6],[0,-4],[-3,-5],[-2,-2],[-2,-1],[0,-1],[5,-1],[7,5],[2,7],[3,7],[6,3],[6,-3],[6,-7],[7,-13],[3,-1],[4,-3],[2,-4],[-1,-5],[-1,-3],[-1,-2],[-1,-2],[-3,0],[-5,-1],[-11,1],[-6,0],[1,-4],[-12,-4],[-13,-2],[-13,3],[-10,5],[3,7],[2,7],[-5,5],[-1,0],[2,-8],[-2,-2],[-5,-4],[-4,-1],[-1,-1],[2,-1],[1,-2],[1,-2],[-1,-2],[-2,-3],[-1,-2],[0,-1],[2,-2],[4,-2],[4,-2],[19,0],[8,-1],[18,-6],[1,-1],[-3,-10],[-2,-9],[-4,-2],[-19,0],[-6,-2],[-9,-4],[-9,-5],[-4,0],[-18,4],[-7,3],[-14,9],[-11,13],[-6,-6],[-3,-2],[-3,-2],[-3,0],[-3,1],[-3,2],[-6,5],[-7,4],[-4,3],[-1,-1],[3,-3],[4,-3],[11,-9],[3,-2],[0,-2],[-7,-2],[-8,-3],[-3,-2],[-6,-6],[-2,-1],[-9,-1],[-3,0],[-7,4],[-10,2],[-6,1],[-8,4],[3,-4],[16,-5],[1,-2],[-3,-3],[-2,-2],[-4,0],[-5,1],[-6,0],[-6,-1],[-2,-2],[1,-1],[1,-1],[2,-2],[2,0],[4,4],[4,0],[8,-1],[9,3],[7,2],[5,0],[17,4],[4,5],[6,2],[13,2],[12,-1],[7,-1],[5,-4],[7,-4],[6,-3],[7,-2],[4,-5],[11,-5],[7,-2],[4,-2],[1,-12],[0,-5],[-2,-13],[-5,-3],[1,-7],[-2,-6],[-5,2],[-6,4],[-14,6],[-13,3],[-5,4],[-6,3],[-8,10],[-5,14],[-3,7],[-4,0],[-6,-2],[-5,-2],[-2,-3],[-17,-4],[-6,-3],[-3,0],[-13,-5],[5,-2],[2,0],[6,1],[3,1],[11,5],[9,1],[4,1],[7,3],[4,1],[1,-1],[0,-1],[4,-17],[-2,-4],[-3,-2],[-8,-3],[-3,-1],[3,-3],[7,2],[5,3],[3,-1],[4,-4],[5,-2],[13,-7],[5,-3],[9,-3],[9,-5],[2,-2],[9,-2],[2,-1],[3,-8],[3,-1],[9,-1],[-2,-3],[-8,-7],[-4,-2],[-2,-2],[1,-2],[0,-5],[2,-7],[2,7],[1,3],[2,1],[2,0],[6,4],[5,-2],[2,-8],[1,-8],[-1,-6],[1,-11],[-1,-3],[2,-3],[1,-12],[2,-4],[-3,-3],[-9,-2],[-3,2],[-9,-1],[0,3],[-1,4],[0,2],[0,2],[-1,12],[-2,-3],[0,-2],[-1,-3],[-1,-13],[-3,-3],[-7,1],[-7,-1],[-3,1],[-13,6],[-5,5],[-5,8],[-2,8],[-1,7],[-4,6],[-5,4],[-6,4],[-7,3],[-6,3],[-5,4],[-6,4],[-6,2],[-10,1],[-13,0],[-9,3],[-2,-1],[-2,-1],[2,-4],[10,-2],[8,0],[10,0],[7,-1],[2,-2],[2,-4],[1,-6],[-2,-5],[-8,-5],[-4,-3],[-12,-5],[-4,-1],[-9,0],[-8,1],[-10,2],[-5,0],[-12,1],[-2,-1],[3,-3],[5,-1],[3,-2],[0,-3],[-1,-5],[-1,-3],[-2,-3],[-8,-4],[-3,-2],[-14,-5],[-1,-1],[3,0],[9,2],[3,0],[14,-4],[12,0],[24,4],[2,0],[1,-1],[2,-1],[1,-2],[-2,-3],[-5,-2],[-8,-2],[-4,-2],[-4,-2],[-6,-5],[-2,-6],[7,-2],[3,3],[4,6],[3,3],[7,3],[10,-2],[7,2],[15,6],[2,0],[22,-3],[20,-7],[10,-2],[14,-2],[25,1],[2,-1],[-1,-2],[-2,-2],[-4,-3],[-5,-2],[-3,0],[-2,-2],[-6,-1],[-2,-1],[2,-5],[-1,0],[-5,0],[-9,-3],[-7,0],[-1,0],[1,-2],[1,-2],[2,-3],[-1,-2],[-3,-1],[-3,-1],[-8,2],[-1,0],[1,-2],[1,-2],[0,-2],[-2,-3],[-5,-1],[-8,-6],[-3,-1],[-8,-1],[-1,-1],[3,-4],[0,-1],[-5,-5],[-8,-2],[-1,-2],[-1,-4],[0,-1],[-2,-2],[-7,-4],[-5,-3],[-3,-1],[-3,-3],[-4,-2],[-5,0],[-4,-1],[-8,-3],[-5,-1],[-16,-5],[-8,-1],[-6,-2],[-14,-5],[-6,-1],[-5,-2],[-5,-1],[-8,1],[-4,0],[-3,0],[-2,-2],[-4,-4],[-4,0],[-11,3],[0,-2],[3,-3],[0,-3],[-6,-2],[-4,-1],[-5,1],[-7,3],[-9,6],[-11,9],[-5,3],[0,-3],[1,-3],[2,-3],[1,-2],[-2,-1],[-1,-1],[-2,0],[3,-4],[2,-5],[0,-4],[-3,-4],[-3,-2],[-2,-1],[-13,-10],[-3,-1],[-2,-1],[-1,-2],[-4,-8],[-2,-3],[-3,-3],[-1,0],[0,-2],[0,-2],[-1,-3],[-2,-5],[-8,-13],[-6,-13],[-2,-4],[-2,-2],[-2,1],[-3,0],[-1,-3],[-1,-4],[-2,-3],[-1,-2],[-13,-9],[-3,-1],[-3,1],[-3,-1],[-7,5],[-1,2],[-5,4],[0,-2],[1,-1],[1,-2],[1,-2],[4,-11],[-3,-2],[-2,-2],[-7,-4],[-6,-7],[-3,-2],[0,5],[0,2],[-4,3],[0,-2],[0,-2],[-3,-8],[-1,-1],[-1,0],[-3,-1],[-3,1],[-3,3],[-1,2],[-5,-5],[-2,0],[0,-4],[-3,-3],[-3,-2],[-4,0],[-2,-2],[-6,2],[-1,5],[4,6],[2,2],[-1,3],[1,4],[8,13],[6,6],[0,1],[-8,1],[-7,2],[-6,1],[-3,0],[4,-4],[7,-4],[-3,-3],[-3,-4],[-3,-9],[-2,-4],[-7,4],[-3,2],[2,-5],[6,-5],[0,-2],[0,-5],[-12,-5],[-12,-1],[-9,-2],[-15,-1],[-6,0],[-1,-2],[15,-9],[2,-2],[-2,-3],[-3,-2],[-5,-6],[-2,-2],[-7,-3],[-11,3],[-6,-2],[-6,2],[0,-4],[2,-3],[2,-7],[3,1],[5,2],[4,-5],[2,-9],[5,-5],[2,-3],[0,-3],[-2,-3],[-6,-5],[-6,-1],[0,-4],[-2,-2],[-6,1],[-2,1],[-3,1],[-11,1],[11,-7],[4,-3],[2,2],[4,0],[5,-1],[-1,-12],[3,-10],[0,-2],[-6,-5],[0,-6],[-4,-1],[-4,0],[0,-6],[-2,-3],[0,-3],[1,-2],[-3,-3],[-2,-5],[-3,-4],[-2,0],[-5,0],[-6,1],[-5,5],[-2,1],[-2,2],[1,-4],[1,-2],[5,-3],[8,-5],[0,-3],[-2,-2],[-6,-9],[-1,0],[-3,-2],[-7,1],[-3,1],[-9,-1],[-3,1],[-2,-1],[2,-2],[5,-2],[6,-3],[9,-1],[-1,-4],[-2,-2],[1,-4],[-1,-3],[0,-3],[-2,-8],[2,-6],[3,-2],[0,-4],[1,-5],[-4,-5],[-3,0],[-5,-1],[-1,-2],[7,-2],[-1,-4],[-2,-5],[-2,-10],[-4,-17],[-2,-17],[-9,-14],[-3,-1],[-1,0],[-4,1],[-7,3],[-6,1],[-3,0],[-1,-2],[3,-2],[5,-1],[3,-2],[7,-2],[2,-3],[2,-3],[0,-2],[0,-2],[1,-12],[-3,-4],[-3,-3],[-8,0],[-1,1],[-8,4],[0,-2],[6,-5],[2,-2],[-1,-1],[-3,0],[-3,-2],[-6,1],[0,3],[2,2],[-3,0],[-3,-1],[-2,0],[-1,0],[-1,1],[-1,6],[1,2],[5,7],[2,4],[-2,1],[-3,-3],[-4,-7],[-1,-4],[-3,0],[-5,2],[-16,8],[1,6],[-1,4],[5,1],[3,2],[3,2],[4,4],[3,7],[-1,1],[-9,-9],[-5,-3],[-3,-1],[-1,2],[-5,3],[-3,1],[-6,2],[-1,1],[-2,1],[-3,9],[3,12],[3,3],[1,4],[1,5],[-1,2],[-2,-1],[0,-2],[0,-2],[-1,-2],[-8,-4],[-8,-4],[-4,-3],[-3,-3],[-1,-2],[-3,0],[-4,-1],[-3,-1],[-4,1],[-3,2],[-3,1],[-4,-2],[-2,0],[0,-1],[2,-4],[-3,-1],[-5,0],[-3,1],[-2,2],[-1,2],[1,3],[8,5],[4,3],[-3,1],[-8,-1],[-1,1],[-5,0],[0,7],[-1,2],[-1,1],[-1,2],[-2,1],[-1,1],[-9,1],[-1,5],[-1,4],[-2,5],[-4,2],[-2,2],[1,3],[1,3],[-2,1],[-1,2],[0,2],[-2,4],[0,3],[2,2],[5,4],[2,1],[0,1],[6,2],[-5,2],[-3,0],[-2,0],[-2,-3],[-2,-3],[-8,0],[-1,1],[0,4],[0,4],[3,4],[-4,3],[-3,0],[-4,3],[-3,2],[-3,3],[-3,3],[-1,0],[1,3],[1,3],[0,6],[-2,2],[3,5],[4,6],[8,8],[-9,-4],[-7,-8],[-1,-1],[-1,2],[-2,5],[-2,2],[-1,2],[-4,2],[-2,3],[-2,4],[-3,5],[-5,11],[-8,11],[-2,7],[2,9],[-2,5],[7,3],[11,3],[5,3],[4,0],[6,1],[3,2],[-4,0],[-3,0],[0,1],[1,2],[1,3],[-2,0],[-6,-5],[-10,-4],[-8,-2],[-1,0],[-3,-1],[-1,0],[-1,0],[-3,4],[-1,2],[5,6],[4,9],[5,5],[3,1],[6,0],[2,-1],[-1,4],[0,1],[5,2],[5,1],[4,-1],[2,-3],[3,-8],[5,-2],[-1,3],[-2,5],[-1,7],[-2,3],[-3,1],[-6,-1],[-3,5],[-1,2],[0,3],[-4,7],[-1,3],[-2,5],[-1,0],[1,-6],[2,-4],[3,-9],[1,-4],[-2,-3],[-3,-3],[-3,-2],[-6,-2],[1,5],[1,4],[-3,-1],[-3,-3],[-1,-5],[-2,-4],[-6,-10],[-2,-6],[-2,-3],[-3,0],[-2,2],[-2,5],[0,4],[0,10],[0,5],[-1,7],[-3,15],[-1,6],[-5,3],[-2,4],[-1,3],[1,1],[1,1],[8,4],[6,5],[7,8],[3,3],[10,2],[4,0],[0,1],[-1,1],[-7,0],[-9,-4],[-2,-1],[-4,-5],[-3,-3],[-8,-6],[-6,0],[-6,8],[-6,-2],[-5,1],[-1,1],[-1,10],[3,12],[-3,0],[-1,1],[-2,2],[-1,1],[1,2],[9,5],[14,11],[6,5],[4,1],[3,3],[3,4],[1,2],[2,2],[4,2],[5,2],[7,7],[1,2],[-2,1],[-3,-3],[-7,-5],[-5,-4],[-16,-14],[-8,-5],[-3,-4],[-3,-3],[-4,-2],[-3,-1],[-7,-1],[-4,-2],[-2,1],[-1,7],[1,4],[0,4],[2,6],[2,4],[1,2],[1,2],[5,4],[3,2],[2,4],[12,1],[4,0],[1,1],[1,1],[-1,1],[-3,1],[-10,0],[-9,0],[-4,1],[-2,0],[-3,1],[-4,2],[-5,9],[2,11],[0,5],[7,5],[4,1],[5,4],[7,5],[9,4],[4,1],[4,-1],[13,-5],[7,-1],[5,1],[8,-1],[13,-8],[3,1],[-1,2],[-15,8],[0,2],[4,1],[4,2],[-2,1],[-10,-1],[-3,-2],[-9,-1],[-5,2],[-5,1],[-6,3],[-6,-1],[-3,-1],[-7,-2],[-2,0],[-12,-11],[-5,-2],[-4,1],[3,6],[0,3],[0,3],[1,4],[7,8],[4,8],[1,5],[3,1],[4,-1],[13,-3],[11,-4],[7,-1],[5,0],[3,1],[1,2],[1,2],[0,3],[1,1],[2,1],[3,5],[1,4],[-1,2],[-2,-1],[-5,-1],[0,-1],[-5,-6],[-4,-1],[-11,-2],[-5,0],[-9,3],[-2,1],[0,1],[-11,0],[-4,-1],[-2,1],[1,3],[4,3],[4,12],[4,3],[8,2],[9,0],[14,-9],[5,-1],[4,1],[9,3],[2,1],[3,4],[5,6],[-1,2],[-6,-4],[-3,-1],[-3,0],[3,12],[1,8],[1,2],[8,0],[11,1],[2,2],[0,1],[-4,1],[-2,2],[-4,0],[-5,-2],[-6,0],[0,4],[5,8],[0,3],[2,8],[0,3],[3,4],[7,2],[3,2],[0,2],[-4,6],[1,2],[3,1],[2,2],[-1,0],[-3,1],[-5,-1],[-6,-1],[-4,2],[-4,1],[-2,0],[-7,-4],[-2,0],[-3,1],[-18,3],[-2,1],[-7,6],[-5,3],[-7,4],[-10,3],[-11,2],[-7,2],[-3,3],[-6,6],[-4,5],[-1,2],[2,3],[3,2],[5,2],[9,-1],[4,0],[5,-2],[4,0],[8,0],[8,-1],[5,-1],[6,-3],[17,-10],[7,-4],[4,0],[12,-4],[3,0],[5,2],[0,1],[-1,1],[-6,1],[-7,4],[-4,4],[0,5],[0,3],[1,2],[1,5],[-4,3],[-3,1],[-7,4],[-1,1],[4,0],[3,0],[8,-2],[3,0],[3,0],[0,1],[-4,3],[-5,4],[-12,1],[-7,-1],[-5,2],[-5,2],[-4,1],[-6,-2],[-4,0],[-3,1],[-3,7],[1,3],[2,1],[2,2],[1,3],[4,2],[22,6],[6,4],[-1,1],[-3,-1],[-5,-2],[-3,0],[-13,2],[-2,-1],[-5,-3],[-7,-4],[-3,0],[-5,3],[0,1],[-1,2],[5,3],[1,1],[4,4],[-1,2],[-5,-1],[-1,1],[1,3],[-1,4],[-1,4],[-5,6],[-1,1],[-2,2],[-3,8],[1,2],[3,1],[0,1],[-7,-1],[0,-2],[1,-2],[1,-2],[0,-4],[1,-2],[3,-4],[2,-1],[3,-4],[2,-5],[-1,-3],[-2,-2],[-4,-3],[-2,-2],[0,-3],[-3,-2],[-2,1],[-2,0],[2,-4],[1,-3],[-1,-4],[-4,-3],[-2,0],[-4,-2],[-10,-1],[-4,1],[-7,2],[-7,1],[-4,2],[-4,5],[-2,4],[0,4],[1,3],[3,2],[2,10],[4,9],[10,9],[2,4],[1,1],[0,2],[-1,1],[-12,-12],[-7,-1],[-2,3],[0,4],[2,1],[5,0],[3,2],[-4,4],[-4,1],[-1,1],[4,3],[9,0],[3,2],[3,2],[4,4],[1,3],[0,3],[0,2],[0,3],[0,2],[-1,3],[-2,3],[-6,2],[-2,-3],[-2,-1],[-2,0],[-2,1],[-3,0],[-2,2],[-3,0],[-1,1],[0,3],[0,3],[2,2],[4,1],[3,2],[2,4],[0,3],[-1,4],[-3,4],[-6,-4],[-3,0],[0,2],[-1,2],[-2,3],[-4,1],[-3,2],[0,2],[1,2],[1,2],[2,5],[2,0],[2,0],[-1,4],[-2,4],[-2,2],[0,1],[0,1],[-2,3],[-1,1],[-3,6],[-2,1],[-3,2],[-3,0],[-4,-2],[-8,-1],[-7,-1],[-1,0],[3,2],[5,2],[6,2],[2,3],[0,3],[0,3],[-2,3],[2,1],[6,2],[2,0],[3,2],[-7,5],[-8,4],[-2,1],[-2,2],[-1,3],[-3,3],[-3,4],[-5,3],[-12,5],[-5,4],[-3,5],[-2,3],[-2,2],[-9,4],[-1,2],[9,5],[1,2],[-4,6],[-4,4],[-4,2],[-6,1],[-5,2],[-6,3],[-5,2],[-7,2],[-13,6],[-19,6],[-9,3],[-5,2],[-7,0],[-13,3],[-11,1],[-7,0],[-2,0],[-5,4],[-8,2],[-5,-1],[-5,-4],[-6,-3],[-3,-1],[-5,4],[-2,2],[-3,1],[-2,-1],[-4,-3],[-4,-2],[-6,-3],[-5,-1],[-7,0],[-1,-1],[-3,0],[-3,1],[-3,1],[-3,3],[-2,1],[-2,0],[-5,-1],[-7,-4],[-3,-1],[-2,1],[-3,1],[-6,3],[-3,0],[-3,-1],[1,-3],[6,-6],[5,-4],[-5,-1],[-36,6],[-5,2],[-7,3],[-5,2],[-10,5],[-7,3],[-3,3],[0,1],[2,2],[15,8],[5,1],[12,2],[3,1],[1,1],[-3,1],[-16,0],[-13,1],[-12,3],[-2,1],[-2,1],[-2,3],[1,3],[3,3],[1,2],[1,1],[-15,-7],[-6,-3],[-5,1],[-3,1],[-2,1],[0,2],[1,1],[1,1],[-8,3],[-3,3],[-1,2],[3,3],[3,2],[2,1],[7,1],[27,2],[19,-2],[6,7],[4,2],[13,2],[20,0],[13,-1],[7,-2],[9,-3],[0,1],[-2,3],[0,3],[3,4],[2,3],[-1,2],[-4,3],[-7,4],[-4,0],[-4,0],[-5,-3],[-10,-5],[-5,-1],[-8,0],[-4,0],[-4,1],[-7,3],[-2,1],[-3,-2],[-4,-3],[-3,-2],[-3,-1],[-4,0],[-4,0],[-17,4],[-4,2],[0,4],[-6,3],[-6,0],[0,1],[7,5],[6,2],[-1,0],[-8,0],[-6,-2],[-3,0],[-7,-1],[-8,2],[-3,1],[-4,2],[-4,2],[-11,2],[-3,1],[-2,2],[-10,5],[-5,4],[-1,3],[7,5],[0,1],[-3,2],[-1,1],[1,2],[6,5],[2,2],[10,2],[10,4],[4,1],[4,0],[13,0],[4,1],[4,2],[6,2],[12,3],[27,5],[2,0],[0,1],[-2,3],[-1,1],[6,2],[12,3],[9,2],[5,0],[5,1],[6,2],[4,0],[21,1],[10,-1],[4,0],[3,1],[4,2],[8,6],[3,4],[4,5],[5,9],[3,9],[3,8],[2,5],[1,2],[4,2],[5,2],[8,1],[-1,1],[-3,1],[-3,1],[-3,0],[-6,-2],[-6,-2],[-7,1],[-5,-1],[-4,-2],[-7,-1],[-5,0],[-9,3],[-4,0],[-11,0],[-3,1],[-3,2],[-2,2],[-2,3],[0,4],[4,6],[2,1],[10,7],[7,3],[7,3],[4,1],[5,1],[4,1],[8,5],[8,4],[11,7],[5,2],[17,4],[5,0],[4,-1],[3,-2],[11,-7],[1,0],[-2,3],[-4,8],[1,4],[6,3],[2,1],[7,0],[10,-2],[7,-1],[5,-2],[7,-1],[3,0],[2,1],[3,3],[5,5],[1,7],[0,8],[-2,6],[-1,3],[1,3],[5,4],[5,3],[11,3],[9,1],[6,0],[7,-2],[10,-1],[9,-3],[15,-8],[9,-4],[8,-2],[8,-3],[12,-6],[6,-3],[4,-1],[3,0],[-1,2],[-6,4],[-8,4],[-19,7],[-11,6],[-9,6],[-7,3],[-13,4],[1,1],[15,5],[27,5],[32,3],[10,0],[19,1],[1,2],[4,1],[17,3],[5,0],[8,-1],[8,-3],[4,-2],[5,-5],[2,-6],[0,-18],[0,-4],[1,-1],[3,2],[5,4],[3,2],[3,4],[2,6],[1,4],[-4,5],[-1,7],[3,4],[7,0],[28,-14],[11,-3],[13,-7],[15,1],[13,-1],[7,0],[3,1],[-5,3],[-19,9],[-9,7],[-6,8],[-2,4],[5,1],[22,0],[32,-4],[42,-13],[21,-5],[37,-15],[11,-2],[4,-1],[4,2],[2,2],[0,3],[-2,3],[-1,4],[0,5],[2,9],[6,3],[3,3],[-3,6],[-7,4],[-27,11],[0,1],[6,1],[8,1],[67,-2],[11,-1],[5,-1],[3,-1],[2,-1],[15,1],[-1,3],[-1,2],[-78,4],[-15,2],[-7,0],[-8,-1],[-16,-1],[-7,0],[-9,6],[8,6],[7,0],[14,-3],[8,4],[13,3],[13,1],[28,6],[5,1],[6,-1],[15,-1],[5,-2],[7,-3],[4,-1],[4,0],[6,-2],[9,5],[8,5],[10,4],[13,-2],[8,-3],[8,-3],[10,-1],[18,-11],[4,0],[1,1],[2,2],[1,3],[2,4],[-2,1],[-15,4],[-3,2],[-3,3],[0,2],[3,2],[3,0],[10,0],[3,0],[3,2],[4,2],[3,1],[6,0],[10,-2],[9,0],[3,1],[1,2],[1,1],[1,0],[32,0],[8,1],[6,1],[8,0],[6,0],[8,-2],[9,0],[12,3],[11,1],[64,0],[21,-2]],[[2530,6099],[2,-1],[1,-1],[3,-3],[3,-2],[1,5],[-1,3],[0,1],[0,2],[10,-13]],[[2549,6090],[-1,-2],[-3,-5],[-5,-8],[-4,-6],[-4,-7],[-3,-5],[-1,-1],[-4,-4],[-1,-2],[-1,-8],[-1,-2],[1,-4],[1,-7],[0,-4],[-3,-4],[-2,-4],[-1,-3]],[[2517,6014],[0,1],[-1,0],[-2,-1],[-1,0],[-1,-1],[0,-3],[0,-4],[0,-2],[0,-1],[-3,-2],[-1,-3],[-1,-3],[-2,-2],[-1,0],[-1,0],[-2,-3],[-3,-5],[-1,-4],[0,-3],[0,-3]],[[2497,5975],[-11,9],[-3,2],[-15,0],[-7,4],[-7,7],[-5,6],[-11,19]],[[2438,6022],[0,1],[1,3],[1,4],[-1,4],[0,3],[1,5],[0,4],[0,2],[1,1],[1,3],[-3,9],[0,3],[0,2],[3,10],[3,12],[4,13],[3,8],[8,0],[5,0],[8,0],[7,0],[5,0],[2,1],[0,5],[0,5],[1,6],[0,2],[-1,3],[-3,1],[-2,3],[0,3],[-1,4],[-1,4],[-3,5],[-4,4],[-4,7],[-3,7],[-3,5],[-2,3],[0,1],[6,0],[5,0],[0,11],[0,10],[0,11],[10,0],[13,0],[12,0],[10,0],[6,0]],[[9020,5948],[-1,-1],[-1,2],[-1,2],[0,6],[4,6],[1,5],[1,0],[1,-1],[1,-2],[-4,-9],[-1,-8]],[[3411,5503],[-2,-3],[0,-3],[-1,-4],[-1,-2],[2,-5],[1,0],[0,-1],[1,-1],[0,-1],[-1,-1],[-1,-1],[-1,-3],[0,-3],[-1,-2],[-2,-1],[-5,0],[-2,0],[-1,-1],[-2,-2],[-1,-1],[-1,-1],[-1,-2],[-1,-4],[0,-2],[1,-3],[1,-3],[-1,-6],[-1,-4],[0,-3],[-1,-6],[-2,-6],[-1,-4],[0,-4],[1,-6],[3,-8],[1,-4],[1,-6],[3,-6],[2,-4],[0,-5],[0,-2],[2,-1],[1,-1],[2,0],[1,0],[1,1],[3,0],[0,-1],[0,-8],[1,-3],[0,-1],[1,-2],[0,-2],[0,-4],[1,-3],[0,-4],[0,-2],[1,-1],[1,-3],[0,-1],[1,-1],[1,-5],[0,-1],[1,0],[0,-2],[0,-4],[1,-1],[1,-4],[0,-3],[1,-4],[2,-3],[0,-3],[2,-6],[2,-5],[2,-1],[1,-1],[2,-1],[1,-2]],[[3312,5483],[-5,14],[-6,14],[-6,13],[-1,2],[3,6],[2,5],[2,2],[1,3],[-1,10],[0,3],[-1,4],[0,4],[0,4],[1,2],[1,1],[3,1],[2,1],[1,1],[1,2],[1,0],[3,-1],[1,2],[3,3],[5,5],[1,3],[1,5],[0,3],[-1,1],[-1,0],[-2,1],[-2,-2],[-1,1],[-2,3],[0,3],[1,3],[0,3],[-3,8],[0,2],[2,3],[1,3],[2,7],[1,3],[3,1],[1,1],[2,4],[3,4],[4,4],[1,6],[1,2],[3,3],[1,2],[0,1],[-5,14]],[[3333,5676],[1,-1],[4,-9],[2,-2],[0,2],[2,-1],[6,-6],[7,-10],[11,-20],[3,-7],[2,-4],[3,-8],[1,-4],[0,-17],[-3,-11],[0,-8],[0,-12],[-2,-6],[2,3],[1,11],[2,6],[2,6],[3,2],[4,-3],[3,0],[2,-2],[5,-11],[5,-9],[2,-7],[6,-3],[3,-5],[1,-5],[1,-12],[-1,-19],[0,-1]],[[8172,6463],[0,-1],[-2,4],[0,2],[1,0],[2,-2],[0,-2],[-1,-1]],[[8166,6463],[-4,0],[0,1],[-1,1],[2,2],[4,3],[-1,-3],[0,-4]],[[8173,6482],[1,-2],[0,-3],[1,-1],[0,-2],[-1,-2],[0,-2],[-1,-2],[-3,3],[-3,2],[-3,-1],[-1,2],[0,2],[3,3],[0,1]],[[7047,2123],[-4,-3],[-3,0],[-1,3],[-3,6],[-1,1],[-1,2],[2,1],[2,-2],[5,-1],[4,-4],[3,-1],[-1,-1],[-2,-1]],[[2690,6047],[-7,1],[-4,-2],[-1,-4],[-1,-1],[-2,0],[-2,-2],[-3,-3],[-3,-1],[-2,0],[-1,0],[0,-2],[-1,-1],[-1,0],[-1,0],[-1,1],[-1,0],[0,-3],[-1,0],[-1,1],[-2,-1],[-1,-3],[-3,0],[-3,1],[-2,3],[-2,5],[-1,1],[-4,-3],[-1,-4],[-1,-3],[1,-2],[-1,-1],[-2,-1],[-1,-3],[-1,-4],[0,-4],[1,-2],[-1,-2],[-2,-1],[-3,-4],[-3,-7],[-2,-4],[-3,-3],[-2,-3],[0,-3],[0,-1],[-1,-1],[-6,7],[-1,5],[-2,-1],[-1,-2],[-3,-6],[-2,-7],[-2,-1],[-6,1],[-4,0],[0,-1],[-1,-3],[1,-4],[1,-13],[0,-5],[0,-2],[-2,0],[-2,-1],[-2,-3],[0,-2],[0,-4],[-1,-3],[-1,-3],[-2,-1],[-7,-1]],[[2574,5931],[0,6],[-2,3],[-2,5],[-1,3],[1,2],[-1,3],[-3,2],[-3,-2],[-1,1],[-2,2]],[[2560,5956],[3,3],[0,1],[-1,2],[-1,1],[1,3],[0,4],[1,9],[0,2],[-2,3],[-3,0],[-2,-1],[-2,2],[-1,3],[-2,1],[-3,-2],[-4,-4],[-1,-1],[-1,0],[-1,3],[0,3],[0,1],[-2,1],[-2,1],[-1,1],[-1,2],[-3,3],[-1,3],[-3,5],[-1,2],[-1,2],[-2,3],[-1,-1],[-5,3],[-1,0]],[[2549,6090],[3,-2],[2,4],[1,1],[3,4],[1,1],[5,2],[2,0],[2,-4],[2,-3],[3,2],[2,1],[11,-4],[4,2],[8,0],[3,-1],[5,6],[3,1],[4,3],[-1,3],[-1,1],[6,-1],[8,-6],[9,1],[3,3],[2,1],[9,-6],[3,-5],[2,0],[1,1],[1,1],[-2,1],[-1,1],[7,-3],[14,-22],[0,-2],[-6,7],[-3,-1],[-1,-1],[0,-3],[1,-2],[1,0],[1,1],[2,-2],[2,-2],[2,-4],[1,-4],[1,0],[2,3],[2,0],[1,-3],[1,1],[-1,4],[-4,4],[1,0],[8,-7],[2,-10],[2,-2],[2,-3]],[[2599,6127],[-4,-4],[-2,0],[2,3],[4,3],[2,2],[3,-1],[-5,-3]],[[2614,6132],[-2,-3],[0,1],[1,3],[1,2],[1,0],[0,-2],[-1,-1]],[[5489,7647],[3,-4],[-11,5],[1,1],[2,0],[5,-2]],[[5462,7660],[5,-1],[4,0],[3,-1],[2,-1],[1,-1],[-3,0],[-3,0],[-3,-1],[-4,1],[-1,1],[-1,1],[0,2]],[[5512,7635],[0,-2],[1,-2],[1,-3]],[[5514,7628],[-5,5],[-5,6],[-9,10],[-7,2],[-9,8],[-6,2],[2,1],[3,0],[14,-10],[-2,3]],[[5477,7668],[-2,-1],[-12,1],[-4,1],[-4,3],[-1,1],[4,1],[4,-1],[1,-2],[10,-2],[4,-1]],[[5466,7676],[-5,0],[-3,1],[-2,2],[0,1],[0,3],[5,0],[6,-2],[2,-2],[-1,-1],[-2,-2]],[[5426,7717],[2,-5],[-1,1],[-2,3],[-1,3],[2,-2]],[[5423,7722],[0,-2],[-3,4],[-2,2],[0,1],[5,-5]],[[5421,7714],[1,-1],[0,-1],[-2,1],[-7,12],[-1,3],[3,-3],[6,-11]],[[5421,7737],[0,-1],[-2,3],[-2,2],[-1,2],[-2,3],[-1,4],[-4,6],[0,2],[2,-3],[1,-1],[1,-1],[3,-4],[3,-6],[4,-5],[-1,0],[-1,-1]],[[5411,7762],[1,-3],[-2,3],[-3,0],[0,2],[0,2],[1,1],[1,0],[1,-2],[1,-3]],[[5402,7756],[0,-2],[-2,3],[-1,5],[-2,8],[0,2],[1,3],[0,2],[-2,7],[2,1],[1,-5],[0,-2],[2,-4],[0,-6],[0,-8],[1,-2],[0,-2]],[[5411,7774],[-4,-1],[-1,2],[-1,2],[-2,1],[-2,2],[0,1],[2,3],[1,5],[2,-3],[2,-5],[1,-1],[2,-6]],[[5525,7829],[-1,-1],[0,-2],[-1,-2],[1,-4],[2,-6],[-1,-4],[1,-2],[3,-2],[0,-1],[-1,0],[-1,-2],[0,-4],[3,-4],[5,-3],[1,-1],[1,-1],[1,-1],[0,-1],[0,-1],[0,-1],[-2,-1],[-3,0],[-2,2],[0,-1],[0,-2],[-2,0],[1,-10],[0,-2],[-1,-1],[-1,0],[-1,0],[0,-1],[0,-2]],[[5488,7657],[-1,1],[-6,9],[-6,6],[-6,10],[-8,4],[-6,5],[-4,-1],[-3,-1],[-3,0],[-1,0],[-2,3],[0,2],[0,3],[-3,5],[-5,4],[-4,6],[-9,15],[-1,5],[1,1],[2,0],[1,1],[2,0],[3,-1],[-2,3],[-3,3],[-8,13],[-3,6],[0,6],[1,9],[-2,6],[-6,9],[-2,4],[-5,2],[-2,0],[-1,-3],[-1,-7],[-4,-9],[-1,-4],[-3,-6],[-1,0],[-2,0],[-3,9],[-3,7],[0,3],[-1,4],[-2,14],[2,3]],[[5377,7806],[1,-3],[7,-3],[2,2],[1,2],[0,1],[3,-2],[2,1],[3,0],[3,-1],[1,2],[2,5],[1,3],[1,1],[1,-1],[0,-2],[1,-2],[3,-4],[1,-2],[2,0],[1,1],[2,1],[4,-3],[4,-1],[3,2],[-1,2],[-1,2],[0,2],[0,2],[2,2],[0,1],[-2,3],[0,1],[5,4],[4,2],[1,1],[1,3],[0,4],[0,4],[-2,4],[0,1],[0,2],[1,2],[2,1],[2,1],[2,1],[2,1],[2,2],[2,4],[1,0],[3,0],[1,1],[-1,5],[1,2],[1,0],[1,1],[3,0],[2,-2]],[[5458,7862],[2,-1],[5,-4],[3,-4],[2,-5],[3,-4],[3,-3],[2,-3],[2,-5],[3,-2],[3,-1],[3,-2],[0,-2],[2,-3],[3,-2],[4,-1],[9,0],[1,0],[1,-1],[3,1],[2,2],[1,1],[3,5],[2,0],[3,0],[1,1],[1,0]],[[2977,6265],[0,-4],[-7,5],[-6,6],[0,4],[3,0],[3,-2],[4,-4],[3,-5]],[[3006,6223],[-2,4],[-3,4],[-1,2],[-2,1],[-12,-1],[-2,0],[-1,-2],[-1,0],[-3,-1],[-4,-1],[-8,3],[-3,2],[-3,1],[-3,0],[-4,-1],[-3,-2],[-2,-4],[0,-4],[-2,-1],[-3,6],[-2,4],[-3,3],[-6,5],[-2,2],[0,3],[2,11],[3,1],[2,1],[3,-2],[4,-2],[3,-1],[5,-1],[2,-2],[19,-4],[4,-1],[1,0],[1,2],[1,2],[2,2],[5,1],[1,1],[1,2],[0,3],[-3,4],[-5,9],[-5,10],[2,4],[-1,6],[1,6],[1,6],[-4,4],[-6,5],[-7,2],[-2,1],[-1,4],[1,5],[2,2],[3,2],[3,1],[6,2],[7,-2],[6,-5],[6,-4],[7,-1],[3,-2],[2,2]],[[2981,6338],[1,-1],[0,-2],[-3,1],[-3,2],[-1,-1],[0,1],[-2,1],[2,2],[1,0],[2,0],[3,-3]],[[5614,7972],[3,0],[1,0],[0,-3],[1,-2],[0,-2],[1,-2],[2,0],[3,-3],[2,-4],[2,-1],[1,-1],[0,1],[2,0],[0,-1],[2,-2],[0,-2],[0,-2],[0,-2],[1,-1]],[[5635,7945],[-1,-1],[-5,-7],[-2,-2],[-1,0],[-2,0],[-2,0],[-2,-2],[-1,0],[-2,-2],[-1,-4],[-2,-3],[-2,-2],[-1,-2],[-1,-6],[-1,-2],[-1,-2],[-1,-2],[-2,-9],[-2,-3],[-2,-3],[0,-2],[0,-2],[-2,-5],[-2,-5],[-1,-2],[1,-3],[-3,-3],[-1,-2],[-1,-1],[-1,-2],[-1,-5],[0,-2],[0,-2],[-2,-1],[0,-2],[-1,-3],[-1,-1],[-2,-3],[-6,1],[-2,0],[-1,-2],[0,-1],[0,-2],[-2,-1],[-1,-1],[-3,2],[-6,-2],[-1,-1]],[[5562,7840],[-1,1],[-2,1],[-6,1],[-2,-1],[-4,0],[-3,1],[-2,-1],[-2,-4],[-1,-1],[-1,-1],[-2,-1],[-1,-2],[-2,-1],[-2,1],[-1,1],[-1,0],[0,-2],[-1,-1],[-3,-2]],[[5458,7862],[0,1],[-2,5],[-2,2],[1,3],[-1,1],[-1,1],[0,3],[-1,3],[0,2],[-6,0]],[[5476,7949],[1,0],[2,0],[1,-1],[5,-6],[4,-4],[4,-3],[5,0],[5,0],[10,1],[7,0],[0,1],[1,3],[-1,2],[0,3],[1,4],[4,2],[10,2],[5,2],[1,3],[2,3],[2,0],[2,-1],[3,-3],[2,-1],[2,1],[5,4],[5,5],[4,11],[1,2],[4,1],[6,0],[3,-2],[3,0],[3,0],[5,2],[2,0],[2,-1],[1,-2],[2,-2],[0,-2],[1,-1],[1,-2],[1,-2],[1,0],[10,3],[0,1]],[[8414,4555],[-2,0],[-1,1],[0,5],[1,3],[6,4],[2,3],[3,7],[2,2],[1,1],[0,-1],[0,-5],[1,-3],[0,-2],[-3,-2],[-2,-7],[-6,-4],[-2,-2]],[[8385,4574],[-2,-1],[-3,2],[0,1],[2,3],[2,4],[3,0],[1,-1],[0,-5],[-3,-3]],[[8427,4590],[-2,-2],[0,5],[2,5],[2,2],[1,-2],[0,-1],[-3,-2],[0,-5]],[[8333,4644],[1,-3],[5,-5],[0,-2],[1,-3],[1,-3],[2,0],[2,0],[1,-1],[2,-3],[2,-5],[2,-6],[2,-3],[2,-4],[-1,-4],[-3,-6],[-2,-1],[-2,-1],[-3,-3],[-2,2],[-3,1],[-3,2],[-3,5],[-2,5],[-1,4],[-4,3],[-6,8],[-3,1],[-2,-1],[-1,0],[-8,4],[-1,2],[-1,3],[-1,2],[0,4],[1,2],[1,2],[4,3],[3,1],[4,0],[5,1],[5,-1],[1,1],[3,3],[1,-1],[1,-3]],[[8473,4636],[-2,-3],[-1,-6],[-3,-5],[-4,-9],[-3,-5],[-2,-5],[-3,-4],[-2,-1],[-5,-1],[-5,-6],[-3,-3],[-3,0],[-3,2],[-1,2],[0,3],[1,3],[1,2],[1,3],[-4,4],[0,3],[1,7],[1,8],[2,5],[4,9],[3,5],[2,2]],[[8445,4646],[0,-2],[1,-3],[1,0],[0,1],[4,-1],[1,1],[2,3],[1,2],[1,5],[0,2]],[[8456,4654],[4,2],[2,3],[1,3],[5,5],[1,2]],[[8469,4669],[0,-5],[1,-2],[1,0],[3,3],[1,0],[1,-2],[0,-5],[-2,-4],[-3,0],[-1,-1],[0,-2],[0,-3],[1,-1],[1,-4],[1,-7]],[[8211,4679],[-1,-2],[-2,3],[-1,2],[2,2],[2,-2],[0,-3]],[[8415,4692],[-1,-4],[-1,1],[0,3],[1,2],[2,3],[2,1],[2,-1],[0,-1],[-3,-1],[-2,-3]],[[8318,4680],[-1,0],[-2,1],[1,5],[-1,3],[1,3],[1,5],[0,1],[1,-1],[0,-1],[1,-1],[1,0],[0,-2],[0,-2],[0,-2],[-2,-2],[-1,-3],[1,-4]],[[8425,4703],[-1,-3],[-7,0],[0,4],[2,3],[1,1],[2,1],[3,-1],[0,-5]],[[8239,4688],[-3,-12],[1,-2],[1,-2],[-6,-2],[-3,1],[-1,-1],[-6,3],[-4,2],[-1,3],[1,2],[1,-1],[3,0],[2,1],[0,8],[-1,10],[5,8],[2,3],[3,2],[6,-4],[2,-2],[0,-1],[1,-3],[-3,-13]],[[8452,4704],[-2,-4],[-1,-6],[-1,-2],[-3,-1],[-1,6],[-2,0],[1,6],[1,2],[2,0],[0,-3],[1,0],[3,9],[1,0],[1,0],[0,-1],[0,-6]],[[8442,4707],[-4,-1],[-3,-7],[-2,0],[-1,-4],[0,-1],[0,-1],[0,-1],[-1,-2],[-2,2],[-1,-2],[-1,-1],[-2,3],[-2,0],[-1,0],[3,6],[3,5],[1,1],[-1,1],[-1,1],[0,1],[2,1],[2,0],[1,-2],[1,0],[4,6],[2,-1],[2,-2],[1,-2]],[[8857,4701],[-1,-1],[-7,2],[-1,2],[0,1],[2,3],[1,4],[3,1],[1,0],[2,-9],[0,-3]],[[8265,4702],[-1,0],[-1,1],[0,2],[0,4],[0,3],[1,2],[4,0],[0,-2],[-3,-10]],[[8307,4709],[-1,0],[-1,2],[1,3],[1,1],[1,-2],[0,-1],[0,-2],[-1,-1]],[[8460,4715],[0,-4],[2,2],[2,1],[5,-1],[4,0],[2,-2],[0,-7],[-1,-1],[-18,-6],[-2,2],[-1,2],[2,5],[0,2],[1,4],[2,3],[2,0]],[[8550,4717],[5,-2],[2,0],[1,-2],[-3,-5],[-5,4],[-1,4],[1,1]],[[8410,4688],[-4,-2],[-3,-2],[-2,-3],[-1,0],[-3,-1],[-4,1],[-2,-1],[-7,-7],[-3,0],[-3,-2],[0,3],[-1,2],[-3,0],[-2,0],[-3,-6],[-3,1],[-2,0],[-1,-1],[-2,-1],[-1,1],[-6,4],[-6,3],[-7,-1],[-5,2],[-3,-2],[-3,-2],[-1,2],[-1,3],[-1,4],[0,4],[0,3],[1,3],[1,3],[0,3],[1,-2],[1,1],[4,3],[4,5],[3,2],[2,1],[2,-1],[2,0],[1,1],[3,-4],[1,-1],[4,0],[4,-2],[3,-3],[4,-4],[3,-4],[2,-1],[1,-1],[1,1],[2,3],[2,1],[2,0],[3,1],[2,0],[1,2],[2,-1],[1,-2],[5,-7],[2,0],[3,1],[1,2],[0,3],[1,3],[1,2],[2,2],[4,3],[3,2],[2,5],[-5,2],[1,4],[2,2],[2,-1],[1,-3],[1,-10],[-1,-1],[-1,-2],[-1,-2],[-2,-4],[1,-4],[-1,-2],[-1,-1]],[[8634,4705],[-2,-2],[1,4],[6,11],[1,-2],[3,-1],[-4,-4],[-4,-2],[-1,-4]],[[8284,4705],[1,-3],[1,1],[3,3],[2,1],[1,0],[2,0],[2,-3],[0,-4],[1,-1],[1,5],[1,1],[1,1],[3,0],[1,-2],[2,-7],[0,-6],[0,-3],[2,-1],[0,-2],[0,-3],[-1,-1],[-2,-1],[-1,0],[-1,2],[-1,1],[-2,-1],[-2,-1],[0,-3],[2,-1],[0,-1],[0,-1],[-1,0],[-2,2],[-1,-1],[-6,-2],[-1,0],[-1,2],[0,6],[-1,2],[-4,-8],[-1,-1],[-1,-1],[-2,0],[-6,-5],[-2,1],[-1,0],[-7,-5],[-3,-1],[-2,-1],[-1,1],[-2,-1],[-1,-2],[-3,-1],[-3,1],[-2,2],[-3,2],[0,3],[0,4],[1,4],[-1,9],[1,4],[1,3],[1,2],[2,0],[3,3],[3,5],[1,-1],[4,-3],[2,0],[4,0],[1,-1],[1,-5],[1,-1],[1,-2],[3,-7],[2,0],[2,-1],[4,5],[3,-1],[0,4],[-1,4],[-2,3],[-1,0],[-2,0],[-1,1],[-4,6],[-2,4],[0,4],[0,3],[3,3],[2,1],[5,-2],[1,-2],[2,-6],[1,-3]],[[8206,4714],[3,-3],[4,-9],[0,-2],[-1,-3],[-3,-4],[-6,-5],[-1,-3],[-2,-6],[0,-2],[0,-1],[-1,-1],[-1,-1],[-2,1],[2,4],[0,4],[-1,4],[-2,3],[-3,4],[-3,4],[-3,2],[-3,1],[-1,2],[-2,5],[-1,3],[0,2],[0,3],[1,0],[3,0],[6,-4],[3,0],[2,1],[4,6],[1,0],[4,-3],[3,-2]],[[8606,4726],[-2,-6],[-2,1],[-3,7],[0,5],[0,1],[2,1],[4,-2],[1,-4],[0,-3]],[[8521,4742],[1,-3],[0,-1],[-4,-1],[-3,-3],[-1,-3],[-2,-5],[-4,2],[-4,0],[-2,2],[-2,0],[-2,-2],[-4,-4],[0,6],[1,4],[3,8],[4,-2],[3,0],[4,2],[3,4],[4,2],[3,-6],[2,0]],[[8539,4745],[-2,-2],[0,5],[0,3],[3,-1],[0,-3],[0,-1],[-1,-1]],[[8847,4707],[-6,-7],[-9,1],[-3,0],[-5,-2],[-1,2],[1,7],[4,19],[5,17],[2,4],[3,4],[3,3],[7,4],[6,-1],[1,-1],[2,-6],[2,-4],[1,-6],[-3,-11],[-3,-10],[-5,-8],[-2,-5]],[[8647,4723],[0,-1],[-4,1],[-2,0],[0,5],[-1,3],[2,5],[0,5],[1,1],[1,3],[1,9],[1,1],[2,1],[1,5],[1,1],[1,4],[2,2],[0,3],[1,2],[2,1],[1,-1],[1,-4],[-2,-4],[1,-10],[-2,-10],[-1,-4],[-2,-2],[-1,-3],[-2,-5],[-1,-5],[0,-2],[-1,-1]],[[8665,4769],[0,-3],[-1,2],[-1,3],[-2,0],[-1,1],[-1,2],[5,1],[1,-6]],[[8177,4773],[0,-2],[-2,0],[-1,4],[1,1],[1,0],[1,0],[0,-3]],[[8573,4770],[-1,-1],[-2,3],[-1,1],[2,3],[1,1],[1,-2],[0,-1],[0,-1],[0,-3]],[[8354,4774],[-3,-1],[-1,1],[0,6],[3,-3],[1,0],[0,-3]],[[8162,4775],[-1,-1],[-5,0],[-3,-5],[-2,-1],[-7,0],[-1,1],[-1,0],[0,-1],[-3,0],[-7,5],[-2,3],[2,5],[2,5],[6,2],[25,0],[3,-5],[0,-2],[-5,-3],[-1,-3]],[[8204,4782],[-2,-1],[-2,2],[0,3],[0,3],[3,1],[2,0],[2,-2],[1,-2],[1,-2],[-4,0],[-1,-2]],[[8740,4795],[0,-1],[-1,2],[0,1],[1,3],[1,2],[1,0],[0,-2],[-2,-5]],[[7923,4801],[-2,-1],[-1,1],[-1,2],[2,4],[1,1],[1,0],[1,-2],[-1,-5]],[[8741,4807],[-1,-1],[-1,5],[1,1],[2,-3],[-1,-2]],[[8744,4813],[-1,0],[0,3],[1,2],[1,2],[1,0],[-2,-7]],[[8736,4813],[0,-4],[-1,-5],[-2,-5],[-2,-8],[-1,-2],[-3,-3],[-3,4],[-1,4],[1,17],[2,-1],[0,1],[1,1],[-2,2],[-1,10],[1,3],[1,1],[2,-3],[2,-5],[3,-4],[3,-3]],[[7982,4838],[3,-7],[2,-3],[3,-2],[3,0],[3,-1],[3,-3],[4,-1],[2,1],[1,1],[1,0],[1,-1],[3,-6],[3,-5],[0,-3],[2,-12],[2,-3],[3,-1],[3,0],[3,-1],[8,-3],[3,1],[3,3],[2,-2],[7,-4],[3,-1],[4,1],[3,1],[2,-1],[2,-2],[1,0],[2,0],[2,3],[2,5],[1,6],[1,7],[1,3],[1,3],[2,2],[1,1],[4,-1],[1,-2],[4,-11],[1,-1],[4,-1],[1,0],[3,3],[2,0],[2,-3],[2,-3],[1,-1],[7,-2],[3,-5],[1,-1],[5,1],[3,-1],[3,-1],[2,-7],[1,-8],[0,-2],[3,-3],[1,-2],[0,-7],[0,-7],[6,-6],[7,-4],[7,0],[7,1],[3,2],[5,2],[1,0],[8,-8],[1,-1],[1,-6],[0,-6],[-1,-15],[-1,-4],[1,-4],[1,-9],[1,-3],[3,-4],[0,-3],[0,-2],[-3,1],[-3,2],[-1,4],[-1,2],[-4,-1],[-6,3],[-7,5],[-12,11],[-3,0],[-3,-1],[-4,-3],[-3,-2],[-3,-1],[-2,1],[-7,3],[-6,1],[-17,1],[-5,3],[-8,1],[-6,2],[-6,3],[-16,15],[-5,4],[-16,7],[-3,1],[-5,-1],[-4,2],[-3,0],[-5,-2],[-1,-2],[-2,-3],[-3,0],[-4,1],[-8,3],[-3,2],[-3,3],[-3,4],[-1,1],[-8,4],[-6,2],[-12,2],[-2,1],[-3,1],[-1,4],[0,4],[1,3],[1,4],[1,4],[-9,7],[-7,4],[-3,0],[-3,0],[-3,0],[-4,0],[-1,1],[-2,1],[-2,-1],[-1,0],[0,3],[0,3],[2,3],[1,1],[1,-5],[0,-1],[2,-1],[3,7],[1,3],[1,8],[1,-1],[2,1],[1,1],[2,20],[2,5],[2,5],[2,1],[2,-3],[5,-1],[3,-2],[3,0],[3,-1],[5,-3],[1,0],[2,1],[2,4],[1,6],[3,-3],[5,-2],[1,-1]],[[8445,4840],[0,-3],[-1,3],[-1,2],[0,3],[1,-1],[1,-4]],[[8347,4821],[-1,-10],[0,4],[-1,9],[0,4],[0,5],[0,12],[1,6],[1,-7],[1,-4],[-1,-19]],[[8130,4849],[0,-2],[-3,0],[0,3],[1,4],[1,0],[2,-2],[-1,-3]],[[8688,4847],[-1,-6],[-2,2],[-1,4],[1,6],[-2,8],[2,0],[1,-3],[2,-8],[0,-3]],[[8742,4855],[0,-2],[0,-4],[0,-4],[-1,-4],[1,-6],[0,-3],[0,-4],[0,-1],[-1,-6],[-1,-2],[-1,-2],[-5,2],[-3,4],[-2,4],[0,1],[-3,5],[0,2],[0,2],[2,1],[2,0],[0,2],[1,8],[-3,5],[-1,2],[1,2],[3,-2],[3,9],[1,2],[0,5],[2,0],[1,0],[1,-4],[1,-2],[-1,-3],[2,-1],[1,-6]],[[8692,4844],[-3,-5],[2,12],[1,5],[2,4],[3,18],[0,-1],[1,-1],[-1,-13],[-4,-10],[-1,-9]],[[7843,4868],[-3,0],[-4,7],[0,2],[1,2],[1,0],[5,-4],[1,-3],[-1,-4]],[[8433,4880],[0,-6],[-1,1],[-1,2],[0,2],[0,1],[0,1],[2,-1]],[[8389,4871],[-2,-2],[-3,7],[-1,5],[0,3],[1,3],[1,0],[-1,3],[2,2],[1,-1],[1,-3],[1,-1],[1,-4],[-1,-12]],[[8406,4880],[-1,-4],[-1,-3],[-2,0],[-1,1],[-2,2],[-1,-2],[-1,0],[-1,3],[1,11],[2,4],[0,4],[-2,9],[1,4],[5,4],[3,4],[2,1],[1,-3],[0,-15],[-4,-12],[1,-8]],[[8421,4922],[0,-13],[0,-3],[-1,5],[-1,1],[0,-1],[-1,-1],[-1,0],[-1,-5],[0,-4],[-1,-3],[0,-10],[0,-3],[2,1],[0,1],[3,-4],[1,-3],[0,-3],[-2,-4],[-2,-1],[-2,1],[0,-1],[-1,-1],[-1,-3],[1,-2],[-2,-7],[-1,-2],[-3,2],[-1,-2],[-1,1],[-2,6],[0,4],[2,3],[0,3],[1,3],[1,4],[1,3],[0,2],[1,7],[0,3],[1,3],[1,7],[0,12],[2,10],[3,3],[1,0],[0,-3],[3,-6]],[[8709,4939],[2,-3],[-3,3],[-5,5],[-1,3],[4,-5],[3,-3]],[[8423,4947],[-3,-7],[-2,0],[-2,5],[-1,5],[0,2],[2,3],[5,-1],[1,-3],[0,-4]],[[8570,4977],[-4,-3],[1,6],[0,1],[3,-1],[0,-3]],[[8562,4972],[0,-2],[-2,-1],[-1,0],[0,2],[0,1],[-1,-1],[-2,-1],[-2,-3],[-1,1],[0,3],[0,1],[2,4],[3,1],[4,4],[2,0],[-1,-2],[0,-2],[-1,-2],[0,-3]],[[8575,4980],[0,-3],[0,-1],[-2,1],[-1,0],[-1,5],[0,1],[2,-2],[1,0],[1,-1]],[[8233,4984],[-1,-10],[-2,6],[2,7],[1,1],[0,-4]],[[8544,4993],[0,-3],[-2,2],[-2,2],[2,2],[2,-3]],[[8230,4961],[-6,-11],[-1,3],[1,11],[-2,7],[0,5],[1,9],[2,6],[3,5],[1,1],[0,-9],[0,-3],[1,-3],[-1,-2],[1,-10],[0,-3],[-1,-3],[1,-3]],[[8523,5006],[5,-5],[1,-2],[0,-4],[1,-2],[1,-1],[2,-4],[1,-4],[-1,-9],[-2,-1],[-2,-2],[-4,-5],[-2,-1],[-2,0],[-1,-2],[-2,0],[-4,3],[-3,3],[-6,6],[-1,2],[-1,3],[-2,6],[-1,4],[0,10],[1,3],[1,1],[3,-3],[3,3],[7,2],[7,0],[1,-1]],[[8554,5015],[-1,-5],[-2,0],[-1,1],[3,3],[1,1]],[[7968,5011],[0,-1],[-2,0],[-1,2],[-1,1],[0,2],[2,2],[3,-2],[-1,-4]],[[7985,5017],[-2,-2],[0,2],[0,1],[0,2],[2,1],[0,-1],[0,-3]],[[8603,5019],[7,-7],[3,-1],[6,1],[2,0],[5,-9],[2,-5],[0,-5],[1,-5],[1,-1],[2,0],[2,-7],[0,-2],[-1,-16],[-7,6],[-6,7],[-2,3],[-7,6],[-1,2],[-1,2],[-3,4],[-6,1],[-2,0],[-1,-1],[0,-2],[0,-4],[-2,-1],[-3,2],[-4,1],[-3,3],[-3,1],[-1,1],[0,2],[0,2],[-1,1],[-1,-1],[-2,-1],[-1,-2],[-2,-6],[-2,-2],[-3,-1],[-1,1],[-2,1],[-4,10],[-1,2],[-1,2],[-2,1],[-1,-2],[-1,-3],[0,-3],[0,-3],[-2,-6],[-2,-3],[1,6],[0,3],[-1,4],[-1,3],[7,17],[2,4],[11,1],[6,-1],[3,1],[2,1],[2,-1],[1,-3],[1,-2],[1,0],[3,2],[3,4],[1,2],[2,0],[2,0],[1,-1],[4,-3]],[[7789,5000],[1,-8],[-3,6],[0,4],[-1,2],[-2,4],[-1,4],[-1,9],[1,2],[1,0],[6,-12],[0,-2],[0,-5],[-1,-1],[0,-3]],[[8005,5011],[0,-6],[-1,-2],[-2,-3],[-1,-2],[-2,0],[-1,3],[0,3],[-3,2],[0,-1],[-1,-3],[-4,-3],[-2,0],[1,5],[-1,4],[0,4],[0,2],[-1,2],[1,3],[0,4],[1,3],[1,10],[5,2],[1,-2],[5,-2],[4,-6],[2,-7],[-2,-10]],[[7783,5026],[-2,-5],[-4,0],[0,3],[0,7],[-1,2],[0,1],[1,4],[0,1],[6,-10],[0,-3]],[[8732,5061],[-1,0],[0,2],[0,3],[1,1],[1,-1],[-1,-5]],[[7773,5049],[0,-2],[-5,5],[-2,2],[-2,5],[1,3],[0,4],[0,1],[2,1],[1,-3],[2,-7],[2,-6],[1,-3]],[[8501,5043],[-1,-1],[-1,3],[-2,8],[-1,3],[-1,8],[1,3],[1,3],[1,0],[1,-2],[-1,-9],[3,-11],[0,-5]],[[8439,5071],[1,-2],[-2,0],[-1,4],[1,3],[1,-5]],[[8500,5081],[8,-2],[-1,-2],[-9,-4],[-3,1],[-10,-2],[-2,0],[0,3],[-1,3],[2,2],[2,0],[5,-1],[9,2]],[[8420,5079],[-2,-5],[0,3],[0,2],[1,2],[1,1],[0,-3]],[[8620,5086],[0,-3],[2,-3],[-1,-5],[0,-1],[0,-2],[1,-2],[-1,-1],[-1,1],[-2,-2],[-1,-2],[-3,-1],[-1,2],[-6,2],[-4,6],[0,1],[7,6],[3,2],[3,0],[3,2],[1,0]],[[8471,5086],[2,-2],[1,0],[1,2],[2,-1],[0,-4],[2,1],[1,-2],[0,-4],[-5,-1],[-3,-3],[-5,3],[-6,-5],[-3,-2],[-3,0],[-2,9],[1,10],[1,1],[2,1],[5,1],[9,-4]],[[8762,5092],[11,-3],[3,1],[7,-2],[5,-3],[9,-1],[3,-1],[2,-3],[-5,-2],[-3,-2],[-4,-1],[-4,1],[-3,-1],[-1,2],[-4,2],[-5,4],[-10,5],[-1,3],[0,1]],[[8026,5091],[-4,-3],[0,5],[2,2],[2,-1],[0,-3]],[[7945,5088],[1,-4],[1,-4],[1,-4],[1,-18],[5,-16],[12,-6],[-2,-3],[-1,-2],[0,-3],[-2,-11],[0,-2],[1,-4],[0,-4],[-1,0],[-2,1],[-2,1],[-1,2],[-1,2],[-2,1],[-2,3],[-4,2],[-3,2],[-2,5],[-1,6],[1,8],[-1,3],[-1,2],[-2,6],[0,7],[-3,3],[-2,2],[-2,1],[-6,-3],[-1,1],[-1,2],[-3,2],[0,4],[1,3],[4,4],[1,2],[1,4],[-1,3],[0,2],[1,3],[2,2],[3,3],[2,-5],[0,-4],[1,-3],[2,4],[-1,7],[3,2],[2,0],[2,-2],[1,-3],[1,-4]],[[8432,5086],[-1,-1],[-2,2],[0,8],[2,2],[0,-3],[1,-2],[1,-2],[-1,-4]],[[8559,5088],[-2,-2],[-1,-1],[-4,2],[-4,-1],[-5,-2],[-3,2],[-2,3],[0,3],[2,8],[3,6],[2,1],[3,-2],[4,-4],[4,-5],[3,-5],[0,-3]],[[8422,5116],[0,-3],[-1,-3],[1,-6],[3,8],[3,1],[1,-2],[1,-1],[1,-3],[-1,-7],[-2,-3],[-2,0],[-1,4],[-2,0],[-1,-8],[0,-1],[-1,-1],[-2,2],[0,1],[2,4],[-1,11],[-1,-2],[-4,-10],[-2,-5],[-1,3],[-1,6],[0,9],[2,6],[2,-1],[5,2],[2,-1]],[[8047,5116],[-6,-6],[-1,0],[-1,2],[0,12],[1,3],[4,0],[2,-1],[2,-2],[0,-4],[0,-2],[-1,-2]],[[8748,5120],[-1,-2],[-2,2],[-1,4],[0,3],[2,3],[1,-3],[1,-3],[1,0],[-1,-4]],[[7754,5081],[-3,0],[-5,7],[-2,3],[0,4],[-5,16],[-1,4],[2,13],[6,3],[1,-2],[1,-6],[3,-11],[1,-5],[1,-3],[0,-2],[0,-1],[2,-7],[2,-4],[0,-6],[-3,-3]],[[8638,5108],[-1,-2],[-3,2],[-2,3],[-1,5],[-1,4],[0,3],[-1,4],[0,2],[6,4],[1,-2],[3,0],[1,-3],[-1,-13],[-1,-7]],[[8635,5139],[0,-3],[-2,-2],[-12,-3],[1,2],[1,2],[1,1],[1,0],[1,0],[1,0],[1,1],[2,-1],[3,1],[0,3],[2,-1]],[[8760,5146],[6,-2],[2,0],[2,-2],[2,1],[2,-1],[5,-9],[2,-6],[4,-5],[2,-1],[-2,-5],[-4,-2],[-1,0],[-3,2],[-2,0],[-3,3],[0,6],[-2,11],[-3,-3],[-3,5],[-1,1],[0,-1],[-2,2],[-1,3],[0,3]],[[8535,5139],[0,-1],[-3,1],[-1,1],[2,8],[1,0],[1,-8],[0,-1]],[[8628,5153],[-2,0],[-3,3],[2,2],[1,0],[1,2],[2,-1],[0,-2],[-1,-4]],[[8384,5160],[1,-2],[0,-3],[-1,1],[-3,0],[-1,-1],[-1,-1],[-1,-1],[1,3],[2,4],[1,0],[2,0]],[[8915,5033],[0,-11]],[[8915,5022],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-5],[-1,-6],[-2,-9],[0,-7],[2,-6],[1,-4],[0,-10],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12]],[[8915,4659],[-1,2],[-4,6],[-4,7],[-2,7],[-2,6],[-11,19],[-3,6],[0,1],[0,2],[1,3],[2,9],[-2,-5],[-3,-5],[-4,0],[-4,-1],[-3,-3],[-4,-1],[-2,1],[-1,4],[-1,3],[0,4],[-1,-6],[-3,-3],[-5,-7],[-1,1],[-1,3],[0,3],[1,3],[1,3],[0,7],[2,4],[1,9],[1,3],[1,3],[-1,3],[-2,1],[-1,2],[-2,6],[-1,2],[-2,2],[-1,3],[2,2],[1,1],[2,0],[3,-1],[1,0],[3,2],[-2,-1],[-1,0],[-6,4],[-4,4],[-3,7],[0,2],[2,1],[5,2],[-1,4],[-2,3],[-1,6],[-2,4],[-3,6],[-2,6],[-2,13],[-2,10],[0,4],[2,2],[-3,1],[-2,1],[1,5],[3,3],[-3,-1],[-2,-1],[-1,0],[-1,0],[-1,2],[0,3],[1,4],[-1,5],[-2,2],[-2,3],[-1,2],[-1,0],[-1,2],[-1,3],[-13,14],[-1,4],[-1,-2],[-1,-1],[-1,3],[-2,1],[-1,0],[-2,1],[-2,1],[-1,0],[-7,4],[-6,7],[-5,3],[-3,4],[-4,3],[-7,3],[-7,2],[-3,0],[-2,-1],[-2,0],[-13,15],[-2,7],[0,4],[1,3],[5,1],[-4,1],[-1,-1],[-3,-2],[-1,0],[-3,1],[-2,3],[-3,-2],[-2,3],[-1,3],[-1,2],[-1,0],[-2,-1],[-1,0],[-2,2],[0,4],[-2,2],[-1,2],[-2,4],[-2,5],[1,10],[0,4],[2,5],[2,6],[-2,0],[-2,-2],[-1,-3],[0,-3],[0,-10],[-2,-3],[-2,0],[1,-6],[-1,-5],[-3,-7],[0,-3],[0,-4],[0,-3],[-5,-9],[-1,-1],[-3,0],[-3,-1],[-2,2],[-1,3],[-1,3],[-1,7],[-1,7],[3,9],[-1,8],[-2,7],[-6,9],[-6,9],[-2,2],[-4,1],[-2,1],[-1,3],[-1,4],[3,2],[4,4],[3,0],[7,-2],[2,-3],[2,-1],[5,8],[4,10],[2,2],[2,0],[2,-1],[4,-3],[3,-2],[2,0],[2,-3],[1,-1],[0,4],[2,6],[2,1],[1,1],[1,1],[0,5],[-3,1],[1,4],[2,2],[0,2],[0,3],[-6,-5],[-6,-2],[-4,0],[-3,0],[-7,-3],[-3,0],[-7,1],[-3,2],[-3,-1],[-3,0],[-2,3],[-3,5],[-1,4],[-2,2],[0,3],[-2,13],[0,9],[-3,0],[-3,1],[-12,9],[-1,-3],[-2,-1],[-2,0],[-1,0],[-2,2],[0,2],[1,6],[2,2],[1,2],[1,3],[2,9],[0,3],[0,3],[0,3],[1,1],[5,3],[9,4],[3,3],[2,4],[2,3],[1,3],[1,2],[8,5],[3,1],[3,-1],[7,-3],[6,-6],[5,-7],[6,-5],[7,-1],[3,1],[4,-1],[1,-2],[2,-4],[0,-3],[-1,-6],[2,-6],[2,-5],[1,-7],[1,-3],[-1,-6],[-1,-3],[-2,-6],[-1,-5],[1,-7],[0,-8],[0,-6],[1,-7],[1,-6],[4,-18],[3,-12],[1,6],[0,8],[1,3],[1,1],[2,-1],[0,-3],[0,-7],[2,-13],[2,-1],[2,2],[0,-4],[0,-7],[1,-6],[1,-2],[3,-5],[2,-1],[4,-1],[3,-1],[4,2],[2,5],[2,4],[6,11],[2,6],[2,8],[0,1],[7,9],[0,3],[1,6],[2,6],[1,3],[6,3],[6,1],[7,6],[2,4],[1,3],[-2,5],[0,3],[2,2],[5,7],[7,7],[5,4],[3,0],[3,-4],[3,-3],[15,-10],[2,-3],[2,-5],[3,-3],[3,-1],[3,-3],[3,-3],[7,-7],[8,-7],[2,-1],[8,0],[2,-1],[1,-2],[1,-1],[9,-1],[2,-2],[1,-2],[1,-5],[6,-1]],[[7901,5165],[3,-6],[0,-2],[-1,-3],[-1,-5],[0,-1],[-2,2],[-2,-4],[-1,7],[-2,4],[2,5],[1,0],[0,-1],[3,4]],[[8543,5165],[3,-8],[-2,-8],[1,-5],[4,0],[1,-2],[1,-2],[0,-3],[-1,-2],[-2,-2],[-3,3],[0,3],[-1,1],[-3,-2],[-1,-1],[-1,4],[1,6],[-2,2],[-3,6],[0,2],[1,4],[0,3],[1,1],[3,-5],[1,4],[1,2],[1,-1]],[[8534,5155],[-2,-1],[-2,0],[0,6],[0,8],[2,1],[3,-2],[-1,-2],[1,-4],[-1,-6]],[[7881,5164],[-4,-2],[-4,1],[1,4],[2,4],[1,0],[3,-3],[2,-3],[-1,-1]],[[8633,5184],[5,-3],[1,0],[7,-6],[1,-3],[-1,-2],[1,-3],[-2,-4],[-1,-1],[-1,2],[-2,1],[-3,-2],[-1,1],[-2,4],[-2,3],[-4,8],[-1,0],[0,-3],[1,-3],[2,-6],[2,-1],[1,1],[1,-3],[0,-4],[-4,-2],[-1,3],[-1,6],[-2,-2],[-1,-2],[-2,5],[-4,1],[-3,3],[1,3],[0,3],[2,2],[2,-2],[2,2],[1,0],[1,1],[4,1],[3,2]],[[7734,5153],[-1,-2],[-3,2],[1,4],[0,5],[2,4],[0,5],[-3,13],[2,0],[1,-1],[2,-9],[2,-5],[-1,-7],[-2,-9]],[[7910,5174],[1,-1],[1,3],[1,-4],[1,-2],[2,-2],[-1,-1],[-1,-1],[-1,-1],[-5,7],[-4,-2],[-3,2],[0,1],[1,4],[1,8],[3,-2],[0,-3],[0,-1],[2,-1],[2,-4]],[[8598,5173],[-1,0],[-1,3],[-3,4],[-2,6],[7,-10],[0,-3]],[[8540,5183],[-1,-1],[0,2],[-1,1],[1,6],[0,1],[0,-4],[1,-5]],[[7907,5187],[0,-1],[-1,1],[-1,1],[0,1],[-3,8],[1,0],[3,-7],[1,-3]],[[7868,5215],[-3,0],[-1,0],[1,6],[1,3],[1,0],[2,-5],[-1,-4]],[[8539,5221],[-1,-1],[-1,0],[0,3],[1,4],[1,0],[0,-1],[0,-3],[0,-2]],[[8537,5229],[-1,-2],[-1,1],[0,3],[0,1],[1,1],[1,0],[0,-4]],[[7873,5222],[-1,-1],[-2,8],[0,4],[1,1],[1,-3],[1,-2],[1,-4],[-1,-3]],[[7883,5230],[0,-2],[-2,4],[0,2],[0,1],[2,-2],[0,-3]],[[7895,5232],[-2,-2],[-2,5],[0,2],[0,1],[1,0],[1,-3],[1,-1],[1,-2]],[[7861,5227],[0,-2],[-1,1],[-6,3],[-2,0],[-4,3],[-2,1],[-1,2],[1,4],[0,2],[1,6],[1,2],[2,-4],[3,-4],[1,-2],[5,-4],[1,-2],[1,-6]],[[7872,5244],[0,-3],[-2,1],[-1,4],[1,2],[1,1],[1,-3],[0,-2]],[[7865,5234],[-1,-2],[-1,1],[-2,2],[-2,3],[-2,3],[-3,2],[-1,1],[-1,0],[1,7],[2,0],[5,-6],[2,-3],[3,-8]],[[7889,5252],[2,-3],[1,2],[0,-2],[0,-2],[-2,-6],[-3,1],[-1,2],[0,2],[1,0],[0,3],[1,0],[1,3]],[[7904,5254],[1,-4],[1,-3],[1,-3],[-1,-5],[-1,-6],[-1,-1],[-2,1],[-1,2],[0,1],[0,2],[-1,1],[1,2],[-1,3],[-4,-2],[-1,0],[0,4],[0,1],[3,5],[2,1],[2,-1],[2,2]],[[7844,5241],[-1,-2],[-1,3],[-2,4],[0,4],[-1,7],[0,4],[1,3],[3,-3],[1,-5],[1,-1],[0,-5],[-1,-5],[0,-4]],[[7707,5268],[6,-16],[3,-2],[3,-8],[1,-2],[-1,-5],[-1,-15],[-2,-4],[-3,2],[0,3],[-3,11],[-4,6],[-1,0],[-1,7],[-2,7],[-6,14],[4,0],[3,3],[0,3],[1,0],[3,-4]],[[7846,5268],[0,-8],[-2,2],[-1,3],[-3,2],[-3,1],[-2,2],[-2,4],[0,1],[0,1],[1,1],[12,-6],[0,-3]],[[8468,5241],[-5,-10],[-2,-4],[-1,-5],[-2,-6],[-3,-5],[-1,-2],[-3,-2],[-1,-1],[-4,-1],[-9,-4],[-3,0],[-4,0],[-6,1],[-1,1],[-2,5],[-3,4],[-2,0],[-3,0],[-17,0],[-6,-1],[-6,-2],[-4,1],[-3,2],[-2,1],[-3,-1],[-11,-3],[-3,1],[-6,3],[-3,1],[-4,-1],[-3,-3],[-1,-3],[-3,-8],[-2,-6],[-1,-7],[-1,-7],[-1,-7],[0,-6],[0,-7],[1,-7],[1,-6],[4,-12],[1,-2],[4,-4],[3,-4],[2,-13],[2,-6],[2,0],[2,0],[3,-1],[3,-1],[3,4],[2,7],[2,5],[4,11],[3,5],[1,1],[2,-1],[1,-2],[2,-3],[3,-1],[3,1],[4,3],[1,2],[1,3],[3,2],[7,0],[3,-1],[7,1],[0,2],[-2,2],[0,2],[1,1],[4,2],[5,2],[3,-1],[2,-4],[1,-3],[1,-4],[-1,-11],[-1,-2],[-2,-1],[-2,1],[-2,6],[-3,2],[-4,-2],[-1,-2],[-2,-2],[-2,-5],[-2,-7],[-4,-10],[-5,-8],[-2,-4],[-3,-2],[-8,-6],[-2,-4],[-2,-5],[-2,-2],[-2,-1],[-1,1],[-4,3],[-1,-2],[0,-4],[2,-2],[2,-4],[2,-6],[2,-1],[2,-2],[2,-2],[2,-5],[3,-13],[1,-6],[2,-6],[6,-9],[0,-2],[0,-3],[1,-3],[2,-5],[0,-4],[-2,-4],[0,-6],[-2,-8],[0,-3],[0,-3],[1,-2],[1,-2],[2,-1],[1,-2],[3,-6],[1,-2],[1,-2],[0,-4],[1,-2],[1,-3],[2,-1],[1,1],[0,1],[2,0],[0,-3],[1,-3],[0,-4],[0,-7],[-1,-2],[-1,0],[-3,3],[0,-2],[0,-2],[-1,-1],[-2,0],[-4,0],[-7,-4],[-3,-3],[-1,-4],[-1,-3],[1,-7],[-1,-3],[-3,0],[-5,1],[-3,2],[-1,2],[-2,4],[-1,6],[1,17],[1,2],[0,2],[1,3],[0,4],[-2,5],[-3,1],[-3,4],[-11,21],[-1,2],[0,3],[1,4],[3,11],[1,2],[0,9],[0,8],[0,7],[-2,5],[-3,1],[-3,1],[-3,-2],[-3,-4],[-6,-7],[-2,-5],[0,-6],[1,-6],[2,-5],[0,-6],[2,-21],[0,-2],[-2,-6],[0,-14],[0,-19],[1,-11],[0,-6],[-3,-14],[-1,-8],[0,-3],[3,-14],[1,-5],[0,-6],[-3,3],[-1,-1],[-2,0],[-3,-1],[-4,0],[-1,-2],[-3,-3],[-1,-2],[-1,0],[-5,5],[-2,5],[-3,5],[0,7],[1,6],[1,7],[2,12],[0,8],[1,6],[1,6],[1,6],[0,22],[0,2],[-4,14],[0,2],[0,4],[0,3],[0,3],[0,2],[-2,3],[-1,1],[-4,-1],[-6,-4],[-2,3],[-2,5],[-1,7],[0,7],[0,7],[1,6],[-1,5],[-1,5],[0,2],[0,2],[2,2],[1,1],[2,2],[3,7],[1,6],[1,7],[1,7],[1,6],[3,6],[0,6],[-1,9],[1,5],[-1,5],[0,5],[2,9],[4,20],[4,10],[1,3],[3,-5],[1,-6],[0,5],[0,5],[-2,12],[-1,23],[0,2],[2,0],[1,2],[1,3],[-2,9],[0,3],[3,11],[2,5],[1,2],[1,8],[1,2],[2,2],[2,5],[1,7],[1,0],[2,-5],[1,-2],[3,-2],[2,2],[1,3],[1,2],[1,3],[1,2],[2,7],[2,6],[1,2],[1,1],[2,1],[2,0],[3,-3],[2,-1],[2,0],[2,-1],[1,-1],[0,-4],[2,-3],[1,-1],[1,-1],[7,1],[7,-3],[9,-1],[3,-1],[3,-3],[4,-4],[1,-1],[2,0],[2,4],[1,1],[2,0],[6,-1],[15,-5],[3,1],[9,10],[4,9],[3,3],[2,4],[0,5],[1,1],[3,2],[1,1],[3,7],[2,5],[1,2],[3,-1],[2,-3],[2,-8],[0,-1],[-3,-4],[0,-2],[-3,-11],[-2,-6],[-2,-5]],[[7824,5304],[2,-5],[0,-3],[-1,-4],[0,-5],[-3,-4],[-3,1],[-1,1],[-2,8],[0,7],[1,3],[3,-1],[3,4],[1,-2]],[[8547,5233],[2,-2],[2,1],[1,2],[1,4],[1,6],[2,4],[2,1],[1,1],[0,5],[0,5],[2,4],[5,7],[4,3],[4,0],[0,-2],[0,-4],[1,-5],[-1,-15],[-1,-3],[-4,-5],[-5,-4],[-1,-2],[-1,-4],[0,-4],[4,-5],[6,-6],[1,-2],[1,-4],[0,-4],[1,-3],[2,-1],[2,-2],[1,-3],[-10,7],[-3,3],[-3,1],[-3,1],[-3,2],[-4,1],[-1,-2],[-1,-4],[0,-4],[0,-5],[0,-4],[0,-5],[2,-18],[3,-13],[5,-14],[2,-5],[3,-5],[-5,2],[-1,4],[-5,5],[-1,3],[-3,13],[-1,3],[-3,4],[-2,4],[0,4],[0,5],[0,7],[0,6],[1,8],[-1,3],[-2,3],[-2,6],[0,7],[0,4],[1,4],[1,3],[0,3],[-3,4],[-2,12],[0,7],[3,12],[0,6],[0,4],[1,4],[1,8],[3,7],[5,10],[2,2],[2,1],[0,-2],[0,-2],[-4,-10],[0,-2],[0,-5],[1,-2],[2,-5],[0,-7],[0,-7],[0,-7],[-1,-3],[-2,-7],[-7,-9],[0,-2],[0,-2],[1,-3],[1,-2]],[[7703,5303],[0,-1],[-3,6],[-3,3],[1,1],[3,-1],[1,0],[1,-3],[0,-5]],[[8567,5302],[-4,-1],[-1,3],[-1,12],[3,10],[4,6],[2,1],[1,0],[3,-7],[-2,-14],[-2,-7],[-3,-3]],[[8483,5337],[-1,-2],[-1,7],[1,3],[1,-1],[1,-1],[-1,-3],[0,-3]],[[7679,5320],[-2,-1],[-2,1],[-1,4],[-7,9],[-3,0],[-1,3],[-2,1],[-3,6],[0,4],[2,1],[1,4],[2,-2],[3,-6],[3,-2],[1,-1],[1,-4],[6,-8],[1,-3],[1,-3],[0,-3]],[[8024,5351],[-1,-3],[-2,2],[2,6],[1,1],[0,-6]],[[7937,5349],[-1,-1],[-1,2],[1,3],[-1,2],[0,2],[0,3],[1,-1],[1,-2],[1,-1],[1,0],[0,-1],[-1,-4],[-1,-2]],[[7952,5366],[0,-4],[-2,2],[-1,4],[1,2],[1,-1],[1,-3]],[[8267,5373],[0,-2],[-2,5],[-1,3],[0,2],[3,1],[1,-2],[-1,-7]],[[8490,5382],[-1,-2],[-3,3],[0,5],[-1,3],[-1,2],[0,3],[0,3],[2,-4],[2,-6],[1,-5],[1,-2]],[[8523,5401],[-1,-1],[-1,2],[0,1],[0,2],[0,1],[2,-3],[0,-1],[0,-1]],[[8519,5407],[0,-2],[-1,5],[-1,7],[1,-3],[2,-5],[-1,-2]],[[8274,5425],[1,-6],[0,-2],[-5,-3],[-3,7],[0,3]],[[8267,5424],[3,0],[4,1]],[[8008,5396],[-4,-2],[-2,3],[2,4],[1,0],[1,1],[0,1],[-4,3],[-2,2],[-1,5],[0,4],[6,9],[1,1],[0,-4],[4,-10],[0,-6],[0,-2],[-2,-9]],[[8265,5424],[-2,-2],[-1,-3],[3,-5],[0,-4],[2,-3],[2,-5],[1,-1],[0,-2],[1,-3],[-2,-2],[-2,-1],[-2,3],[-2,3],[0,-4],[-1,-2],[-5,0],[-3,0],[-3,-1],[1,0],[2,-1],[5,-10],[1,-3],[-2,-7],[1,-3],[2,-2],[2,-3],[2,-1],[1,-2],[0,-3],[1,-3],[-2,-1],[2,-1],[2,-2],[-1,-2],[-1,-1],[1,-2],[2,-1],[1,-2],[1,-4],[2,-8],[4,-9],[1,-4],[0,-3],[-1,-3],[-2,-3],[-2,-4],[0,-2],[-3,-1],[1,-2],[1,-2],[2,-6],[4,-9],[2,-4],[9,-13],[5,-5],[6,-13],[3,-3],[0,-4],[-2,-5],[-4,-3],[-6,-1],[-6,2],[-4,1],[-2,3],[-3,7],[-2,3],[1,-4],[0,-4],[0,-4],[-1,-3],[-2,-3],[-2,-2],[-1,-1],[-5,-23],[-1,-6],[-2,-25],[0,-7],[2,-13],[1,-7],[0,-3],[0,-3],[-1,-1],[-5,-4],[-3,-4],[-3,-4],[-2,-6],[-2,-5],[-2,-2],[-2,1],[-1,2],[-1,3],[-1,5],[0,-3],[0,-3],[0,-4],[1,-3],[-1,-4],[-1,-2],[-3,-3],[-1,-3],[0,-5],[-1,-2],[-1,-2],[-4,-5],[-1,-2],[-1,-2],[2,0],[2,0],[0,-5],[1,-3],[-1,-7],[-3,-5],[2,-2],[1,-1],[3,-1],[1,-6],[0,-6],[-1,-6],[-2,-1],[-1,1],[-2,0],[-1,-2],[0,-3],[2,1],[0,-7],[-1,-7],[0,-4],[-2,-4],[-1,-1],[-2,3],[0,-3],[0,-2],[3,-6],[-2,-2],[-1,-2],[0,-2],[-3,-7],[-1,-5],[-1,-5],[-1,-4],[-19,-18],[-16,-15],[-1,1],[-1,2],[0,23],[-2,13],[-1,6],[-2,-6],[-1,1],[-2,1],[-1,2],[0,3],[1,7],[-1,-4],[-2,-3],[-1,1],[-2,1],[0,3],[-1,0],[-3,-7],[-5,-3],[-2,0],[-2,2],[0,5],[0,5],[-1,3],[-1,1],[-1,-1],[-4,-2],[-1,0],[0,-1],[-9,18],[-2,-15],[-6,-8],[-4,-4],[-4,2],[-5,3],[-4,-4],[-5,-9],[-1,-1],[-2,0],[-1,1],[1,7],[0,6],[-1,15],[0,3],[-1,4],[-2,2],[-1,-2],[-1,-3],[-4,1],[-3,2],[-3,-1],[-6,-6],[-3,-1],[-2,1],[-1,3],[0,3],[2,2],[-3,-1],[-2,-3],[-1,-2],[-1,1],[-2,6],[-6,-2],[0,-1],[-2,-2],[-1,1],[-1,2],[0,14],[-3,26],[-1,14],[0,3],[-3,5],[0,6],[1,6],[1,7],[-1,7],[-1,7],[-1,6],[-2,4],[-2,6],[-3,3],[-6,5],[-4,-1],[-1,2],[-1,2],[1,5],[1,3],[1,0],[0,2],[-3,4],[-3,4],[0,3],[-1,3],[0,8],[1,4],[1,3],[0,7],[2,3],[0,1],[-1,1],[-1,3],[-1,2],[-2,5],[-4,6],[0,10],[-1,16],[1,6],[1,13],[2,4],[1,1],[2,2],[-1,0],[-1,0],[-2,-1],[2,12],[0,3],[3,6],[3,6],[1,7],[1,6],[7,6]],[[8044,5301],[-2,-8],[0,-3],[1,-2],[2,-2],[0,-9],[2,-5],[3,-5],[1,-3],[2,-3],[2,-3],[1,-3],[2,-3],[6,-11],[2,-3],[2,-3],[1,-2],[3,1],[9,8],[1,1],[3,1],[5,0],[6,-3],[2,0],[1,2],[3,-1],[2,-1],[1,1],[3,6],[4,2],[2,5],[1,6],[0,6],[2,2],[3,2],[4,3],[12,0],[2,-1],[0,-3],[0,-2],[0,-2],[2,0],[2,-1],[6,-5],[3,-1],[1,0],[3,-4],[2,1],[2,3],[2,4],[2,3],[3,2],[3,-1],[4,2],[4,1],[3,-3],[1,1],[1,3],[1,6],[1,4],[1,8],[0,1],[2,1],[1,2],[0,2],[1,3],[0,2],[-1,2],[-1,6],[0,3],[1,2],[1,2],[4,4],[3,6],[2,2],[1,2],[0,3],[-2,2],[-1,2],[0,3],[0,2],[0,2],[0,2],[0,2],[1,4],[2,4],[1,3],[2,-2],[2,1],[2,2],[1,5],[0,3],[0,2],[1,7],[0,1],[1,5],[0,4],[0,7],[0,6],[0,12],[1,2],[1,6],[1,6],[3,4],[2,4],[1,1],[1,0],[3,-3],[3,4],[3,0],[2,0],[2,-2],[1,-1],[3,4],[1,-1],[1,-1],[1,0],[2,1],[4,-1],[7,0],[5,-3],[5,-6],[2,-1],[1,0]],[[8522,5416],[-1,-1],[-2,0],[0,3],[2,6],[1,5],[-2,1],[-1,4],[0,4],[1,8],[2,-1],[1,-3],[1,-6],[1,-5],[-2,-6],[-1,-9]],[[7680,5485],[3,-1],[6,4],[4,-1],[3,-2],[3,-1],[7,1],[2,0],[1,-1],[1,-2],[3,-8],[6,-9],[2,-6],[0,-7],[1,-1],[6,-13],[1,-5],[-1,-8],[2,-5],[6,-6],[4,-4],[1,-2],[0,-3],[2,-5],[3,-2],[7,-8],[11,-15],[6,-8],[4,-11],[2,-5],[2,-6],[3,-9],[5,-10],[1,-3],[1,-5],[2,-4],[2,-4],[2,-3],[2,-1],[4,-8],[2,-2],[-1,6],[-1,5],[0,3],[0,3],[1,2],[2,1],[3,-2],[5,-9],[2,-5],[2,-8],[1,-7],[2,-4],[3,-1],[3,-1],[3,-2],[6,-10],[2,-5],[2,-6],[1,-6],[1,-8],[0,-1],[4,-9],[3,-3],[2,-2],[8,-2],[3,-3],[2,-5],[1,-5],[-1,-4],[-7,-7],[-6,-5],[6,2],[3,2],[3,3],[3,4],[5,5],[2,1],[2,0],[2,-2],[2,-5],[3,-6],[2,-6],[1,-7],[-2,-4],[-3,-3],[-5,-7],[0,-3],[1,-2],[-1,-5],[2,-3],[0,-3],[-2,-4],[1,-2],[2,-11],[1,-2],[4,-5],[6,-6],[4,-2],[4,-2],[1,0],[3,1],[1,-2],[1,-10],[1,-7],[0,-13],[2,-6],[-1,-7],[2,-6],[3,-4],[3,-3],[2,-3],[0,-4],[-1,-4],[-1,-3],[-3,-6],[-1,-2],[0,-7],[0,-3],[2,0],[1,2],[4,8],[1,2],[1,1],[2,1],[7,0],[3,-1],[3,-3],[2,-4],[9,-23],[4,-12],[0,-3],[0,-4],[0,-2],[-4,-9],[-1,-2],[-1,-9],[1,-7],[1,-3],[1,-3],[0,-3],[-3,-14],[0,-2],[2,-22],[0,-7],[-1,-7],[1,-13],[-2,-38],[-1,-2],[-1,-6],[-2,0],[-2,1],[-1,2],[-1,3],[-1,2],[-4,7],[-2,-1],[-5,-9],[-1,-1],[-1,1],[-3,3],[-8,9],[-1,-3],[0,-4],[2,-10],[0,-5],[-1,0],[-1,0],[-4,6],[-3,6],[-3,9],[-3,4],[-2,5],[-7,17],[-1,3],[-10,12],[-2,3],[-3,5],[-3,5],[-6,7],[-11,19],[-4,10],[-5,17],[-2,4],[-9,13],[-4,8],[-2,4],[-5,16],[-1,5],[-2,5],[-2,3],[-3,5],[-5,14],[-1,5],[-1,6],[0,12],[-10,37],[-3,11],[-2,16],[-1,2],[-6,14],[-2,4],[-2,5],[-2,5],[-4,16],[-1,4],[-2,4],[-7,6],[-3,3],[-2,5],[-2,6],[-1,13],[-4,20],[-3,27],[-3,12],[-3,9],[-1,2],[-13,17],[-2,3],[-3,1],[-3,1],[-3,5],[-1,7],[-1,11],[0,6],[-1,4],[-5,7],[-3,6],[-1,6],[-2,5],[-6,18],[-2,4],[-3,3],[-8,4],[-2,3],[-3,9],[-3,5],[-6,11],[-12,23],[-2,6],[-2,6],[-1,6],[-5,18],[0,4],[1,3],[0,4],[-1,3],[0,2],[2,2],[3,2],[3,0],[4,-1],[3,-2],[2,-4],[6,-9],[3,-3],[3,-2],[7,-2]],[[7648,5519],[0,-2],[-2,1],[-2,5],[1,1],[1,0],[2,-2],[0,-2],[0,-1]],[[4877,8305],[-6,-8],[-2,2],[-2,-1],[1,3],[1,6],[2,2],[3,7],[3,2],[0,-1],[1,0],[1,-7],[-1,-3],[-1,-2]],[[7607,5577],[-1,-4],[-4,14],[-1,1],[0,7],[1,3],[3,3],[1,-2],[2,-14],[-1,-8]],[[7603,5608],[-3,-6],[-1,3],[1,3],[1,1],[1,2],[1,-3]],[[7595,5638],[-2,-1],[-1,3],[-1,3],[1,2],[1,1],[2,-4],[0,-3],[0,-1]],[[7597,5648],[-1,-2],[0,2],[0,1],[-1,2],[0,3],[1,4],[1,-1],[0,-3],[0,-6]],[[7029,5660],[0,-1],[-1,0],[0,1],[1,0],[0,2],[0,1],[0,-2],[0,-1]],[[7586,5659],[1,-2],[-1,0],[-2,3],[1,3],[0,2],[1,-6]],[[7577,5710],[-2,0],[0,2],[0,2],[0,1],[1,1],[1,0],[0,-4],[0,-2]],[[7569,5792],[-1,-2],[-3,1],[0,6],[0,6],[0,2],[2,5],[2,1],[1,-5],[1,-6],[-2,-8]],[[7574,5839],[-1,-1],[-2,2],[1,2],[1,5],[1,-3],[0,-3],[0,-2]],[[7583,5877],[1,-8],[-2,4],[-1,2],[1,2],[1,0]],[[7575,5925],[-1,-4],[0,8],[0,1],[1,0],[0,-5]],[[7575,5848],[-1,-1],[-1,1],[-2,11],[-1,6],[0,3],[1,3],[1,1],[0,4],[1,5],[1,5],[0,1],[2,0],[1,1],[-1,4],[-1,2],[0,2],[0,10],[0,4],[1,4],[-1,6],[1,2],[1,4],[1,7],[-1,2],[2,11],[0,7],[1,8],[3,3],[1,0],[0,-6],[1,-2],[-2,-4],[2,-5],[-1,-2],[0,-3],[-1,-4],[-2,-2],[-1,-5],[-1,-2],[3,-5],[0,-18],[-1,-5],[-2,-1],[0,-12],[0,-3],[-2,-5],[0,-3],[-1,-2],[0,-3],[1,-2],[0,-2],[-1,-7],[0,-7],[-1,-6]],[[7186,7020],[0,1],[-2,4],[2,-5]],[[7203,6975],[1,-1]],[[7219,6963],[0,0]],[[7219,6963],[5,-6]],[[7250,6921],[-2,1],[-1,0],[-2,-2],[-1,-1],[-3,-8],[-2,-2],[-2,-3],[-4,-10],[-3,-9],[-1,-8],[0,-7],[-1,-7],[-2,-4],[-1,-1],[-1,-6],[-1,-7],[0,-3],[3,-3],[2,-3],[3,-3],[2,-3],[2,-1],[0,2],[1,2],[2,-1],[2,-3],[2,-3],[4,-4],[4,-4],[4,-4],[1,-3],[1,-3],[2,-3],[5,-7],[4,-5],[3,-3],[3,-3],[1,0],[2,2],[1,1],[1,-1],[2,-2],[5,-6],[5,-5],[5,1],[1,-1],[1,-5],[0,-4],[6,-3],[4,-1],[4,-3],[2,-2],[2,3],[0,2],[2,1],[3,-1],[6,-3],[2,-1],[2,3],[3,2],[2,1],[4,-3],[7,-5],[4,-3],[0,-3],[1,-2],[0,-7],[1,-3],[7,-6],[2,-3],[2,-1],[1,0],[1,-1],[0,-4],[1,0],[1,-1],[2,-1],[4,3],[3,3],[2,-1],[2,-3],[0,-4],[1,-4],[1,-2],[2,0],[4,3],[4,-2],[3,-1],[3,-2],[2,-1],[3,-3],[5,-4],[1,1],[7,6],[1,0],[1,-7],[3,-2],[3,-2],[3,4],[3,-1],[4,-1],[3,2],[3,1],[4,-4],[0,1],[1,2],[2,9],[1,8],[0,5],[-1,7],[-3,9],[-1,3],[1,16],[2,9],[1,4],[1,6],[0,3],[0,3],[-1,1]],[[7703,6809],[-1,-4],[0,-3],[1,-4],[0,-2],[0,-3],[-1,-2],[-2,-1],[-2,-3],[-3,-4],[-2,-4],[-2,-3],[-1,-3],[0,-4],[1,-5],[6,-16],[0,-2],[-2,-1],[-3,2],[-2,2],[-2,7],[-2,2],[-2,0],[-10,-3],[-3,-1],[-3,-3],[-3,-5],[-2,-4],[-2,-2],[-2,-4],[-8,-11],[-4,-5],[-3,-2],[-2,-2],[-1,-4],[-1,-3],[0,-8],[0,-9],[1,-5],[1,-2],[0,-1],[-1,-3],[-2,-3],[0,-2],[-1,-8],[-1,-4],[-3,-6],[-2,-4],[-3,-4],[-1,-3],[-2,-5],[0,-4],[0,-2],[0,-1],[1,-2],[2,-1],[1,-3],[0,-2],[-1,-7],[-2,-10],[-3,-7],[-3,-7],[0,-3],[-3,-8],[-2,-12],[-1,-8],[-1,-6],[-2,0],[-1,2],[-5,2],[-2,2],[-2,2],[-2,-1],[-2,-1],[-2,0],[-1,0],[-3,5],[-1,-3],[2,-14],[1,-5],[0,-9],[-1,-11],[0,-12],[-1,-3],[-1,-3],[-1,-1],[-2,2],[-1,-1],[0,-2],[0,-5],[-1,-6],[-1,-5],[0,-5],[0,-5],[2,-10],[0,-4],[0,-4],[-1,-1],[-1,0],[-1,-1],[-1,-3],[-1,-8],[-2,-1],[-1,2],[-3,5],[-1,2],[-1,0],[0,-2],[-1,-3],[-1,-2],[-1,-2]],[[7473,6456],[-1,-9],[-2,0],[2,-6],[1,-4],[0,-6],[-2,-1],[-2,1],[-1,5],[-1,-5],[-3,-4],[0,2],[-1,3],[0,4],[1,15],[0,2],[-1,1],[-1,1],[0,3],[-3,-17],[1,-7],[0,-3],[-4,-2],[-4,6],[0,2],[-1,-3],[0,-5],[-4,1],[-2,3],[1,6],[3,14],[0,6],[-3,5],[-2,2],[-2,7],[1,-7],[1,-3],[2,-2],[2,-3],[-1,-4],[-2,-3],[-3,-10],[-3,-6],[-4,-4],[-13,-6],[-3,-3],[-4,-8],[-3,-7],[0,-8],[1,-8],[1,-12],[1,-3],[-1,-5],[-3,-4],[-2,-7],[1,-4],[-1,-2],[-7,-8],[-1,-5],[-2,-5],[-3,3],[-1,0],[2,-4],[0,-2],[-1,-2],[-2,-1],[-10,-6],[-8,-6],[-2,0],[1,2],[1,2],[0,6],[-2,1],[-1,1],[-6,-8],[-2,-8],[0,-2],[2,1],[4,4],[2,-1],[0,-2],[-6,-7],[-13,-22],[-1,-4],[-1,-5],[-2,-4],[-5,-12],[-7,-16],[-3,-7],[-12,-12],[-2,-4],[-5,-13],[-6,-10],[-6,-8],[-10,-11],[-7,-10],[-2,-7],[0,-3],[1,-3],[1,-3],[0,-3],[-1,-4],[0,-2],[-2,-6],[-3,-5],[-11,-9],[-1,1],[-9,1],[-3,-1],[-1,-4],[-3,-18],[-3,-4],[-1,-5],[0,-3],[-2,1],[-1,1],[-2,-1],[-1,6],[-2,1],[-2,0],[-7,-6],[-2,-4],[-6,-23],[-1,-14],[1,-16],[2,-13],[0,-5],[0,-8],[-1,-3],[0,-5],[0,-8],[3,-12],[0,-5],[0,-5],[2,-11],[-1,2],[-1,4],[-2,7],[-3,-7],[2,-4],[5,-5],[1,-5],[-3,-38],[-3,-14],[-2,-9],[-2,-3],[-3,-15],[-3,-17],[0,-6],[1,-8],[-1,-4],[-2,-4],[3,2],[1,-4],[0,-4],[0,-25],[0,-26],[-2,-1],[-3,0],[-2,1],[-2,1],[-3,-2],[-3,-2],[-1,-5],[0,-8],[-7,-20],[-2,-7],[-1,-7],[1,-3],[2,-4],[3,-1],[4,-1],[3,-2],[1,-4],[-5,4],[-7,1],[-15,-10],[-4,-6],[-3,-6],[-1,-13],[-1,-9],[-1,-7],[-8,-11],[-6,-4],[-1,-3],[-6,4],[-7,10],[-3,5],[-9,25],[-2,4],[-2,10],[0,4],[-1,2],[-1,1],[0,2],[-3,12],[0,13],[-2,15],[1,-1],[2,-5],[1,-7],[0,-10],[1,-1],[1,1],[-3,22],[-3,6],[-1,4],[0,4],[0,2],[-2,8],[-1,4],[-5,22],[-2,16],[-3,17],[-2,6],[-4,14],[-3,6],[-3,9],[-2,3],[-1,2],[-7,29],[-2,17],[-2,7],[-1,6],[-2,25],[0,4],[-1,5],[-1,11],[-3,11],[-1,7],[0,3],[-2,11],[-1,5],[-1,4],[-1,5],[-2,3],[-4,11],[-1,3],[-3,7],[-1,13],[-3,6],[4,0],[-2,5],[-1,3],[-1,2],[1,5],[-3,0],[-1,3],[-2,9],[-4,10],[0,6],[-4,18],[-2,42],[-3,19],[0,6],[-3,16],[-1,11],[-1,10],[0,6],[-1,12],[-1,4],[-1,2],[1,5],[2,9],[1,5],[-1,8],[-2,-8],[-2,-2],[0,6],[0,8],[-1,2],[1,2],[5,-1],[-6,5],[0,3],[-1,2],[2,4],[-3,3],[0,11],[-1,2],[0,2],[1,14],[5,28],[0,7],[0,8],[-1,8],[-1,7],[0,2],[-2,1],[-1,3],[-2,11],[1,3],[2,2],[-2,0],[-2,0],[3,5],[3,4],[6,5],[2,3],[-4,-3],[-3,-1],[-9,0],[2,11],[1,3],[2,2],[-3,0],[-2,1],[1,10],[2,2],[2,1],[3,1],[-3,2],[-3,1],[-4,-2],[-3,2],[-5,0],[2,-2],[2,-3],[-1,-6],[-1,-3],[-2,-3],[-2,-4],[-1,-3],[-1,-2],[2,-2],[2,-1],[1,-3],[1,-4],[0,-7],[-5,-18],[-1,-4],[-13,-10],[-4,-6],[-11,-8],[-4,-1],[-4,1],[-7,6],[-10,15],[-2,5],[-8,18],[-6,10],[-4,10],[-6,8],[-5,12],[-1,6],[1,5],[1,3],[3,-1],[1,-5],[2,-2],[1,-1],[7,7],[3,0],[2,4],[3,-1],[5,6],[2,0],[3,1],[4,14],[3,9],[2,2],[0,2],[-1,3],[-1,-1],[-1,-3],[-1,-3],[-1,-2],[-2,2],[-2,0],[-2,-1],[-7,-6],[-3,-4],[-3,-1],[-11,5],[-12,12],[-5,8],[-3,10],[-3,11],[1,4],[5,7],[4,6],[-4,-3],[-4,-3],[-2,-3],[-2,-5],[-3,-1],[-1,8],[-1,7]],[[6893,6558],[2,2],[1,2],[3,1],[3,1],[2,0],[4,0],[0,17],[1,2],[0,1],[1,0],[1,-3],[1,1],[1,1],[3,-1],[1,1],[2,-1],[4,0],[5,0],[4,0],[2,-3],[2,-3],[2,0],[4,0],[2,1],[2,3],[0,3],[6,4],[5,3],[2,0],[0,-2],[0,-3],[1,-3],[2,-2],[2,0],[1,0],[1,1],[2,5],[2,1],[1,0],[2,2],[0,2],[-1,1],[-1,2],[0,2],[0,3],[0,3],[1,2],[1,2],[-1,4],[-2,8],[-2,9],[-2,9],[-3,7],[-1,5],[0,12],[0,2],[-1,2],[-1,0],[-2,-1],[-2,0],[-3,0],[-2,1],[-4,12],[-1,5],[0,5],[1,8],[1,7],[0,8],[0,2],[-1,2],[-2,2],[-4,0],[-5,2],[-3,5],[-3,2],[-1,2],[0,2],[1,8],[1,10],[1,3],[1,3],[1,2],[2,3],[5,9],[4,13],[3,9],[1,3],[2,2],[2,2],[2,3],[2,0],[3,-2],[1,-3],[1,-6],[1,-4],[1,-2],[2,-1],[2,0],[9,7],[3,1],[7,1],[4,3],[5,2],[0,5],[2,8],[5,10],[1,4],[2,8],[1,8],[2,3],[8,8],[7,8],[2,3],[5,16],[3,11],[0,3],[2,10],[2,9],[2,2],[5,4],[5,3],[2,4],[1,4],[0,3],[-1,4],[0,2],[0,3],[3,5],[6,14],[3,7],[1,0],[4,4],[3,4],[0,2],[0,3],[-2,1],[-1,3],[1,4],[1,12],[0,4],[-2,10],[0,3],[1,3],[3,5],[2,3],[10,8],[1,1],[4,2],[2,4],[0,4],[-1,2],[-2,3],[-3,3],[-4,3],[-5,-1],[-3,2],[-1,2],[0,5],[0,9],[-1,0],[-1,-1],[-3,1],[-3,0],[-2,3],[1,3],[0,3],[-1,4],[0,1],[-2,1],[-3,3],[-2,4],[-1,2],[0,2],[0,1],[1,4],[2,5],[1,4],[0,3],[0,2],[-2,3],[-2,2],[-1,2],[0,3],[1,4],[2,3],[4,3],[1,3],[0,3],[-1,0],[-3,0],[-5,1],[0,2],[-1,2],[0,1],[1,2],[1,3],[0,3],[-1,3],[-3,2],[-1,3],[1,2],[1,4],[1,3],[2,7],[2,1],[4,3],[3,2],[6,-2],[2,-1],[6,-2],[4,-2],[5,0],[2,0],[2,-2],[5,-4],[4,-2],[3,0],[5,3],[2,3],[3,4],[3,0],[8,5],[2,-1],[2,0],[3,2],[1,4],[0,2],[1,1],[3,2],[3,3],[1,4],[1,3]],[[7140,7206],[3,4],[3,3],[4,4],[4,5],[4,3],[2,3]],[[7160,7228],[1,0]],[[7197,7098],[0,-4]],[[7200,7059],[0,-3]],[[7691,4481],[0,1],[0,1],[1,0],[0,-1],[-1,-1]],[[7689,4482],[1,0],[0,-1],[-1,1],[0,2],[0,1],[0,-1],[0,-1],[0,-1]],[[7936,4579],[-1,-4],[-1,3],[-2,0],[0,3],[2,1],[1,1],[1,-4]],[[7013,4759],[-1,-2],[-1,-1],[0,5],[-2,4],[1,0],[1,-2],[1,-5],[0,1],[0,2],[0,2],[0,2],[-1,2],[1,1],[1,-2],[0,-2],[0,-5]],[[4723,8289],[0,-2],[-2,3],[-1,2],[-6,1],[3,2],[1,-1],[4,0],[1,-1],[0,-4]],[[4827,8299],[1,-2],[0,-2],[-2,-1],[-2,1],[-1,-2],[0,-2],[1,-4],[1,-2],[1,-6],[1,-6],[2,-3],[0,-5],[0,-2],[0,-4],[0,-1],[0,-4],[2,-8],[1,-4],[0,-10],[-1,-3],[-2,-4],[-1,-4],[-1,-4],[0,-7],[-4,-8],[-1,-2],[-2,-1],[4,-6],[-3,-2],[-4,-1],[-4,1],[-2,0],[-2,-2],[-1,-1],[-1,1],[-1,4],[-1,-5],[-2,-1],[-4,0],[-6,-1],[-3,-1],[-1,-3],[0,-2],[-1,-1],[-1,-1],[-5,-2],[-1,-1],[-2,-4],[-3,-2],[-3,-1],[-2,3],[-1,1],[-1,1],[-3,0],[1,-1],[1,-2],[0,-3],[0,-3],[-2,-2],[-2,0],[-3,-3],[-4,-1],[-2,-3],[-14,-5],[-2,1],[-2,1],[-2,-1],[-6,-2],[-3,0],[4,7],[4,4],[1,1],[-2,0],[-8,-2],[-4,-2],[-3,-1],[2,3],[4,4],[2,2],[1,1],[2,3],[4,3],[-14,-6],[-3,0],[-1,2],[-3,-1],[-1,4],[4,6],[3,3],[3,1],[2,3],[1,2],[-1,1],[-8,-1],[-4,1],[0,2],[1,2],[4,4],[2,0],[2,0],[2,-1],[1,-1],[5,0],[-2,3],[0,5],[-2,1],[2,2],[2,2],[4,4],[1,1],[7,1],[8,3],[8,3],[-4,2],[-2,2],[-3,-5],[-2,-2],[-6,-1],[-2,1],[-3,2],[-1,-1],[-1,-1],[-4,-3],[-4,0],[5,4],[6,8],[2,2],[2,5],[-1,1],[-1,1],[4,9],[2,2],[3,0],[2,1],[1,0],[1,1],[1,2],[-2,2],[-3,1],[-10,-1],[-1,0],[-1,1],[-1,1],[0,3],[-1,1],[-2,0],[-2,-1],[-1,0],[-2,1],[2,3],[-2,1],[-3,-1],[-3,1],[0,2],[1,2],[-1,2],[0,2],[1,1],[2,0],[3,2],[5,0],[-4,2],[-2,1],[0,3],[0,1],[5,4],[4,1],[0,2],[0,2],[-4,1],[-5,-2],[1,5],[1,3],[0,3],[0,3],[-2,-2],[-1,4],[-1,3],[-3,-2],[0,4],[1,2],[2,1],[2,0],[3,0],[3,1],[4,1],[7,-1],[4,-5],[2,1],[2,3],[0,1],[8,-2],[4,-2],[1,1],[0,4],[-2,2],[2,3],[2,3],[2,1],[3,1],[2,1],[1,5],[2,3],[-9,-2],[-9,4],[1,3],[2,2],[3,1],[1,2],[1,1],[3,3],[-1,5],[0,3],[2,2],[1,3],[1,2],[3,1],[4,2],[1,0],[5,0],[1,-1],[0,4],[3,0],[1,0],[0,-3],[1,-1],[1,-3],[-1,-2],[-2,-2],[2,-2],[-2,-3],[2,1],[3,3],[0,3],[-1,3],[-1,3],[1,3],[1,2],[5,1],[-2,3],[2,1],[1,-1],[3,-3],[2,-2],[3,-2],[-2,-3],[-4,-2],[-1,-3]],[[6560,6734],[-2,-6],[-4,-6],[-2,2],[-1,-1],[-3,-2],[-2,0],[-4,-4],[-3,-2],[-2,0],[-1,0],[-1,3],[0,1],[2,0],[5,3],[6,6],[1,3],[-1,4],[0,1],[4,-2],[5,4],[4,1],[2,-3],[-3,-2]],[[6357,7398],[0,-3],[1,-14],[0,-8],[1,-7],[2,-6],[2,-7],[2,-3],[6,-5],[3,-1],[7,-1],[7,-2],[4,-3],[1,-1],[1,-2],[4,-11],[5,-8],[11,-12],[5,-4],[18,-7],[12,0],[33,14],[11,4],[4,0],[-2,-3],[-5,-2],[3,-2],[4,0],[2,0],[1,2],[0,3],[0,3],[-2,13],[-1,10]],[[6497,7335],[8,-1],[3,1],[4,3],[3,2],[2,1],[2,1],[1,2],[3,13],[1,3],[5,7],[4,4],[5,4],[5,3],[7,0],[6,-1],[4,0],[1,0],[1,0],[1,1],[1,6],[1,1],[2,2],[3,0],[4,0],[2,0],[4,-2],[5,0],[3,0],[2,-2],[1,-3],[1,-2],[0,-4],[0,-2],[1,-1],[1,-1],[3,-2],[5,-1],[5,-2],[3,-2],[3,-3],[5,-7],[1,-1],[2,0],[2,0],[3,3],[3,-3],[1,1],[3,1],[3,-2],[9,-7],[1,0],[1,-1],[0,-1],[1,-2],[0,-7],[3,-4],[3,-5],[3,-2],[8,-6],[3,-4],[3,-8],[4,-10],[0,-1],[11,0],[11,0],[1,-4],[0,-8],[1,-8],[1,-6],[0,-5],[-1,-3],[-1,-3],[0,-1],[1,-2],[2,-4],[0,-6],[-1,-4],[0,-2],[1,-3]],[[6697,6919],[-7,-14],[-1,-1]],[[6689,6904],[6,-12],[3,-7],[5,-9],[0,-3],[0,-4],[5,-14],[2,-8],[1,-5],[4,-7],[3,-7],[4,-3],[3,-1],[6,-4],[3,-2],[3,-8],[4,1],[1,0],[1,0],[0,-3],[-1,-11],[1,-12],[1,-17],[0,-3],[-1,-5],[0,-4],[-1,-2],[1,-1],[1,-1],[3,0],[7,2],[1,-1],[1,-2],[2,-3],[0,-2],[-2,-3],[0,-4],[0,-7],[0,-1],[-2,-1],[0,-10],[0,-1],[-2,-1],[-9,0],[-1,0],[-3,-2],[-5,-2],[-2,-1],[-2,-3],[-1,-4],[-1,-3],[0,-1],[-3,1],[-1,-3],[-6,-5],[-1,-1],[-1,-3],[-1,-10],[0,-9],[-1,-1],[-2,-3],[0,-1],[0,-3],[0,-7],[-1,-17],[-1,-5]],[[6710,6635],[-1,0],[-2,-2],[-2,-3],[-4,2],[-4,2],[-13,6],[-1,3],[-1,5],[-2,1],[-3,-7],[-10,4],[-4,-1],[-2,2],[-6,0],[-4,4],[-6,-3],[-5,0],[-7,8],[-8,2],[-6,-1],[-3,1],[-5,3],[-2,3],[-4,-3],[-2,5],[-11,3],[-2,8],[-2,7],[0,7],[-2,12],[-1,18],[-1,6],[-2,7],[-2,5],[-3,5],[-2,2],[-10,4],[-2,0],[-5,-3],[-5,-6],[-8,-3],[-1,-3],[-2,-6],[-3,-3],[-4,1],[-4,-4],[-7,-10],[-4,-3],[-3,1],[-3,4],[-8,6],[-5,3],[-7,-2],[-3,1],[-5,7],[-2,6],[-3,3],[-10,8],[-8,11],[-1,4],[-1,5],[-4,7],[-8,6],[-4,6],[-6,2],[-4,0],[-3,1],[-2,2],[-6,13],[0,5],[-4,13],[-1,4],[-1,12],[-1,4],[-5,5],[0,3],[1,4],[0,4],[-3,3],[-3,2],[-1,3],[1,8],[-1,4],[-3,8],[-4,7],[-4,11],[-2,3],[-1,8],[-2,8],[-2,1],[-12,-11],[-4,6],[-10,10],[-1,2],[0,2],[1,2],[1,0],[3,-2],[1,3],[0,3],[-3,2],[-3,0],[1,-3],[-4,-3],[-1,-4],[1,-5],[0,-7],[-1,-4],[-1,-1],[-5,-1],[-2,-3],[-1,0]],[[6348,6910],[-2,2],[-1,2],[-1,4],[-1,3],[1,2],[-1,2],[-1,3],[-2,2],[-1,0],[-1,2],[-1,4],[-2,2],[-2,1],[0,11],[0,9],[0,10],[-5,0],[-4,0],[0,9],[0,14],[2,12],[2,11],[-3,8],[-4,9],[-2,4],[-2,11],[-2,4],[-1,2],[-1,1],[-5,0],[-4,6],[-5,7],[-6,8],[-5,5],[-3,2],[-5,0],[0,1],[-1,3],[0,4],[2,5],[0,3],[-3,10],[-1,4],[-3,1],[0,3],[0,2],[0,2],[-1,0],[-1,1],[-2,-2],[-2,5],[-5,14],[-2,2],[-1,0],[2,5],[2,6],[0,4],[0,4],[-2,7],[0,3],[1,4],[0,3],[2,-1],[2,0],[1,2],[0,8],[0,3],[7,13],[3,3],[3,3],[0,4],[0,2],[-1,3],[0,2],[-3,6],[-1,3],[0,3],[1,5],[1,4],[4,2],[2,2],[1,1],[-3,3],[-6,1],[-5,-1],[-2,1],[-2,5],[-2,3],[-2,2],[-2,0],[-2,0],[0,2],[-3,18],[-1,2],[-1,1],[-1,0],[-1,1],[-1,3],[-1,3],[0,4],[0,3],[0,3],[-1,2],[-2,1],[-1,2],[-2,16],[-1,4]],[[6243,7323],[0,1],[0,3],[1,3],[0,2],[-3,4],[-3,3],[0,1],[0,4],[0,3],[-1,3],[0,2],[0,1],[1,3],[-1,2],[-4,5],[-2,2],[-3,1],[-1,1],[1,4],[1,4],[2,4],[0,2],[1,4],[0,2],[2,4],[0,1],[0,1],[-2,1],[-2,0],[0,1],[0,2],[0,8],[-1,4],[0,4],[0,8],[-1,1],[-2,4],[0,4],[0,1],[0,2],[1,3],[0,2],[-2,3],[-1,2],[0,2],[-1,3],[0,2],[-1,2],[1,1],[2,0],[3,0],[3,0],[1,1],[2,15],[2,3],[2,2],[4,-5],[1,-1],[1,0]],[[6348,6910],[-3,-2],[-2,1],[-6,5],[-2,0],[-3,-2],[0,-1]],[[6332,6911],[-6,5],[-2,1],[-1,0],[-4,0],[-5,-1],[-3,-2],[-2,-2],[-1,-2],[0,-2],[-2,-6],[-2,-9],[-2,-8],[-3,-11],[-3,-5],[-4,-9]],[[6292,6860],[-5,-2],[-11,2],[-13,2],[-12,2],[-9,1],[-1,1],[-9,13],[-8,11],[-9,13],[-9,14],[-9,13],[-7,10],[-8,13],[-8,12],[-6,9],[-8,8],[-5,6],[-9,10],[-7,7],[-6,6],[-9,10],[-3,2],[-10,4],[-9,2],[-9,3],[-6,2]],[[6087,7034],[4,7],[-1,6],[-3,-1],[-3,-1],[-2,9],[2,1],[-2,13],[-2,13],[-2,12],[-2,13]],[[6076,7106],[8,8],[6,6],[8,9],[8,8],[8,8],[8,9],[8,7],[6,3],[2,3],[3,10],[3,9],[0,3],[0,12],[0,15],[1,8],[2,7],[1,6],[0,4],[0,5],[-1,8],[-2,8],[0,7],[1,4],[1,6],[1,5],[2,3],[6,3],[4,2],[5,8],[3,5],[5,8],[3,5],[0,2],[0,1]],[[6176,7321],[3,1],[5,7],[3,7],[1,0],[2,-2],[2,0],[4,2],[3,-1],[2,-2],[1,0],[6,-4],[2,0],[3,-1],[4,0],[3,2],[2,3],[1,0],[2,-1],[1,-1],[1,-2],[0,-2],[0,-9],[1,-2],[0,-2],[1,0],[2,2],[2,2],[2,3],[2,3],[1,1],[2,0],[2,-1],[1,-1]],[[4568,8998],[3,0],[5,2],[2,2],[6,4],[3,1],[5,0],[2,0],[-3,-2],[-2,-1],[-4,-2],[-3,-6],[-2,-3],[0,-2],[3,-2],[3,-2],[3,2],[1,-1],[1,-2],[1,-1],[0,-2],[0,-4],[-2,-3],[-3,-3],[1,-1],[2,-1],[9,2],[1,0],[0,-1],[0,-2],[1,-1],[1,-2],[0,-1],[-4,-5],[4,3],[4,1],[6,-2],[3,-2],[2,-3],[2,1],[1,0],[1,-1],[0,-2],[-1,-3],[0,-2],[-1,-1],[-2,-1],[-1,-1],[1,-2],[1,-2],[2,0],[1,0],[0,-1],[-1,-2],[-1,-1],[-2,-1],[5,-3],[1,-1],[0,-2],[0,-1],[-1,-2],[-2,-1],[-3,-1],[-2,-1],[0,-2],[0,-2],[0,-3],[-3,-5],[-3,-2],[-2,-2],[-5,1],[-2,1],[0,-4],[-2,-2],[0,-2],[1,-1],[0,-3],[-2,-2],[-2,-3],[-2,-2],[-4,-2],[-4,-3],[-3,-2],[-6,0],[-7,-2],[-9,-5],[-7,-3],[-4,-5],[-7,-7],[-5,-3],[-2,0],[-6,-1],[-4,-2],[-15,-3],[-5,-2],[-1,-2],[-2,-3],[0,-1],[1,-1],[0,-1],[-2,-3],[-4,-2],[-1,0],[-3,2],[-1,0],[0,-1],[1,-2],[-2,-1],[-10,-3],[-16,2],[-7,2],[-8,3],[-5,1],[-6,1],[-6,4],[-3,3],[0,1],[0,2],[1,1],[1,0],[2,0],[0,1],[-1,2],[-2,-1],[-3,-3],[-2,0],[-2,2],[0,1],[-4,1],[-4,2],[-4,3],[0,1],[2,1],[-1,1],[-1,0],[-3,-1],[-4,-3],[-1,-1],[-26,-1],[-6,0],[-2,-1],[-1,3],[-1,5],[0,3],[0,2],[1,2],[1,0],[2,-2],[1,-2],[1,-1],[9,2],[4,2],[1,2],[2,3],[2,1],[1,2],[2,5],[1,2],[2,1],[1,1],[4,1],[-2,1],[-3,0],[-8,-5],[-3,0],[0,1],[1,1],[3,3],[-2,0],[-1,1],[0,2],[2,4],[7,5],[2,0],[1,1],[-1,1],[-2,0],[-6,-4],[-5,-2],[-2,0],[-3,2],[0,1],[-2,2],[1,1],[2,4],[0,1],[-2,0],[-5,4],[-7,0],[-17,2],[-4,-1],[-5,-3],[-4,-1],[-2,0],[-1,2],[-2,2],[-1,3],[1,2],[2,1],[2,0],[4,0],[6,2],[4,0],[1,0],[2,2],[1,1],[2,-1],[1,-1],[5,2],[2,1],[1,1],[1,0],[2,-1],[3,0],[3,1],[5,0],[11,1],[2,1],[1,2],[1,4],[0,1],[-8,-4],[-1,0],[-9,2],[-3,2],[1,2],[5,3],[4,3],[7,4],[2,1],[0,1],[-5,3],[-8,-1],[-2,4],[-7,1],[-5,-1],[-3,2],[-6,-3],[-13,-3],[-5,-3],[-3,-1],[-4,2],[-5,3],[-7,1],[0,1],[3,4],[3,1],[3,0],[4,-3],[4,-1],[-4,4],[0,2],[-1,2],[-1,2],[-1,2],[0,1],[2,1],[3,-1],[9,-5],[4,1],[2,2],[3,1],[-1,1],[-7,0],[-4,1],[-2,1],[-1,3],[0,1],[2,1],[6,-1],[-4,5],[-3,2],[0,1],[0,2],[1,1],[7,-2],[2,0],[-2,1],[-3,3],[0,1],[1,0],[1,2],[0,1],[2,1],[2,0],[2,-1],[7,-5],[1,-1],[0,-2],[0,-2],[0,-1],[3,1],[2,-1],[1,0],[2,4],[2,-1],[1,-2],[1,-1],[0,-2],[-1,-4],[2,2],[3,0],[1,1],[0,4],[-1,4],[-10,5],[-2,1],[-2,3],[1,1],[2,1],[2,0],[7,0],[1,1],[-1,1],[-3,1],[-1,0],[-1,2],[-3,-1],[-5,0],[-4,1],[0,1],[2,1],[3,3],[2,1],[4,-1],[5,1],[4,-1],[3,-3],[4,-4],[5,-3],[1,-1],[3,-2],[6,-7],[6,-3],[0,-1],[-1,-1],[-2,-2],[3,-1],[3,-3],[0,-1],[-2,-8],[-1,-1],[-1,-1],[-6,1],[1,-2],[4,-3],[1,-1],[0,-2],[1,1],[1,-1],[0,-2],[-1,-2],[-1,-2],[1,-1],[1,1],[2,-1],[2,-2],[2,-7],[1,-2],[0,2],[1,5],[1,2],[1,0],[0,1],[1,2],[1,5],[4,4],[1,2],[2,0],[1,-1],[3,-4],[1,-1],[1,1],[2,3],[1,5],[0,6],[0,7],[0,5],[2,3],[2,1],[3,-1],[2,-2],[4,-7],[4,-3],[3,-4],[1,-1],[3,-1],[1,0],[0,1],[1,2],[-1,9],[1,3],[1,3],[5,1],[3,1],[3,3],[2,1],[2,0],[2,-1],[2,-2],[3,-4],[4,-6],[5,-4],[2,-8],[1,-1],[1,0],[0,1],[1,1],[0,4],[-2,4],[-4,11],[0,2],[0,1],[4,1],[7,-1],[3,-2],[5,-7],[1,-1],[1,-1],[0,1],[2,1],[2,2],[2,3],[5,7],[1,0],[2,0],[2,-2],[1,-1],[3,-1],[2,0],[4,2],[4,2],[1,3],[0,1],[-3,10],[1,2],[7,2],[6,1],[2,-1],[3,-5],[3,-2],[1,-2],[0,-4],[2,-2],[3,-2]],[[5993,7069],[-1,0],[-3,-3],[-1,-1],[0,-1],[-1,-1],[0,-13]],[[5987,7050],[-2,0],[-2,3],[-1,2],[0,1],[-2,0],[-3,2],[-4,-5],[-1,-7],[0,-3],[-2,-7],[1,-4],[0,-6],[0,-4],[0,-3],[-1,-1],[1,-1],[0,-1],[2,2],[2,-2],[2,-2],[0,-1],[-1,-1],[-3,-4],[-3,-4],[0,-4],[-2,-8],[0,-1],[1,-1],[5,0],[5,4],[4,3],[1,0]],[[5984,6997],[-1,-9],[0,-5],[0,-1],[1,-5],[-2,-9],[-1,-7],[-1,-3],[-2,-7],[-2,-9],[0,-6],[0,-2],[-1,-11],[1,-3],[-2,-10],[-1,-4],[-1,-7],[-1,-13]],[[5971,6886],[-2,-4]],[[5951,6981],[3,5],[0,4],[4,10],[0,1],[-1,2]],[[5957,7003],[6,18],[3,17],[3,24],[3,13],[2,8],[1,6]],[[5975,7089],[3,1],[2,-1],[3,0],[2,2],[1,8],[2,1],[0,-2],[1,2],[3,4],[2,2],[1,2],[1,1]],[[5996,7109],[-1,-3],[0,-2],[0,-3],[0,-2],[1,-3],[1,-4],[-1,-2],[0,-3],[0,-3],[1,-2],[-2,-5],[-1,-5],[-1,-3]],[[5334,7301],[-1,-1],[-2,2],[0,3],[0,1],[2,-1],[1,-3],[0,-1]],[[5432,7385],[-2,-6],[-1,-3],[-6,-16],[-1,-4],[-1,-4],[0,-3],[-1,-3],[-1,-5],[0,-4],[0,-3],[1,-1],[2,-2],[1,-2],[-2,-2],[2,-4],[1,-2],[0,-3],[0,-2],[-3,-5],[-1,-2],[-1,-3],[0,-3],[0,-3],[0,-3],[-3,0],[-3,2],[-3,-1],[-5,3],[-1,1],[-2,1],[-3,10],[-3,5],[-4,3],[-3,0],[-3,0],[-3,2],[-6,7],[-6,5],[-3,4],[-1,2],[-2,2],[-3,1],[-4,4],[-1,0],[-3,0],[-2,0],[-1,1],[-4,5],[-2,6],[0,2],[1,7],[2,7],[2,1],[1,2],[1,2],[1,2],[3,-7],[2,-1],[1,0],[3,2],[0,3],[3,4],[4,0],[1,-1],[1,-3],[2,-1],[1,-1],[6,-5],[1,-1],[1,-1],[5,3],[3,1],[6,-1],[4,1],[2,0],[4,2],[3,4],[1,1],[2,0],[4,0],[3,-1],[2,1],[1,3],[2,1],[2,-1],[4,4],[2,1],[2,-2],[-2,-3]],[[5235,7434],[-2,-6],[-1,4],[0,4],[0,1],[2,-2],[1,-1]],[[5387,7528],[-2,0],[0,1],[-1,0],[1,3],[2,-2],[0,-1],[0,-1]],[[5230,7548],[-1,-3],[-2,0],[1,2],[1,4],[2,1],[0,-1],[0,-2],[-1,-1]],[[5267,7539],[1,-4],[4,-15],[0,-3],[-1,-4],[-1,-2],[-3,-8],[1,-6],[1,-4],[0,-4],[0,-6],[-2,-32],[-1,-6],[-1,-5],[-2,-2],[-3,2],[-3,3],[-2,-1],[-1,-1],[-2,1],[-1,2],[-1,-11],[-1,-5],[-3,-3],[-2,0],[-2,1],[-2,0],[-2,2],[-1,4],[-2,5],[-2,5],[0,5],[0,11],[0,2],[1,3],[1,4],[-1,5],[1,1],[1,-1],[1,0],[0,2],[0,4],[-2,4],[-2,1],[0,3],[0,4],[1,2],[1,3],[0,10],[-2,3],[-1,5],[0,4],[-2,3],[-2,3],[-1,2],[0,7],[0,6],[1,2],[1,0],[1,-3],[2,-1],[3,0],[3,1],[3,2],[4,3],[4,10],[3,2],[2,2],[1,3],[1,1],[1,-3],[2,0],[3,-3],[1,-3],[1,-3],[1,-1],[2,-1],[-1,-1],[-1,-4],[0,-1],[2,-1]],[[5288,7652],[1,-2],[0,-1],[0,-2],[0,-3],[-2,3],[-4,-2],[-2,1],[-1,2],[1,2],[3,0],[1,1],[2,-1],[1,2]],[[5380,7863],[-1,-3],[-1,-1],[-2,-2],[-2,-2],[-2,-3],[-1,-4],[1,-2],[1,0],[1,0],[2,-1],[2,-1],[0,-2],[0,-1],[-2,-3],[-2,-2],[0,-2],[0,-1],[1,-1],[2,0],[1,-1],[-2,-7],[1,-1],[2,-2],[2,-1],[3,-5],[1,-4],[-1,-1],[-2,-1],[-1,1]],[[5381,7810],[1,2],[-4,8],[-2,0],[-3,-3],[-7,3],[-1,-1],[-1,-3],[-3,-4],[-3,-1],[-4,-4],[-4,-3],[-3,-2],[-2,1],[3,4],[-2,0],[-3,-3],[-3,-3],[0,-4],[-1,-7],[2,-2],[3,-10],[3,-4],[0,-4],[-1,-3],[-3,-3],[-1,2],[-1,0],[-1,-6],[1,-17],[3,-12],[2,-5],[6,-8],[6,-4],[11,-14],[6,-4],[1,-3],[4,-10],[3,-12],[3,-19],[3,-9],[4,-11],[10,-15],[9,-11],[9,-7],[6,-1],[16,1],[3,0],[2,-2],[1,-5],[-1,-3],[-3,-3],[-3,-5],[-1,-6],[3,-5],[15,-11],[16,-10],[4,-5],[6,-8],[13,-11],[2,-5],[9,-11],[3,-9],[1,-6],[-2,-7],[-1,-5],[-1,-5],[-3,2],[-4,5],[-6,20],[-11,2],[-2,1],[-4,4],[0,2],[-1,3],[-1,1],[-4,0],[-3,-3],[-4,-7],[-3,-11],[-4,-16],[-1,-7],[3,-6],[6,-4],[5,-5],[3,-6],[0,-14],[2,-8],[-3,-5],[-4,2],[-5,-3],[-4,-5],[-2,-5],[1,-13],[-1,-5],[-7,-9],[-4,-9],[-1,-4],[-2,-5],[-9,0],[-2,6],[0,8],[2,5],[3,2],[2,10],[0,8],[1,3],[1,3],[3,1],[3,1],[1,11],[-3,5],[-1,6],[-1,13],[-5,15],[-3,14],[-2,7],[-3,4],[-5,0],[-3,1],[-9,10],[-1,1],[0,3],[2,3],[-1,6],[-1,5],[-2,4],[-2,2],[-5,-1],[-1,-1],[-3,0],[-2,-2],[-1,0],[3,8],[-1,1],[-3,4],[-5,0],[-1,0],[-1,-2],[0,2],[0,3],[-6,15],[-3,6],[-2,1],[-3,-1],[-5,2],[-4,1],[-1,-1],[-3,-2],[-1,2],[-1,2],[-5,6],[-6,3],[-11,20],[-4,8],[-8,8],[-4,11],[-4,5],[-6,3],[-1,0],[-2,-1],[-1,-1],[-1,2],[1,2],[1,0],[0,5],[-7,11],[-3,4],[-1,3],[-1,3],[-1,2],[-2,1],[-1,0],[-2,1],[0,5],[0,5],[0,3],[-2,10],[-4,8],[-2,20],[-2,5],[-3,4],[-9,5],[-12,13],[-3,0],[-7,5],[-5,0],[-6,-4],[-7,-12],[-6,-13],[-2,-2],[-8,-4],[-6,-2]],[[5344,7714],[1,-2],[1,0],[1,3],[0,3],[-2,-1],[-1,-3]],[[2854,6247],[3,-2],[3,-1],[2,0],[1,-1],[4,-5],[2,-3],[10,-6],[3,-10],[1,-3],[-3,-2],[-3,-1],[-3,0],[-3,2],[-1,1],[-3,1],[1,2],[-1,0],[-2,0],[-1,-4],[-2,-3],[-2,0],[-1,3],[-1,-1],[-2,-2],[-1,-8],[-2,4],[-2,3],[-3,1],[-6,0],[-3,2],[-2,6],[-1,2],[-2,1],[-2,8],[-1,1],[-6,1],[-1,4],[0,4],[2,4],[1,1],[3,0],[4,2],[1,1],[2,2],[11,-4],[3,0],[3,0]],[[4943,8019],[1,-2],[-2,-1],[-1,1],[-2,0],[-2,-1],[1,5],[4,0],[1,-2]],[[6087,7034],[-4,-7],[-1,0],[-6,-3],[-11,-6],[-7,-4],[-9,-5],[-8,-4],[-8,-4],[-7,-3],[4,-8],[6,-12],[4,-8],[5,-11],[5,-9],[4,-9],[-3,-4],[-5,-5],[-1,-1],[0,-1],[-2,-10],[-2,-8],[-1,-1],[-7,-2],[-8,-3],[-5,-2],[-1,-2],[-3,-9],[-3,-10],[-6,-8],[-6,-9],[-1,-1],[-4,1],[-8,3],[-7,2],[-5,2],[-6,2]],[[5970,6875],[1,7],[0,4]],[[5984,6997],[1,5],[1,6],[1,5],[-1,13],[0,7],[2,8],[-1,9]],[[5993,7069],[3,-1],[2,-3],[3,-7],[5,-3],[1,-2],[3,-4],[3,-1],[9,-3],[8,9],[6,7],[7,8],[5,6],[9,9],[5,6],[7,8],[7,8]],[[8441,6582],[-2,-1],[-2,1],[-2,1],[0,1],[2,2],[0,3],[0,1],[5,-3],[0,-2],[-1,-3]],[[8452,6596],[-2,-9],[-1,-2],[-2,1],[-1,5],[1,2],[1,-1],[1,1],[3,7],[1,-1],[-1,-3]],[[8484,6609],[-3,-2],[-2,1],[0,8],[1,-1],[1,-2],[2,-2],[1,-2]],[[8949,6717],[-1,0],[-1,6],[1,-1],[1,-3],[0,-2]],[[8562,6719],[-3,-3],[-1,-3],[-2,-1],[-3,-4],[-2,-1],[0,-4],[1,-3],[-1,0],[-2,-4],[0,-3],[0,-2],[0,-1],[-2,-3],[-2,0],[0,3],[0,3],[2,6],[0,7],[2,1],[1,1],[3,5],[0,3],[-1,2],[0,2],[0,1],[3,-1],[1,-1],[0,-1],[1,2],[1,2],[3,5],[1,5],[2,-4],[-1,-5],[-1,-4]],[[8582,6780],[-1,-1],[-1,2],[-1,6],[1,4],[1,0],[1,-5],[1,-3],[-1,-3]],[[8591,6803],[1,-2],[-3,1],[-1,6],[2,-1],[0,-2],[1,-2]],[[8595,6809],[-2,-5],[-3,4],[-3,3],[2,1],[0,1],[0,2],[2,2],[4,2],[2,0],[1,2],[1,2],[0,1],[3,2],[0,-2],[0,-3],[-2,-1],[-2,-3],[-1,-3],[-2,-2],[0,-1],[0,-2]],[[8628,6927],[-4,-1],[-1,1],[-2,7],[3,5],[4,-5],[1,-1],[-1,-6]],[[8637,6935],[-3,-1],[0,3],[2,8],[1,5],[1,7],[1,2],[1,0],[0,-2],[0,-8],[-2,-7],[-1,-7]],[[8602,7007],[0,-1],[0,5],[2,4],[1,-3],[-3,-5]],[[8621,7051],[-3,0],[-1,1],[0,2],[3,3],[3,0],[-1,-4],[-1,-2]],[[8613,7040],[-3,-2],[0,2],[-1,1],[2,3],[0,1],[-1,2],[1,7],[0,3],[4,1],[1,-3],[0,-8],[-3,-7]],[[8573,7072],[1,-1],[2,0],[1,1],[1,-1],[1,-4],[1,-2],[-2,-1],[-1,0],[-1,-3],[-2,1],[-1,1],[0,2],[0,7]],[[8884,7088],[-1,-1],[-1,2],[0,2],[0,1],[1,0],[1,-2],[0,-2]],[[8585,7075],[-1,0],[-1,5],[-1,2],[1,1],[3,9],[0,-4],[1,-3],[1,-1],[-1,-3],[-1,-1],[-1,-5]],[[8596,7097],[-2,-2],[-1,0],[1,3],[0,1],[1,5],[2,1],[1,0],[-1,-4],[-1,-4]],[[8605,7128],[-2,-3],[-2,2],[1,5],[0,2],[2,-2],[1,-4]],[[8643,7119],[4,-1],[1,-1],[2,1],[2,2],[2,2],[2,-1],[1,-2],[1,-3],[0,-3],[-3,-6],[-2,-7],[5,-1],[5,0],[-1,-4],[0,-4],[1,-1],[1,-3],[0,-2],[-1,-2],[3,-3],[0,-2],[-1,-2],[-7,-15],[-2,-7],[-1,-8],[-1,-6],[-1,-6],[-1,-7],[-1,-7],[0,-6],[0,-6],[-4,-15],[-2,0],[-3,2],[-2,0],[-1,-4],[2,-7],[-6,-8],[-6,-6],[0,3],[1,2],[1,1],[0,2],[1,7],[0,6],[-2,9],[0,3],[1,1],[1,0],[0,1],[0,3],[0,2],[-2,1],[-2,0],[-1,-3],[-1,-6],[-1,-6],[0,-3],[1,-3],[2,-5],[0,-3],[-1,-2],[-8,5],[-2,0],[-1,1],[-2,7],[3,1],[1,1],[1,2],[0,7],[-1,5],[-2,2],[-1,3],[1,4],[0,6],[0,8],[0,2],[3,1],[2,5],[2,5],[3,8],[2,10],[-2,0],[-2,2],[2,4],[-1,6],[-3,7],[-1,8],[-3,3],[-1,2],[-2,-2],[-1,-2],[1,-6],[0,-4],[0,-5],[1,0],[2,1],[1,-1],[1,-2],[0,-4],[0,-3],[-1,-1],[-2,0],[-1,2],[-2,2],[-2,1],[-3,-2],[-3,-6],[-2,-3],[1,4],[0,5],[-1,3],[-2,5],[-1,3],[0,4],[0,4],[3,-4],[1,-6],[2,-2],[3,0],[-2,8],[-1,2],[-2,3],[-4,6],[-2,3],[0,6],[2,2],[1,-1],[4,-2],[0,3],[0,2],[-1,2],[3,2],[4,3],[1,1],[1,2],[1,1],[3,0],[2,2],[2,6],[1,3],[1,3],[5,4],[1,1],[4,-1],[3,-2],[1,-6],[2,-6],[3,-4]],[[8673,7139],[2,-2],[3,1],[0,-1],[-1,-2],[-1,-2],[-3,2],[-1,0],[-1,3],[1,1],[1,0]],[[8682,7149],[-1,-3],[-2,1],[1,2],[0,3],[1,0],[0,-3],[1,0]],[[8590,7149],[-2,-2],[0,3],[0,11],[4,-2],[0,-4],[-2,-6]],[[8731,7157],[4,-2],[4,0],[0,-10],[1,-4],[1,-3],[-1,-5],[2,-1],[-5,-5],[-5,-7],[-2,-5],[-2,-5],[-1,-5],[-1,-6],[-1,2],[-5,9],[-3,3],[-4,1],[-2,0],[-9,-9],[-2,-6],[-2,-10],[-2,-3],[-1,-1],[-1,-1],[-1,-9],[-3,-5],[-2,0],[-3,2],[-1,-1],[1,8],[-2,1],[-3,0],[-1,5],[-1,3],[1,4],[0,3],[1,2],[0,2],[0,2],[-2,1],[-1,2],[0,5],[-1,1],[-2,-1],[-6,-5],[-1,0],[2,3],[5,5],[2,2],[5,7],[3,3],[1,6],[1,4],[1,3],[1,5],[1,1],[3,5],[1,-1],[2,-5],[2,-4],[2,0],[3,2],[1,1],[4,0],[3,2],[1,3],[0,4],[-1,6],[2,0],[1,0],[4,4],[3,2],[3,1],[4,-2],[4,-4]],[[8731,7170],[0,-1],[-1,0],[-2,-2],[0,2],[-1,2],[-1,1],[4,1],[2,-1],[-1,-2]],[[8747,7159],[-3,-5],[-2,0],[-2,2],[0,3],[2,4],[3,6],[1,3],[2,2],[1,-1],[-2,-8],[0,-6]],[[8593,7163],[0,-3],[-2,2],[-1,1],[2,9],[-1,4],[1,1],[3,5],[1,-1],[0,-1],[0,-2],[0,-5],[-3,-7],[0,-3]],[[8873,7184],[0,-3],[-2,1],[-1,2],[1,3],[1,0],[1,-3]],[[8704,7269],[-1,-2],[-3,1],[-1,3],[0,3],[3,3],[2,-5],[0,-3]],[[8842,7362],[-3,0],[0,1],[1,1],[0,3],[1,4],[0,1],[-2,0],[0,5],[2,5],[4,7],[1,2],[1,-4],[-2,-7],[0,-3],[3,-1],[-2,-9],[-4,-5]],[[8922,7567],[1,-1],[5,3],[-1,-9],[0,-9],[0,-15],[1,-7],[1,-6],[2,-5],[3,-3],[4,-10],[2,-13],[2,-7],[1,-6],[0,-3],[0,-3],[0,-4],[0,-4],[0,-10],[-2,-12],[0,-6],[-2,-2],[-1,-3],[-1,-1],[-1,-1],[-1,0],[-1,-1],[0,-4],[-1,-3],[-1,-2],[-1,-4],[-1,-7],[0,-8],[-1,-5],[-3,-2],[-3,1],[-4,-3],[-1,-1],[-3,-10],[-1,-5],[0,-6],[1,-8],[1,-7],[1,-13],[-1,-20],[-1,-7],[-2,-4],[-2,-2],[-1,-3],[-2,-7],[-3,-13],[0,-3],[0,-3],[-1,-5],[0,-4],[0,-5],[1,-5],[4,-13],[2,-3],[1,-3],[-6,-4],[-1,-2],[-4,-7],[-2,-7],[1,-7],[-1,-3],[-1,-2],[-1,-1],[-5,-4],[-2,-3],[-3,-5],[-1,-3],[-2,1],[-2,2],[2,3],[-1,4],[1,9],[-1,4],[2,3],[1,4],[3,4],[1,3],[1,2],[-2,3],[-1,2],[-3,0],[-2,0],[-1,-3],[0,-4],[0,-1],[0,-2],[-4,-5],[1,-5],[1,-2],[1,-2],[0,-1],[-2,-5],[-1,0],[-2,6],[-3,3],[-3,0],[-3,-1],[-2,-4],[-1,-3],[-1,-4],[1,-8],[-1,-7],[-2,-5],[-1,-3],[-3,-4],[-1,0],[-1,2],[-1,2],[1,11],[0,5],[3,3],[-3,4],[-3,2],[-4,-2],[-1,-3],[0,-3],[-3,-4],[-2,-4],[-3,-7],[-1,-8],[-6,3],[-3,1],[-4,-1],[-5,1],[-6,-1],[-8,-3],[1,2],[6,5],[0,1],[-1,3],[-1,0],[-4,-1],[-1,0],[-1,3],[-1,1],[-1,-1],[0,-5],[-1,-1],[-1,1],[0,5],[0,6],[0,4],[1,3],[-1,1],[-2,0],[-1,-2],[-2,-2],[-3,-11],[-1,-7],[2,-5],[6,-7],[1,-2],[0,-3],[0,-3],[-2,-2],[-7,-2],[-6,-5],[-2,-4],[-5,-19],[-4,-12],[-7,-4],[-6,3],[-2,5],[-1,5],[-3,5],[-2,5],[-1,7],[0,10],[-1,6],[1,1],[4,4],[1,2],[2,5],[1,3],[0,4],[-2,2],[-4,0],[-5,-2],[-3,2],[-4,5],[-1,1],[-4,1],[-4,-1],[-3,-2],[-3,-1],[-1,-1],[-4,-6],[-3,-3],[-2,-2],[-6,-1],[-2,-1],[-3,-2],[-1,0],[-3,-3],[-4,-2],[-1,-2],[-4,1],[-7,-4],[-3,-1],[-3,3],[-3,3],[-4,-1],[-2,-6],[-1,-11],[-1,-5],[0,-6],[-2,1],[-9,11],[-8,-2],[-2,-1],[-2,-2],[-3,-1],[-2,2],[-2,2],[-2,0],[-2,-2],[-1,16],[0,2],[2,3],[1,3],[4,1],[3,-1],[3,1],[2,3],[2,5],[3,4],[3,3],[4,3],[3,5],[3,5],[2,4],[3,3],[4,8],[6,8],[2,7],[2,2],[4,3],[7,3],[3,0],[3,-6],[2,1],[1,1],[4,1],[3,-1],[3,0],[4,1],[6,2],[4,2],[3,3],[12,2],[8,5],[1,-1],[2,-1],[0,-3],[-1,-4],[1,-3],[1,-1],[8,0],[2,-1],[3,2],[3,4],[3,4],[3,5],[-2,6],[-1,7],[2,7],[2,6],[3,4],[3,4],[5,12],[4,10],[2,12],[-1,14],[3,11],[4,2],[6,5],[4,1],[0,-2],[0,-3],[-5,-9],[-3,-3],[-2,-2],[-1,-1],[-1,-3],[3,-6],[0,-3],[0,-4],[0,-3],[3,-4],[4,-1],[1,0],[1,1],[4,9],[1,1],[11,7],[5,5],[4,1],[2,3],[7,10],[2,4],[2,5],[2,6],[1,7],[2,4],[10,9],[3,5],[1,3],[2,7],[0,8],[2,5],[1,6],[3,6],[2,5],[2,5],[2,13],[1,7],[0,3],[1,2],[1,3],[1,3],[0,3],[1,9],[0,7],[-2,6],[-2,2],[-1,0],[-2,0],[-2,2],[0,2],[2,1],[1,1],[1,2],[2,7],[1,7],[0,3],[-1,6],[-1,6],[0,4],[1,4],[2,4],[1,1],[2,0],[2,1],[1,2],[1,2],[1,6],[1,4],[-1,9],[1,2],[1,2],[1,-2],[2,0],[2,1],[1,-1],[1,-3],[1,-15],[1,-2],[1,-1],[1,0],[1,2],[1,3],[2,1],[5,-3],[2,2],[1,4],[1,6],[0,6],[-2,2],[-1,0],[-1,-2],[-1,-1],[-8,-3],[0,7],[2,10],[1,3],[1,1],[3,-1],[2,-1],[3,-5]],[[8874,7608],[-1,-1],[-1,1],[0,4],[0,2],[2,2],[2,0],[-2,-8]],[[8924,7783],[-2,-1],[-2,3],[0,3],[1,2],[2,-1],[1,-3],[1,-2],[-1,-1]],[[8918,7795],[-1,-4],[-2,6],[0,6],[1,0],[1,-1],[1,-3],[0,-4]],[[8994,7725],[4,0],[1,0],[3,-1],[10,-9],[4,-1],[3,0],[2,1],[2,2],[7,11],[6,9],[1,0],[0,-3],[0,-3],[-3,-8],[-4,-12],[0,-6],[1,-6],[2,-5],[1,-7],[2,-9],[3,-1],[1,0],[3,2],[3,4],[2,0],[2,0],[-3,-3],[-3,-3],[-2,-5],[-1,-1],[-3,0],[-1,0],[-4,-3],[-3,-2],[-2,-4],[-3,-1],[-3,-1],[-5,-3],[-4,0],[-6,3],[-2,-1],[-7,-5],[-6,-8],[-5,-9],[-4,-10],[-1,-5],[-1,-6],[-1,-4],[0,-4],[-1,-3],[-1,-2],[-4,1],[-5,6],[-11,8],[-12,12],[-7,6],[-12,-2],[-12,-11],[-1,1],[-4,8],[-2,3],[-3,1],[-2,0],[-2,-1],[-2,-4],[-1,-3],[-1,-3],[0,-3],[0,-2],[3,-6],[3,-3],[1,-1],[3,0],[1,0],[5,-8],[6,-8],[1,-2],[-2,-3],[-2,-1],[-3,0],[-2,1],[-5,3],[-2,-2],[-2,-6],[-2,-6],[-1,-3],[-3,-3],[-4,-2],[-2,0],[-1,3],[-1,2],[0,4],[1,6],[1,7],[1,6],[-1,9],[-1,2],[-4,5],[-2,5],[0,6],[0,4],[1,7],[1,4],[2,2],[1,0],[3,3],[3,4],[3,4],[3,5],[2,5],[-3,7],[0,4],[0,4],[3,2],[2,-2],[6,-5],[1,-1],[3,0],[6,-1],[3,0],[1,1],[2,5],[1,6],[0,7],[0,8],[1,6],[4,9],[2,6],[0,14],[2,7],[1,6],[1,13],[-2,13],[-2,7],[-2,6],[0,5],[2,6],[0,1],[0,2],[3,1],[2,1],[1,3],[2,1],[1,-1],[1,-3],[4,-7],[7,-11],[8,-18],[5,-8],[5,-8],[6,-8],[7,-7],[4,-3],[2,-5],[2,-1]],[[7140,7206],[-2,5],[0,3],[-2,6],[-1,5],[-2,8],[-1,5]],[[6393,7767],[-1,-1],[-1,0],[-3,6],[1,6],[1,2],[1,0],[0,-1],[-1,-3],[-1,-3],[2,-4],[2,-2]],[[6397,7774],[-1,-1],[-1,4],[1,3],[2,1],[-1,-5],[0,-2]],[[6463,7799],[-1,0],[-2,1],[-1,3],[2,3],[1,0],[1,-4],[0,-3]],[[7227,7614],[-4,6],[-4,7],[-3,1],[-6,1],[-3,0],[-1,2],[-2,3],[-2,4],[-3,3],[-1,6],[-1,1],[-2,-1],[-3,0],[-1,1],[-3,0],[-4,3],[-3,2],[-5,0],[-2,0],[-7,-1],[-7,2],[-5,1],[-3,0],[-1,0],[-3,0],[-3,1],[-5,3],[-2,0],[-1,0],[-9,-3],[-3,0],[-9,0],[-7,0],[-3,1],[-1,0],[-3,-6],[-2,-1],[-7,1],[-9,4],[-6,4],[-6,5],[-7,7],[-4,3],[-1,-2],[-1,0],[-2,-1],[-4,1],[-1,-4],[-5,-2],[-3,-3],[-1,-2],[-3,-18],[-1,-6],[2,-11],[-2,1],[-3,3],[-1,2],[-3,1],[-9,2],[-2,3],[-1,2],[-2,1],[-4,1],[-7,5],[-3,0],[-10,3],[-1,0],[-1,0],[-4,-2],[-2,-1],[-3,1],[-4,-3],[-3,-4],[-2,-4],[-2,-3],[0,-5],[-2,-2],[-1,-4],[0,-3],[1,-3]],[[6970,7617],[-2,-2],[-3,-1],[-1,-1],[-2,-4],[-1,-3],[-1,-1],[-1,0],[-2,3],[-2,-1],[-2,-2],[-3,-5],[-4,-7],[-3,-4],[-5,-4],[-4,-1],[-2,-2],[-5,-5],[-1,-3],[-3,-2],[-3,-2],[-2,-4],[-1,-5],[-1,-4],[-4,-5],[-3,-4],[-2,-5],[-3,-5],[0,-2],[0,-4],[1,-3],[0,-3],[-1,-2],[-2,-1],[-2,0],[-4,3],[-3,3],[-2,2],[-1,3],[0,3],[1,6],[0,4],[-1,2],[-1,2],[-1,2],[-2,4],[-2,-1],[-1,-1],[-2,1],[-6,0],[-4,-1],[-4,0],[-5,-1],[-7,0],[-2,0],[-1,2],[-1,5],[0,4],[-2,9],[0,6],[-1,8],[-1,9],[0,6],[-5,0],[-4,0],[-5,0],[0,5],[0,6],[0,7],[1,9],[0,8],[1,9],[0,6],[0,7],[-2,-2],[-3,-2],[-3,-3],[-2,6],[-2,5],[-2,8],[-2,6],[-4,4],[-3,3],[-2,4],[-3,5],[-2,4],[-3,4],[-2,-1],[-3,-3],[-3,-2],[-3,-3],[-2,-1],[-3,1],[-3,0],[-6,1],[-4,0],[-5,1],[-6,1],[-7,1],[-4,-1],[-6,-2],[-6,-1],[-5,-2],[-6,-1],[-4,-1],[-3,0],[-3,5],[-4,8],[-3,4],[-3,5],[-4,7],[-3,5],[-3,5],[-2,4],[0,6],[-2,3],[-4,3],[-3,4],[-4,4],[-4,4],[-4,3],[-4,4],[-4,4],[-3,4],[-4,4],[-4,3],[-4,4],[-4,4],[-4,4],[-3,4],[-4,3],[-4,4],[-4,4],[-3,3],[-3,-1],[-4,-2],[-5,-2],[-5,-2],[-8,-4],[-5,-2],[-4,-2],[-5,-2],[-5,-3],[-5,-2],[-6,-3],[-5,-2],[-4,-2],[-4,-2],[-4,-2],[0,-13],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13]],[[6554,7564],[-1,0],[-3,-1],[-4,-2],[-4,-1],[-1,1],[-2,1],[-1,3],[-2,4],[-2,3],[-2,6],[-2,4],[-4,10],[-1,3],[-1,3],[-1,3],[-5,6],[-6,6],[-5,6],[-2,1],[-2,2],[-4,0],[-2,0],[-6,-2],[-6,-2],[-6,-3],[-6,-4],[-1,-1],[-4,-4],[-5,-6],[-5,-10]],[[6458,7590],[-1,6],[0,10],[0,3],[1,8],[2,5],[1,6],[1,7],[-2,12],[-1,2],[-1,1],[-2,0],[-3,0],[-2,-1],[-2,4],[-3,1],[-2,-2],[-1,0],[-2,1],[-2,2],[0,3],[-1,3],[-3,6],[-2,3],[-3,0],[-4,0],[-2,1],[0,3],[1,7],[0,4],[-1,3],[0,3],[-1,3],[-3,4],[-2,6],[-4,12],[-3,13],[-1,2],[-3,2],[-6,2],[-4,2],[-1,2],[-1,3],[0,3],[1,3],[1,4],[3,2],[6,1],[6,-1],[5,-5],[2,-2],[2,0],[4,2],[1,0],[5,0],[-1,2],[-2,2],[-2,0],[-1,1],[-3,5],[-4,6],[-1,2],[-1,4],[1,4],[3,3],[3,5],[1,6],[1,3],[3,4],[3,-1],[5,4],[9,-1],[11,1],[3,0],[6,-3],[4,-2],[5,-1],[3,2],[-3,4],[-7,5],[-2,5],[3,12],[5,10],[2,13],[0,13],[-2,4],[1,4],[1,3],[1,4],[-1,4],[-1,7],[-1,2],[-4,3],[-6,0],[-6,2],[-2,-1],[-1,-3],[-1,-1],[-4,-3],[-1,-1],[-2,1],[-2,3],[-2,0],[-5,2],[-3,5],[-1,1],[-9,4],[-3,0],[-7,-4],[-5,-5],[-2,-1],[-3,-3],[-1,0],[-2,0],[-1,0],[-3,-5],[-6,-6],[-3,-3],[-3,-2],[-3,-2],[-4,0],[-1,-1],[-4,-1],[-3,-1],[0,-2],[1,-4],[-3,1],[-2,-2],[1,-3]],[[6367,7853],[-1,0],[-7,6],[-5,4],[-4,3],[-1,1],[-1,1],[-1,3],[0,3],[0,2],[1,1],[2,0],[1,0],[1,-1],[2,-2],[3,0],[2,1],[0,3],[-3,10],[-3,9],[-4,9],[-1,3],[-4,8],[-4,8],[-3,7],[-1,2],[-5,1],[-9,1],[-4,1],[-2,-2],[-3,-1],[-2,3],[-2,4],[-1,5],[0,4],[0,6],[-1,6],[-2,3],[-4,2],[-5,5],[-2,10],[3,13],[4,9],[3,4],[1,4],[1,3],[-1,3],[-1,3],[-3,3],[-2,3],[1,8],[2,11],[3,9],[4,5],[3,4],[1,3],[0,5],[0,4],[1,3],[1,3],[2,2],[2,3],[3,1],[3,-3],[4,-5],[5,-11],[4,-7],[1,-2],[3,-4],[3,-2],[4,3],[5,3],[1,2],[1,2],[-1,5],[0,4],[-1,4],[-2,7],[-1,11],[-1,4],[1,0],[2,0],[2,-1],[3,3],[4,5],[7,7],[2,5],[1,5],[2,3],[5,1],[4,2],[3,4],[5,3],[4,2],[2,2],[1,3],[5,7],[3,5],[3,5],[1,3],[3,0],[4,-2],[4,-2],[3,-3],[0,-4],[0,-2],[2,-1],[1,-1],[2,1],[4,0],[5,4],[6,7],[6,2],[3,-1],[3,-5],[2,-5],[2,-2],[1,0],[3,1],[3,0],[2,-2],[4,0],[5,1],[0,1],[3,-1],[3,-2],[2,-3],[5,-8],[2,-2],[5,-3],[3,-3],[2,-4],[2,-3],[3,-5],[3,-7],[1,-6],[0,-6],[2,-2],[1,0],[1,0],[1,3],[0,4],[0,7],[-1,5],[-1,2],[0,2],[0,3],[2,1],[3,-1],[3,-3],[5,-4],[5,-7],[4,-5],[5,-4],[4,-1],[3,1],[4,3],[3,4],[2,3],[1,4],[5,6],[5,4],[2,0],[1,-2],[5,3],[2,1],[4,1],[5,-2],[3,-5],[4,-3],[3,0],[3,2],[2,3],[1,4],[2,2],[0,1],[6,-2],[3,0],[1,1],[4,-1],[6,-5],[3,-6],[4,-8],[2,-2],[3,-1],[2,-1],[3,-1],[8,-2],[1,0],[1,-2],[-1,-4],[1,-1],[6,3],[2,2],[2,6],[2,7],[1,2],[2,1],[1,-1],[2,-4],[3,-4],[4,-1],[2,-1],[4,0],[8,2],[8,4],[5,5],[2,8],[1,8],[2,6],[-1,5],[-4,5],[-1,2],[-10,3],[0,2],[-1,0],[-9,5],[-5,2],[-1,3],[-1,4],[-3,3],[-6,4],[-1,2],[1,3],[4,2],[6,6],[2,1],[5,1],[4,4],[3,3],[2,3],[-1,4],[-4,10],[-1,6],[0,4],[3,4],[1,2],[2,5],[1,2],[5,1],[5,0],[4,-1],[5,0],[4,-1],[3,-1],[2,2],[1,2],[0,3],[-2,3],[-7,4],[-3,3],[-2,-1],[-4,1],[-4,2],[-3,1],[-1,3],[1,4],[1,2],[2,1],[3,0],[3,1],[0,1],[1,2],[-1,1],[-1,2],[-2,0],[-2,-1],[-2,-1],[-4,2],[-4,2],[0,2],[3,3],[1,3],[0,3],[0,4],[1,5],[2,3],[3,2],[7,-3],[10,-3],[1,0],[1,2],[1,1],[12,1],[3,2],[1,1],[12,2],[2,2],[2,2],[2,0],[4,1],[4,2],[4,1],[4,0],[4,1],[1,1],[1,2],[4,2],[7,2],[2,-1],[3,-1],[5,1],[3,2],[2,-2],[2,-1],[2,1],[1,5],[1,4],[3,2],[1,1],[2,1],[1,2],[7,0],[5,4],[1,-2],[8,1],[9,2],[6,2],[9,3],[5,2],[6,1],[6,1],[3,4],[4,1],[3,0],[3,1],[1,2],[1,3],[-1,3],[0,3],[3,1],[3,1],[3,1],[5,5],[4,3],[3,2],[8,-1],[7,-1],[7,-3],[3,-3],[3,-3],[3,-1],[3,-1],[3,1],[2,2],[1,2],[2,2],[7,1],[2,-2],[3,-8],[2,-10],[4,-14],[2,-6],[-1,-4],[0,-5],[0,-5],[-3,-6],[1,-3],[7,-3],[9,1],[6,3],[3,-1],[2,1],[1,5],[2,1],[3,-3],[1,-5],[2,-4],[0,-4],[1,-5],[1,-1],[2,2],[2,1],[0,1],[-1,2],[0,2],[0,2],[2,1],[3,-1],[5,-1],[5,-7],[3,-1],[2,0],[3,0],[3,2],[2,3],[1,1],[2,0],[1,-1],[0,-3],[-1,-4],[-4,-3],[-4,-4],[-2,-6],[-1,-6],[1,-3],[1,-2],[0,-3],[1,-1],[2,2],[5,6],[2,1],[4,1],[6,0],[4,-2],[2,-3],[2,-2],[1,1],[1,2],[0,3],[0,3],[7,6],[4,4],[1,1],[3,-1],[2,0],[5,4],[4,4],[1,3],[0,3],[1,1],[6,1],[1,1],[5,3],[7,5],[4,3],[6,1],[1,1],[3,2],[3,3],[3,1],[-2,-7],[-2,-8],[-1,-3],[-7,1],[0,-2],[1,-4],[1,-2],[1,-1],[1,-3],[7,-7],[9,-9],[9,-10],[7,-7],[2,-3],[2,-3],[5,-10],[4,-10],[8,-16],[7,-17],[8,-17],[4,-11],[9,-21],[2,-7],[5,-12],[4,-12],[3,-11],[2,-1],[1,3],[0,2],[1,1],[3,3],[1,1],[2,0],[2,1],[1,3],[0,6],[-1,2],[1,3],[1,1],[2,1],[1,0],[2,3],[2,1],[2,0],[2,0],[1,-3],[1,-3],[2,0],[3,0],[0,-2],[-1,-5],[-1,-3],[0,-2],[2,-2],[5,1],[2,0],[1,-3],[0,-2],[1,-3],[-1,-3],[1,-2],[5,0],[3,2],[5,0],[5,-3],[3,0],[3,1],[5,0],[3,2],[2,3],[1,3],[1,1],[5,0],[2,0],[2,4],[2,2],[3,0],[3,0],[6,-3],[4,-3],[4,-4],[2,-3],[2,-5],[2,-4],[2,-5],[1,-5],[2,-9],[2,-3],[2,0],[2,-1],[3,-1],[7,-6],[2,0],[2,-2],[0,-3],[0,-3],[0,-3],[3,-5],[1,-4],[2,-5],[1,-2],[1,-1],[3,1],[3,-1],[11,-3],[1,0],[1,-3],[2,0],[2,0],[2,0],[2,3],[1,2],[4,3],[3,4],[2,3],[2,1],[1,-2],[0,-3],[-1,-2],[-2,-3],[1,-2],[2,-1],[3,-4],[4,-9],[1,-2],[2,-2],[2,-1],[2,-1],[2,-4],[1,-4]],[[6138,5059],[-1,0],[1,3],[3,4],[1,0],[0,-1],[0,-1],[0,-1],[-4,-4]],[[6163,5413],[-4,-10],[-4,-12],[-7,-23],[-6,-12],[-4,-8],[-1,-2],[0,-10],[0,-24],[0,-49],[1,-48],[0,-49],[0,-24],[0,-8],[3,-11],[4,-9],[5,-14],[3,-7],[0,-2],[0,-5]],[[6153,5086],[-4,-10],[-3,-4],[-5,-2],[-1,0],[-2,1],[-1,-2],[0,-4],[-1,1],[-1,1],[1,-6],[0,-4],[-1,-4],[-2,-4],[0,-3],[-5,-8],[-6,-1],[-4,-5],[-1,-3],[-2,-8],[1,-11],[-2,-9],[0,-4],[-4,-6],[-1,-5],[-1,-6],[-1,-2],[-2,-12],[-1,-8],[-1,-2],[0,-2],[-1,-5],[-1,-2],[-1,-2],[-4,-19],[-3,-9],[-2,1],[-2,-3],[0,-1]],[[6089,4914],[-1,0],[-2,3],[-4,7],[-5,6],[-4,7],[-4,6],[-4,6],[-5,7],[-4,6],[-4,6],[-3,4],[-1,2],[-1,5],[0,1],[-1,1],[-2,1],[0,2],[1,4],[1,5],[0,4],[0,4],[-1,6],[0,1],[-3,4],[-6,7],[-6,6],[-6,7],[-5,7],[-6,7],[-6,7],[-6,7],[-6,6],[-6,7],[-6,7],[-6,7],[-6,7],[-6,7],[-6,7],[-6,6],[-5,7],[-3,3],[-2,2],[-2,0]],[[5941,5126],[0,10],[1,25],[0,22],[0,11],[3,7],[1,5],[1,7],[1,6],[3,4],[1,3],[3,8],[2,10],[2,3],[2,3],[1,2],[2,2],[2,1],[0,2],[0,6],[0,2],[1,5],[2,3],[1,3],[1,2],[0,5],[0,3],[0,5],[0,12],[-2,9],[-1,11],[1,4],[-1,6],[-1,0],[-1,2],[-1,6],[-1,5],[0,1],[-4,5],[-2,12],[-2,2],[-1,11],[0,3],[1,12],[0,2],[-1,2],[-4,3],[-3,4],[1,2],[0,2],[-1,1],[-5,19]],[[5943,5427],[6,11],[5,12],[8,15],[6,13],[6,12],[5,10]],[[7045,7456],[-2,0],[-3,1],[-2,-1],[-2,-2],[-2,-2],[-4,-1],[-4,0],[-2,0],[-7,1],[-2,0],[-2,-1],[-4,-1],[-2,-4],[-1,-3],[0,-1],[-3,3],[-1,3],[-2,2],[-1,0],[-5,-4],[-1,0],[-1,2],[0,4],[0,3],[-2,1],[-3,0],[-1,2],[0,2],[0,2],[0,2],[-1,1],[-2,0],[-2,-2],[-2,-2],[-2,-1],[-2,0],[-2,-1],[-1,-5],[-6,-1],[-2,1],[-1,3],[-2,6],[-1,0],[-2,1],[-3,0],[-4,-3],[-1,2],[-1,1],[-1,-2],[-1,0],[-4,0],[-6,0],[-2,1],[-2,0],[-4,-2],[-2,0],[-3,-1],[0,8],[-2,6],[1,4],[1,5],[1,3],[1,-1],[2,-2],[1,0],[1,2],[-1,2],[0,2],[1,2],[1,2],[6,4],[6,2],[3,-1],[5,-4],[3,-2],[2,-1],[2,-6],[1,0],[1,1],[1,2],[1,5],[2,2],[6,4],[0,1],[0,1]],[[6970,7501],[1,1],[3,1],[6,1],[2,0],[2,-2],[2,-2],[2,0],[1,0],[1,0],[0,-2],[1,-1],[2,2],[2,2],[2,1],[1,1],[1,1],[1,3],[3,6],[2,1],[1,0],[0,-1],[0,-1],[3,-1],[1,1],[1,2],[-1,4],[0,1],[0,1],[0,1],[5,-3],[1,0],[2,2],[2,3],[1,2],[9,8],[1,1],[0,1],[-4,2],[-2,-1],[-2,0],[-1,1],[-4,1],[-1,1],[-4,5],[-2,2],[-2,2],[-2,0],[-2,-2],[0,1],[-1,2],[0,3],[0,3],[-1,1],[-2,-1],[-3,1],[-2,1],[-1,6],[-1,3],[0,3],[-1,1],[-2,1],[0,4],[0,1],[-1,1],[-1,-1],[-1,-2],[1,-4],[-1,-4],[0,-1],[-1,-2],[-2,0],[-2,2],[0,-12],[-1,-1],[-2,2],[-2,-1],[-3,1],[-3,2],[-2,1],[-2,1],[-3,2],[-1,8],[-1,3],[-1,1],[-5,-3],[-2,2],[-3,3],[-3,1],[0,1],[0,2],[7,9],[3,6],[2,3],[3,1],[2,1],[1,6],[1,1],[1,0],[3,2],[6,5],[0,2],[-1,1],[-2,2],[-2,2],[-2,-1],[-1,-1]],[[6963,7478],[0,1],[-1,0],[-2,1],[-2,1],[-1,0],[0,-1],[1,-2],[1,-2],[2,-1],[2,3]],[[6993,7485],[0,2],[-1,0],[-2,-1],[0,-1],[1,-2],[1,-1],[1,3]],[[6977,7482],[1,0],[-1,5],[1,4],[-3,0],[-1,1],[-2,4],[0,1],[-1,-2],[-1,-2],[1,-3],[1,-2],[1,-1],[0,-1],[-1,-4],[1,-1],[3,0],[1,1]],[[7869,5801],[-1,-2],[-1,5],[0,1],[2,-4]],[[7862,5834],[-1,-1],[-1,1],[0,3],[1,2],[0,1],[1,-6]],[[7900,5783],[-5,8],[-9,3],[-1,3],[0,1],[-1,-5],[-5,-4],[-2,3],[-2,3],[0,3],[2,3],[2,2],[1,8],[-1,10],[-2,3],[-2,2],[-2,-4],[-1,-6],[-2,-3],[-2,-1],[-3,0],[-2,10],[0,8],[0,9],[1,5],[-3,7],[-1,7],[-1,4],[-1,-2],[0,-2]],[[7858,5858],[0,2],[-5,20],[-1,10],[1,7],[1,3],[-2,3],[-2,5],[-4,6],[0,9],[-1,10],[-1,4],[-1,7],[-1,5],[-1,15],[1,1],[2,0],[4,1],[0,3],[0,2],[2,3],[3,7],[2,8],[2,4],[1,5],[3,7],[5,4],[3,1],[3,2],[4,2],[1,0],[4,-2],[2,-1],[2,0],[3,0],[2,0],[4,2],[6,-2],[4,2],[6,2],[3,-2],[2,-2],[0,-4],[1,-2],[1,-2],[1,0],[1,3],[2,4]],[[7921,6010],[0,-1],[1,-4],[1,-3],[1,-3],[2,-3],[1,0],[4,3],[5,-4],[1,-2],[2,-4],[2,-3],[5,0],[1,7],[-1,4],[-2,8],[-1,5],[1,1],[4,1],[1,1],[1,5],[1,-1],[3,-1],[2,4],[2,3],[0,-1],[1,-3],[1,-1],[2,-2],[2,-3],[1,-4],[1,-1],[3,1],[1,0],[1,4],[1,2],[1,-1],[1,0],[3,5],[2,4],[1,1],[2,-2],[1,1],[1,5],[2,3]],[[7986,6031],[0,-3],[-1,-6],[-1,-6],[-2,-5],[-1,-3],[0,-11],[0,-3],[0,-3],[1,-1],[2,-10],[2,-10],[2,-7],[0,-5],[-1,-12],[-2,-12],[0,-5],[1,-6],[1,-7],[0,-10],[-1,-6],[-1,-4],[-1,-4],[-2,-2],[-1,3],[-2,1],[-2,-2],[-1,-1],[-3,-6],[-3,-6],[-5,-1],[-2,-4],[-2,-1],[-3,0],[-3,-1],[0,-2],[0,-10],[0,-2],[0,-1],[-2,0],[-3,1],[-3,3],[-3,0],[-2,-4],[0,-2],[-1,0],[-1,-1],[-1,-2],[0,-2],[1,-5],[0,-6],[0,-5],[1,-3],[5,-9],[2,-2],[0,-2],[-1,-5],[1,-7],[-2,0],[-3,3],[-1,2],[-2,-2],[0,1],[-2,3],[-1,4],[-2,0],[-3,-1],[-4,-1],[-1,0],[0,-1],[-2,-6],[-1,1],[-4,2],[-3,1],[-1,-1],[1,-5],[1,-4],[-1,-2],[-2,-2],[-2,-4],[-1,-3],[-1,-1],[-4,0],[-3,0],[-2,-4],[-1,-2],[-1,-1]],[[784,4525],[0,-1],[-1,0],[0,1],[0,2],[0,1],[1,-2],[0,-1]],[[670,4860],[0,-1],[-1,0],[0,1],[0,1],[1,0],[0,-1]],[[152,4915],[1,-1],[0,-1],[-1,1],[0,1],[0,1],[0,-1]],[[216,4924],[1,0],[0,-1],[-1,0],[0,1],[0,1],[1,0],[-1,-1]],[[244,4927],[-1,-1],[0,1],[0,1],[1,-1]],[[696,4948],[-1,0],[0,1],[-1,1],[0,1],[1,0],[1,1],[0,-1],[0,-1],[0,-2]],[[248,5003],[-1,0],[0,1],[1,0],[0,-1]],[[231,5024],[1,-1],[0,-1],[1,-2],[0,-1],[-1,0],[-1,1],[0,1],[1,-1],[0,1],[0,2],[-1,0],[0,1],[-1,0],[0,1],[1,-1]],[[9854,5114],[0,-3],[-1,0],[0,2],[0,3],[-1,3],[1,-1],[1,-3],[0,-1]],[[9709,5133],[-1,1],[0,1],[1,-1],[0,-1]],[[9846,5138],[0,-2],[-1,1],[1,2],[-1,8],[-1,1],[-1,2],[2,-2],[1,-1],[0,-5],[0,-4]],[[9805,5242],[2,-2],[0,-2],[-1,-1],[-2,-5],[2,4],[0,3],[-1,2],[-1,2],[1,0],[0,-1]],[[9806,5261],[-1,0],[0,1],[4,1],[0,1],[0,-1],[0,-1],[-1,0],[-2,-1]],[[9805,5283],[-1,-1],[1,1],[0,1],[0,4],[1,0],[0,-2],[0,-2],[-1,-1]],[[9805,5290],[0,-1],[-1,3],[-1,3],[0,1],[0,-1],[1,-1],[0,-1],[1,-3]],[[629,5291],[5,-7],[-2,0],[-5,3],[-4,6],[1,2],[1,-3],[2,-2],[1,5],[1,1],[-4,5],[2,-1],[3,-3],[-1,-6]],[[9800,5360],[-2,-3],[0,1],[0,1],[2,2],[1,0],[0,-1],[-1,0]],[[9804,5364],[-2,-2],[-1,0],[3,3],[0,-1]],[[574,5410],[2,-5],[0,-3],[-2,1],[-1,1],[2,0],[0,1],[-1,1],[-1,1],[0,-2],[-1,2],[0,1],[1,1],[1,1]],[[3263,6170],[-2,-1],[-1,1],[0,4],[1,1],[2,-2],[0,-3]],[[3260,6177],[-1,-1],[-1,3],[-2,1],[-2,3],[0,1],[0,1],[1,1],[3,-3],[1,-3],[1,-2],[0,-1]],[[8508,7097],[-1,-1],[-1,1],[0,1],[-2,3],[0,2],[1,3],[4,5],[9,5],[2,0],[4,-2],[1,-4],[-1,-3],[-1,-3],[-4,-4],[-4,-2],[-7,-1]],[[8520,7162],[1,-3],[-3,1],[-1,2],[0,3],[2,0],[1,-3]],[[8506,7163],[-2,0],[-1,2],[-1,0],[1,3],[2,5],[1,2],[3,-1],[1,-3],[-2,-4],[-2,-4]],[[8549,7178],[0,-2],[-2,2],[2,3],[0,-3]],[[8504,7184],[0,-1],[-2,0],[-1,4],[0,3],[-2,2],[2,3],[3,-5],[0,-6]],[[8557,7189],[-1,-6],[-2,0],[-1,3],[-1,-1],[-1,-1],[-1,5],[0,4],[2,2],[2,-1],[2,-1],[1,-4]],[[8575,7188],[-2,-3],[-4,4],[-1,3],[3,4],[2,4],[2,1],[0,-13]],[[8511,7286],[-1,-4],[-1,2],[-1,9],[2,-3],[1,-4]],[[8636,7343],[-2,-2],[-1,2],[0,1],[1,2],[1,1],[1,-2],[0,-2]],[[8514,7357],[-1,-7],[-1,0],[-1,1],[-1,1],[-1,7],[2,3],[2,-2],[1,-3]],[[8565,7408],[7,-25],[6,-17],[6,-12],[8,-23],[2,-13],[0,-7],[2,-11],[-1,-6],[0,-10],[-1,-4],[-1,-4],[0,-7],[1,-4],[0,-5],[0,-2],[1,0],[2,2],[1,0],[0,-6],[-2,-15],[-2,-11],[-2,-9],[-4,-9],[-3,-3],[-3,-1],[-5,-1],[-4,2],[-4,-1],[-2,-2],[-1,-3],[1,-5],[0,-4],[-2,1],[-3,2],[-3,0],[-2,1],[-1,5],[-2,0],[-3,-3],[-4,-1],[-2,-1],[0,-3],[0,-2],[3,-4],[-1,-3],[-3,-2],[-1,4],[-2,5],[-1,0],[-2,-1],[0,-5],[1,-3],[1,-4],[-2,-4],[0,-3],[-2,-2],[-4,5],[0,3],[2,3],[0,4],[0,2],[-6,-9],[-4,-10],[-2,1],[-1,3],[-1,1],[-4,-7],[-1,-5],[-1,0],[-1,2],[0,5],[0,4],[-5,5],[-1,5],[1,3],[3,-2],[3,0],[-1,3],[-1,1],[2,1],[2,3],[-2,0],[-2,-1],[-1,1],[-1,6],[-2,6],[-1,7],[2,3],[1,6],[2,8],[1,3],[2,2],[1,2],[-1,1],[-2,1],[0,2],[1,1],[2,3],[3,3],[1,6],[-1,1],[-2,2],[1,3],[0,2],[0,2],[-2,3],[-2,4],[1,4],[-1,6],[0,5],[0,3],[-1,6],[0,6],[-2,-1],[-1,-1],[-4,2],[-2,0],[0,5],[1,6],[4,5],[2,0],[2,2],[2,1],[3,-3],[3,-1],[1,-6],[1,-1],[1,2],[2,3],[0,1],[0,2],[-3,1],[-2,7],[0,3],[-1,2],[1,6],[-3,7],[-1,2],[0,6],[-1,4],[-1,2],[0,3],[0,2],[1,0],[1,2]],[[8517,7360],[1,1],[0,2],[0,5],[2,3],[4,8],[1,4],[2,3],[2,3],[3,1],[3,1],[7,-1],[1,1],[5,0],[1,-1],[3,0],[4,0],[2,1],[1,2],[2,4],[1,6],[2,5],[1,0]],[[5598,7617],[-4,-1],[-2,-2],[-1,-4],[0,-1],[-1,0],[-1,1],[-2,3],[-3,0],[-7,-6],[-1,-3],[0,-7],[-1,-1],[-1,-1],[-3,0],[0,1]],[[5557,7634],[0,1],[0,4],[0,3],[-1,3],[1,2],[2,0],[1,-1],[1,3],[4,2]],[[5565,7651],[3,1],[1,2],[-1,2],[0,2],[4,5],[1,2],[0,1],[0,2],[-1,3],[0,1],[2,2],[2,1],[1,1],[1,-2],[0,-1],[0,-2],[2,-2],[2,-2],[2,-1],[2,-3],[3,-5],[0,-2],[3,-3],[2,-2],[0,-5],[7,-4],[2,0],[1,0],[0,-2],[-1,-3],[-3,-10],[0,-2],[-2,-2],[-1,-1],[1,-3],[0,-2]],[[6340,6890],[-1,-1],[-1,0],[-1,3],[-2,8],[1,3],[0,1],[0,1],[1,1],[0,3],[1,2],[1,-3],[3,-9],[0,-3],[0,-2],[-2,-4]],[[6345,6828],[-5,0],[-6,0],[-5,-1],[-5,0],[-3,6],[-1,6],[-1,6],[-2,9],[-8,2],[-5,1],[-7,1],[-5,2]],[[6332,6911],[0,-2],[1,-7],[2,-7],[1,-5],[1,-3],[-2,1],[-1,1],[-2,1],[-4,-8],[-3,-4],[0,-1],[3,-2],[3,0],[2,1],[1,-1],[1,-5],[0,-4],[3,-13],[2,-5],[2,-7],[1,-5],[1,-3],[1,-5]],[[7836,6473],[2,-6],[3,-6],[4,-8],[1,-4],[3,-4],[0,-3],[1,-4],[0,-4],[1,-2],[1,0],[1,0],[1,2],[1,5],[0,1],[1,-4],[1,-1],[1,-1],[1,-1],[0,-4],[0,-3],[-1,-3],[-1,-4],[0,-6],[-1,-4],[1,-4],[6,-18],[3,-3],[7,-3],[3,-3],[2,-2],[2,1],[2,5],[3,3],[5,5],[1,0],[3,-2],[4,-5],[3,-5],[2,-3],[1,-2],[0,-3],[-1,-2],[-2,-2],[-2,-2],[-1,-3],[1,-1],[3,0],[3,-3],[1,-2],[0,-3],[1,-3],[1,-1],[3,0],[1,-1],[1,-1],[1,-5],[0,-4],[-2,-4],[-1,-3],[-1,-4],[-1,-4],[-5,-8],[-1,-1],[-8,5],[-3,-1],[-2,0],[-1,0],[-1,-2],[2,-4],[0,-5],[-1,-4],[-3,-3],[-1,-1],[0,-2],[1,-2],[2,-3],[3,-2],[9,-12],[2,-3],[3,-4],[3,-3],[8,-4],[3,-3],[1,-2],[0,-2],[-1,-2],[-1,-5],[0,-3],[1,-2],[1,-4],[3,-6],[2,-3]],[[7925,6231],[2,0],[2,-2]],[[7929,6229],[1,-4],[2,-5],[0,-4],[1,-5],[2,-6],[3,-5],[3,-7],[2,-4],[1,-2],[7,-12],[2,-4],[2,-8],[2,-1],[1,-2],[0,-4],[0,-3],[1,-10],[1,-3],[1,-4],[1,-2],[1,-2],[1,-1],[2,3],[1,2],[0,-1],[1,-7],[2,-2],[1,-3],[2,-2],[4,-8],[3,-3],[1,-1],[1,-1],[1,-3],[-1,-2],[-1,-2],[-4,-5],[-1,-2],[1,-3],[1,-4],[1,-4],[2,-3],[3,-5],[3,-5],[2,-4],[1,-4],[-1,-3],[-1,-4],[-1,-4],[-2,-2],[0,-2],[0,-4],[1,-3],[0,-3],[0,-6]],[[7921,6010],[2,1],[2,3],[3,3],[1,4],[1,3],[0,4],[0,11],[1,5],[0,6],[-1,5],[0,8],[0,3],[0,3],[2,3],[1,4],[1,6],[0,4],[-1,2],[-1,2],[-3,3],[-2,3],[-1,3],[0,3],[1,3],[-2,3],[-5,3],[-3,4],[0,4],[-3,6],[-3,7],[-2,11],[0,13],[0,11],[2,13],[-2,10],[-3,4],[-3,4],[-3,5],[-3,7],[-3,10],[-5,13],[-2,6],[-2,-1],[-3,1],[-4,4],[-4,2],[-3,0],[-3,-1],[-1,-2],[0,-2],[1,-2],[0,-1],[-2,-1],[-2,-3],[-1,-4],[-1,-7],[-2,-2],[-2,-1],[-3,-2],[-3,-3],[-1,-2],[0,-2],[-1,1],[-1,2],[0,3],[-1,3],[-3,1],[-3,3],[-3,6],[-2,3],[-2,1],[-1,-3],[-3,-5],[-2,-2],[-1,1],[-2,-2],[-1,-4],[-1,-4],[-4,-4],[-4,-6],[-3,-5],[-4,-7],[-1,-1],[-2,1],[-2,2],[-2,3],[3,12],[3,14],[1,6],[0,4],[0,4],[-2,4],[-1,3],[0,2],[0,2],[2,3],[1,5],[2,10],[2,11],[0,6],[-2,7],[-1,7],[1,9],[0,4],[-2,2],[-5,1],[-2,0],[-1,-1],[-2,-3],[-1,-1],[-4,-1],[-3,3],[-2,5],[-1,7],[2,7],[1,7],[1,5],[0,2],[-1,3],[-2,4],[-2,5],[-1,3],[-2,0],[-1,-3],[-1,-4],[-1,-1],[-1,1],[0,3]],[[7780,6354],[1,3],[1,13],[2,8],[2,4],[2,1],[3,0],[2,0],[1,2],[0,1],[-2,1],[0,2],[0,4],[1,3],[1,1],[1,4],[2,7],[1,3],[2,0],[3,3],[4,6],[2,6]],[[5975,7089],[1,5],[1,5],[2,8],[2,7],[5,21],[3,9],[1,12],[4,11],[3,4],[2,3],[0,4]],[[5999,7178],[5,0],[3,1],[1,2],[2,-1],[1,-3],[-1,-2],[-2,-3],[1,-1],[1,0],[2,-2],[1,-2],[3,-12],[-2,-5],[-2,-5],[-1,0],[-2,-2],[-1,-3],[-1,-2],[0,-2],[2,-2],[1,-1],[-1,-1],[-2,1],[-2,0],[-1,0],[-2,-1],[-2,-2],[-1,-2],[0,-1],[-1,-4],[1,-3],[1,-1],[0,-1],[0,-1],[-1,-2],[-2,-2],[0,-2],[-1,-2]],[[4790,5434],[-3,1],[-10,8],[-7,5],[-24,27],[-7,11],[-8,16],[-17,32],[-4,5],[-5,3],[-3,2],[-2,3],[-2,9],[-4,5],[-8,8],[-6,13]],[[4680,5582],[1,2],[3,8],[3,8],[2,5],[3,5],[2,4],[3,4],[6,11],[1,2],[1,8],[1,10],[1,3],[4,2],[1,1],[1,7],[1,9],[0,2]],[[5693,6451],[0,-29],[0,-29],[0,-28],[0,-29],[-7,0],[-7,0],[-7,0],[-6,0],[0,-8],[0,-7],[0,-7],[0,-7]],[[5666,6307],[-14,13],[-13,14],[-13,14],[-14,13],[-13,14],[-13,14],[-14,13],[-13,14],[-13,13],[-14,14],[-13,14],[-13,13],[-13,14],[-14,14],[-13,13],[-13,14],[-10,9],[-9,-9],[-8,-7],[-10,-10]],[[5416,6508],[-12,-12],[-9,-9],[-1,0],[-9,16],[-8,12],[-3,4],[-14,6],[-14,7],[-14,6]],[[5264,6925],[3,3],[5,3],[2,3],[1,2],[4,9],[2,5],[2,7],[1,5],[0,4],[0,5],[-2,13],[-2,12],[2,5],[1,2],[2,6],[1,1],[4,2],[2,4],[2,4],[0,3],[2,3],[3,2],[1,4],[5,5],[5,5],[5,5],[4,4],[1,3],[0,3],[-2,7],[0,8],[0,7],[0,4],[1,11],[0,1]],[[5319,7095],[4,-4],[5,-1],[13,-14],[4,-1],[9,-2],[10,6],[4,1],[7,-6],[4,-1],[5,0],[9,-5],[2,-2],[5,-7],[3,-3],[18,-7],[3,-4],[2,-9],[0,-11],[2,-8],[2,-10],[3,-7],[3,-6],[3,-4],[8,-5],[9,-3],[10,0],[15,-8],[14,-9],[3,-4],[7,-4],[13,-21],[7,-8],[6,-1],[4,1],[9,8],[3,4],[8,18],[3,9],[1,7],[0,7],[-1,6],[-2,6],[-2,8],[-1,15],[1,11],[2,6],[2,7],[7,12],[7,8],[13,12],[7,0],[3,1],[5,8],[3,0],[3,-2],[10,1],[4,-2],[5,-5],[7,-3],[4,-3],[5,-4],[1,-10],[-1,-3],[0,-4],[5,-7],[14,-3],[3,-2],[4,-5],[3,-2],[9,0],[6,1],[6,-2],[2,-2],[2,-4],[2,-10],[1,-3]],[[3308,5980],[-1,-6],[-3,4],[-1,4],[0,3],[2,6],[2,3],[1,2],[0,-5],[0,-11]],[[7218,5705],[1,-4],[-2,3],[-2,2],[-1,2],[4,-2],[0,-1]],[[7221,5739],[-2,-1],[-1,4],[-1,1],[1,1],[0,1],[1,-4],[2,-2]],[[7221,5749],[3,0],[3,0],[2,-1],[3,-9],[9,-16],[5,-16],[1,-3],[0,-3],[2,-1],[1,-2],[5,-15],[0,-3],[0,-4],[1,-2],[1,-2],[2,0],[1,-3],[1,-12],[0,-4],[0,-2],[7,-19],[0,-2],[0,-2],[0,-2],[1,-3],[2,-9],[1,-2],[2,-8],[0,-16],[-1,-7],[-1,-8],[-1,-8],[-2,-6],[-2,-5],[-7,-11],[-2,-2],[-10,-7],[-6,-6],[-7,-2],[-6,4],[-5,8],[-2,12],[-2,13],[-2,14],[-2,44],[-1,12],[-2,15],[1,7],[1,7],[0,-15],[0,-1],[1,1],[1,15],[0,6],[3,16],[0,3],[0,6],[0,3],[3,12],[1,6],[1,7],[0,7],[-1,7],[3,-2],[2,-2],[1,-2],[2,1],[1,0],[-1,4],[-3,3],[-6,3],[-2,2],[-1,3],[1,3],[0,1]],[[5798,3450],[-3,-1],[0,-1],[-2,1],[-2,-1],[-2,0],[-1,-1],[-2,-4],[-4,-11],[-1,-2],[0,-4],[-1,-4],[-1,-2],[-1,-1],[-4,1],[-4,1],[-2,4],[-2,4],[-1,3],[-2,2],[0,1],[-2,1],[0,1],[-1,1],[0,2],[-1,2],[0,5],[-1,3],[-2,5],[-1,4],[-2,6],[-1,5],[-1,5],[0,2],[1,2],[3,3],[3,2],[1,3],[2,6],[1,3],[1,2],[1,2],[2,5],[2,6],[2,6],[2,2],[4,2],[4,5],[4,5],[6,5],[3,1],[2,1],[0,-1],[1,-3],[1,-3],[3,-4],[1,-1],[3,-6],[3,-4],[3,-5],[2,-2],[1,-1],[1,-4],[1,-3],[1,-3],[0,-3],[-1,-7],[-2,-7],[-1,-3],[-2,-2],[-1,-3],[-1,-6],[0,-6],[-2,-3],[-2,-2],[-2,-2],[-4,-4]],[[5582,8368],[-2,0]],[[5580,8368],[3,7],[1,4],[1,6],[1,2],[0,-3],[0,-4],[-2,-8],[-2,-4]],[[5652,8291],[0,1],[0,2],[0,5],[-1,3],[-2,4],[-3,2],[-3,2],[-2,1],[-1,1],[-1,1],[0,1],[-1,1],[-3,2],[-2,0],[-1,-2]],[[5632,8315],[-1,2],[-2,6],[1,4],[0,4],[4,11],[-1,2],[-2,4],[-3,2],[-2,5],[-6,0],[-6,0],[-1,0],[-6,3],[-5,3],[-4,2],[-3,2],[-1,3],[-3,-1],[-2,0]],[[5589,8367],[-1,5],[1,6],[-1,9],[-4,12],[0,12],[0,2]],[[5584,8413],[8,7],[9,7],[2,1],[9,4],[1,1],[8,-1],[6,-1],[5,0],[3,1],[2,-1],[3,-3],[2,0],[2,2],[11,-1],[3,0],[3,-1],[5,-2],[3,-1],[7,1],[3,0],[2,0],[5,5],[2,1],[1,1],[2,-1],[1,-4],[4,-7],[4,-1],[10,-3],[2,-2],[6,-6],[4,-3],[2,-3],[3,-5],[2,-3],[4,-3],[4,-2],[1,0]],[[5759,8497],[3,0],[2,-1],[0,-4],[4,-4],[4,-3],[0,-1],[1,-3],[-1,-3],[0,-1],[-1,-2],[-2,-5],[0,-4],[-2,-8],[1,0],[4,1],[1,-1],[1,-1],[0,-5],[2,-2],[1,-4],[0,-2],[3,-3],[0,-2],[2,-7],[1,-5],[0,-3],[-1,-4],[-1,-2]],[[5584,8413],[-1,11],[1,22],[1,11],[5,6],[3,5],[1,6],[0,6],[2,5],[7,15],[6,1],[8,4],[9,4],[2,-5],[1,-3],[10,-12],[3,-3],[4,-14],[10,-7],[8,2],[4,4],[6,6],[3,4],[0,5],[-1,18],[-2,8],[1,5]],[[8153,6465],[0,-1],[-1,-1],[0,-1],[-1,0]],[[3249,6225],[-3,0]],[[3246,6225],[0,1],[2,1],[1,0],[0,-2]],[[4758,6777],[-3,0],[0,-3],[1,-4],[0,-5],[-1,-2],[0,-3],[0,-3],[1,-4],[0,-3],[0,-2],[-1,-2],[-2,-1],[-4,-1],[-2,0],[-3,1],[-2,0],[-2,0],[-2,-1],[-2,-2],[-2,-4],[-3,-4],[-2,-3],[-2,-1],[-2,0],[-3,3],[-1,1],[-1,0],[-2,-2],[-2,-1],[-1,0],[-3,2],[-4,4],[-2,1],[-2,1],[-3,1],[-2,0],[-3,0],[-3,-3],[-3,-1],[-3,-2],[-4,-2],[1,-5],[1,-3],[0,-3],[0,-3],[-2,-3],[-2,-4],[-1,-3],[-1,-4],[-1,-2],[-2,-4],[-1,-4],[0,-3],[-1,-4],[-1,-1],[-3,-1],[-3,-1],[-2,-1],[0,-2],[-1,-4],[0,-3],[-1,-2],[0,-6],[-2,-5],[0,-7],[-1,-6],[-1,-9],[-1,-9],[-2,-8],[-1,-5],[-1,-3],[-2,-3],[-1,-3],[-2,-3],[-3,-3],[-3,-3],[-2,-3],[-1,-1],[-1,-2],[-2,-4],[-2,-6],[-1,-4],[-2,-8],[-1,-4],[-1,-2],[-2,-2],[-3,-2],[-3,-2],[-2,-3],[-3,-2],[-2,-2],[-1,-4],[-1,-4],[-2,-5],[-1,-7],[0,-4],[-2,-14],[-1,-8],[0,-5],[-1,-6],[-1,-10],[0,-8],[0,-5],[0,-3],[-2,-4],[-1,-3],[-2,-4],[-2,-2],[0,-3],[-2,-3],[-1,-4],[-2,-3],[0,-2],[1,-4],[-1,-4],[-1,-5],[-2,-6],[-3,-3],[-3,0],[-5,0],[-4,0],[-5,0],[-4,1],[-4,2],[-5,0],[-3,0],[-4,-1],[-11,0],[-4,-1],[-6,-2],[-2,0]],[[4527,6418],[2,27],[4,15],[3,7],[5,3],[4,15],[2,14],[2,6],[1,5],[-1,4],[3,8],[3,11],[2,7],[3,12],[1,2],[0,3],[-2,-2],[-1,-5],[-2,-3],[0,4],[2,6],[3,6],[6,7],[11,24],[4,4],[4,10],[1,8],[0,20],[2,11],[2,8],[3,15],[2,7],[2,14],[1,5],[3,2],[4,7],[6,5],[7,8],[3,6],[3,8],[2,15],[4,17],[3,13],[3,6],[3,9],[4,3],[9,2],[14,7],[12,10],[3,5],[4,8],[6,11],[11,13],[5,7],[8,18],[5,15],[5,10],[3,8],[2,9],[1,14],[-1,6],[-3,8],[-2,3],[-1,4],[1,8],[0,12],[1,21],[4,16],[9,22],[2,9],[1,14],[0,5],[11,20],[7,15],[2,4],[6,7],[20,15],[12,11],[7,8],[4,10],[11,37],[11,52],[1,6],[5,2],[3,0],[3,2],[4,4],[3,-1],[-2,-3],[0,-6],[3,-8],[4,-8],[7,-11],[6,-4],[8,-3],[10,5],[5,0],[3,2],[3,-3],[5,-1],[5,2],[4,4],[3,5],[0,-2],[0,-3],[1,-2],[2,-6],[1,-3],[3,1],[2,-2],[6,1],[6,-1]],[[5206,7704],[-2,-1]],[[5783,7802],[-1,3],[-2,4],[-1,1],[1,1],[1,1],[1,1],[0,4],[-1,4],[-1,2],[0,4],[0,5],[1,9],[2,12],[1,6],[-1,4],[1,7],[-1,4],[-2,5],[-2,11],[-3,3],[-3,5],[-1,3],[-1,3],[-2,3],[-3,4],[-2,7],[-2,4],[0,1],[-3,5],[-2,4],[-1,4],[0,3],[-2,7],[-2,5],[-2,4],[-1,2],[-2,4],[-3,2],[-3,1],[-2,-1]],[[5739,7963],[0,2],[6,6],[2,-1],[3,0],[6,0],[3,3],[2,-1],[1,2],[3,2],[0,-1],[4,-1],[3,-2],[2,-2],[2,-2],[2,-1],[1,-1],[1,-3],[2,-1],[3,0],[2,-1],[-1,-3],[1,-1],[1,1],[1,-1],[0,-2],[1,-1],[2,3],[2,0],[5,-2],[2,-7],[2,-2],[1,-1],[2,1],[2,1],[0,-1],[2,-4],[1,-6],[0,-3],[-1,-4],[-1,-5],[-1,-3],[1,-2],[0,-2],[2,0],[3,-4],[2,-3],[2,-2],[1,0],[1,-1],[0,-2],[0,-3],[-1,-4],[0,-2],[2,-2],[0,-3],[0,-2],[1,-2],[3,-3],[4,-3],[1,-3],[1,-3],[0,-6],[0,-5],[5,-6],[0,-2],[-1,-1],[-6,-1],[-1,0],[-2,5],[-1,0],[-2,-2],[-1,-1],[-2,1],[-1,1],[-1,1],[-1,1],[-1,-2],[-2,1],[-1,1],[-1,-4],[-1,-1],[0,7],[-1,2],[-1,0],[-3,-2],[-2,-2],[-1,-2],[0,-4],[0,-4],[2,-7],[-1,-2],[0,-5],[-3,-4],[-3,-2],[-1,-5],[-1,-4],[-3,-3],[-2,-4],[0,-3],[0,-2],[0,-2],[0,-1],[-1,-1],[-4,-1],[-1,0],[-2,-2]],[[6386,4210],[-3,-10],[1,8],[4,13],[1,1],[-3,-12]],[[6342,4414],[0,-2],[-3,1],[-1,7],[2,0],[0,3],[1,1],[1,-7],[0,-3]],[[6375,4468],[2,-6],[1,-6],[5,-14],[2,-5],[2,-6],[0,-12],[3,-17],[3,-27],[1,-27],[1,-13],[2,-12],[4,-12],[1,-13],[-3,-14],[-3,-14],[0,-2],[-2,-3],[-1,0],[-2,3],[-2,6],[-3,13],[-1,6],[-1,2],[-3,-1],[-2,-4],[0,-3],[0,-7],[1,-7],[0,-7],[0,-8],[1,-3],[1,-2],[2,-6],[0,-13],[-1,-7],[-2,-5],[0,-3],[1,-4],[-1,-2],[-3,-2],[-1,-2],[-2,-6],[-2,-12],[0,-6],[1,-19],[0,-13],[-3,-25],[-2,-12],[-3,-15],[-4,-18],[-4,-24],[-3,-24],[-3,-15],[-2,-15],[-4,-25],[-4,-26],[-4,-28],[-7,-32],[-1,-4],[-1,-16],[-2,-14],[-2,-14],[-3,-23],[-1,-8],[-1,-6],[-3,-15],[-2,-5],[-1,-6],[0,-7],[-1,-7],[-3,-13],[-4,-11],[-3,-4],[-6,-6],[-3,-1],[-6,0],[-6,-3],[-7,-7],[-6,-7],[-3,-4],[-3,-2],[-8,0],[-2,2],[-9,12],[-3,2],[-6,1],[-2,1],[-2,2],[-2,6],[-5,5],[-1,2],[-1,4],[-1,4],[-1,4],[-1,9],[-2,5],[-4,11],[-1,3],[0,11],[0,8],[0,13],[0,7],[2,6],[-1,6],[-1,6],[-1,7],[-1,6],[-5,12],[-1,5],[-1,6],[-2,18],[0,6],[0,13],[1,7],[1,4],[0,4],[1,3],[1,2],[1,3],[2,17],[2,3],[3,3],[3,4],[2,6],[1,12],[4,12],[2,6],[3,10],[3,13],[1,7],[1,6],[1,15],[0,7],[0,7],[-2,7],[-4,13],[0,3],[0,9],[0,7],[-1,7],[-2,7],[-2,12],[-1,21],[0,7],[-1,7],[-1,6],[1,11],[12,40],[1,4],[-1,13],[0,7],[1,2],[1,2],[2,0],[10,2],[1,1],[3,4],[3,6],[2,2],[1,-1],[1,-2],[1,-2],[4,3],[1,0],[2,0],[1,2],[0,4],[1,3],[1,1],[5,1],[3,1],[5,2],[4,-9],[1,-1],[1,0],[1,1],[-2,5],[-1,3],[0,3],[2,6],[2,5],[6,8],[6,9],[1,0],[2,-1],[1,-11],[0,-1],[1,0],[1,1],[1,4],[0,3],[-1,4],[0,3],[0,2],[2,6],[3,6],[1,7],[1,3],[2,4],[1,-1],[0,-3],[1,-3],[-1,-3],[-1,-3],[0,-4],[1,-1],[2,1],[1,8],[3,7],[1,3],[1,3],[3,-1],[3,-1],[-5,7],[-1,10],[5,18],[1,3],[0,1],[1,2],[-3,6],[-1,3],[1,4],[1,4],[1,3],[2,1],[1,-2],[3,-5],[2,0],[2,4],[2,6],[3,4],[3,2],[5,10],[3,19],[0,5],[0,7],[-2,6],[-1,8],[0,2],[3,-1],[1,1],[2,7],[5,14],[2,0],[1,-3],[1,-3],[1,-3],[3,-6],[1,-5]],[[7039,5370],[-1,0],[0,1],[0,1],[0,1],[1,0],[0,-1],[0,-1],[0,-1]],[[7041,5424],[0,-1],[-1,0],[0,1],[0,1],[1,1],[0,2],[1,0],[0,-1],[0,-1],[-1,-1],[0,-1]],[[2453,6260],[-3,-2],[-1,2],[7,5],[1,0],[0,-1],[-3,-2],[-1,-2]],[[1919,6263],[-2,-1],[-2,4],[0,2],[2,2],[1,-3],[1,-4]],[[2585,6353],[-2,-2],[0,7],[1,6],[1,4],[3,0],[2,1],[0,-1],[-2,-5],[-3,-10]],[[2591,6407],[1,-3],[-1,1],[-1,2],[0,2],[1,0],[0,-2]],[[2041,6429],[0,-5],[-3,2],[0,3],[0,5],[1,0],[1,-2],[1,-1],[0,-2]],[[1950,6575],[-1,0],[-1,3],[-1,7],[0,1],[3,-9],[0,-1],[0,-1]],[[1897,6589],[0,-3],[-9,11],[2,1],[3,-1],[4,-8]],[[1928,6624],[1,-6],[-1,0],[-2,4],[-1,4],[0,2],[0,1],[3,-3],[0,-2]],[[1887,6598],[0,-1],[-3,7],[0,4],[-1,2],[-3,2],[3,9],[1,19],[1,-3],[-2,-20],[0,-2],[1,-3],[1,-4],[0,-4],[2,-4],[0,-2]],[[1914,6683],[0,-3],[-1,1],[-2,-8],[-1,-1],[1,12],[2,1],[1,1],[0,-3]],[[1801,6801],[-1,-2],[-4,4],[2,6],[0,7],[1,2],[1,-3],[1,-9],[0,-5]],[[1715,6851],[-1,-2],[-3,12],[0,3],[1,1],[1,0],[0,-3],[2,-3],[0,-2],[0,-6]],[[1883,6854],[-2,-13],[-2,0],[-5,4],[0,3],[2,16],[1,2],[4,2],[0,-2],[1,-5],[1,-7]],[[1857,6857],[-1,-1],[-2,4],[-7,12],[-2,6],[-1,3],[1,6],[2,-1],[2,-4],[1,-4],[1,-4],[4,-2],[1,-10],[1,-5]],[[1814,7010],[-1,0],[-2,2],[0,3],[1,0],[1,-2],[1,-2],[0,-1]],[[2301,6679],[0,-12],[-2,-10],[-5,-20],[-3,-12],[-4,-36],[-2,-24],[0,-11],[0,-2],[0,-1],[-1,-25],[1,-21],[-1,-3],[-1,-6],[-1,-9],[0,-4],[0,-3],[2,-13],[0,-10],[5,-17],[3,-6],[3,-5],[2,-3],[-1,-7],[-1,-4],[-1,-6],[-1,5],[1,6],[1,4],[0,2],[-2,3],[-4,8],[-5,16],[4,-25],[1,-4],[1,-1],[1,-2],[0,-3],[0,-2],[4,-17],[5,-17],[0,-5],[2,-6],[11,-24],[7,-19],[3,-17],[1,-6],[1,-7],[5,-8],[1,-6],[3,-3],[2,-9],[3,-5],[-1,0],[-3,3],[0,-2],[3,-4],[5,-4],[2,0],[-2,2],[-2,3],[1,0],[3,-3],[11,-1],[4,-8],[6,-3],[4,-9],[3,-10],[3,-1],[2,0],[5,2],[9,6],[3,3],[6,4],[9,1],[3,-1],[7,3],[3,3],[1,3],[0,2],[7,3],[1,0],[6,1],[3,1],[4,1],[3,-5],[0,-2],[-2,-2],[1,-2],[3,-3],[5,-2],[2,1],[3,5],[4,5],[0,5],[-1,3],[-1,0],[0,2],[1,4],[-1,1],[-2,-3],[-1,0],[0,1],[1,2],[8,8],[2,4],[3,3],[6,11],[2,22],[1,4],[4,7],[0,2],[0,4],[0,12],[0,9],[0,10],[1,9],[1,2],[2,15],[5,6],[8,8],[2,1],[26,8],[4,2],[4,5],[3,2],[6,0],[2,1],[1,0],[0,1],[1,1],[3,-1],[7,-3],[2,-1],[6,-3],[6,-2],[1,1],[1,1],[1,2],[-1,2],[-1,0],[-1,-1],[-1,0],[-3,1],[1,1],[2,0],[2,1],[3,2],[2,-2],[4,-7],[2,-2],[0,-11],[1,-2],[0,-3],[-1,-8],[-1,-7],[-2,-6],[-4,-9],[-4,-7],[-6,-16],[-1,-7],[0,-6],[1,-6],[0,-2],[-1,-2],[-1,0],[-2,-3],[-3,-8],[0,-3],[1,-2],[2,1],[2,0],[1,1],[1,0],[0,-5],[-1,-3],[-1,-1],[-2,-1],[-1,-2],[-1,-2],[0,-5],[1,0],[2,4],[1,-1],[0,-1],[-2,-14],[-2,-14],[-2,-9],[-1,-12],[-1,-5],[-2,-5],[-3,10],[-2,2],[0,3],[1,11],[-1,7],[-1,0],[-1,-4],[-2,-3],[0,-4],[-2,-8],[-1,-2]],[[2438,6022],[-1,1],[-8,16],[-7,17],[-3,5],[-3,5],[-4,8],[-11,17],[-5,8],[-5,9],[-5,6],[-4,3],[-2,2],[-2,3],[-1,0],[0,-4],[1,-1],[2,-2],[2,0],[1,-1],[5,-5],[1,-3],[-13,10],[-6,1],[0,2],[2,5],[0,1],[-1,1],[-3,-4],[-1,0],[0,2],[0,2],[-2,4],[-1,-1],[-1,-2],[-3,-4],[0,-2],[5,-1],[2,-1],[-1,-2],[-4,0],[-5,-1],[-9,-12],[-9,-5],[-12,-11],[-5,-1],[-3,-2],[-8,5],[-11,10],[-16,3],[-10,14],[-11,6],[-7,13],[-4,1],[-2,2],[-10,5],[-9,3],[-10,11],[-6,4],[-5,5],[-12,8],[-4,4],[-4,7],[-6,7],[-3,5],[-3,3],[-5,10],[-2,5],[-2,2],[-2,1],[-7,-1],[-9,5],[-4,1],[-9,7],[-12,8],[-3,9],[-4,9],[-6,11],[-3,5],[-7,6],[-3,4],[-6,4],[-9,9],[-3,8],[-2,7],[-5,8],[-5,15],[-2,6],[-1,9],[-1,5],[-1,4],[0,3],[3,3],[5,1],[3,4],[0,3],[0,2],[-2,5],[-3,1],[-2,1],[0,1],[1,2],[2,5],[3,6],[2,5],[0,8],[0,7],[0,7],[-6,7],[-1,3],[-2,9],[-3,9],[0,20],[-4,17],[-4,9],[-2,3],[-6,13],[-5,8],[-4,14],[-5,10],[-6,15],[-4,8],[-19,26],[1,0],[6,-6],[1,0],[0,4],[-1,3],[-1,1],[-1,-1],[-2,1],[-1,1],[-3,1],[-4,5],[-1,4],[-1,5],[-5,11],[-2,6],[1,0],[1,-2],[2,-1],[2,0],[1,1],[-1,2],[-1,1],[-8,6],[-2,4],[-7,7],[-1,2],[-1,7],[-2,0],[-1,-2],[-4,-2],[-1,3],[0,2],[3,2],[2,6],[0,2],[-1,-2],[-2,-3],[-2,-2],[-3,-1],[-2,1],[-1,1],[-3,6],[-1,17],[2,6],[3,6],[1,4],[2,-3],[1,0],[-1,3],[-2,3],[-1,3],[0,2],[-1,5],[-5,10],[-6,-1],[-2,1],[-2,4],[-2,6],[-1,6],[0,3],[0,3],[-9,4],[-3,4],[-3,6],[-1,4],[-1,3],[-1,5],[-1,7],[1,8],[2,4],[-7,3],[-2,0],[-2,-2],[-2,2],[-4,3],[-4,8],[-6,16],[-5,5],[-2,5],[-3,5],[-2,6],[0,3],[-1,1],[-3,4],[-3,7],[-1,6],[-1,9],[-2,3],[-2,1],[0,4],[0,3],[-1,4],[-4,11],[-2,8],[-2,3],[-1,4],[0,8],[-2,10],[-4,12],[-3,8],[-1,8],[1,9],[-1,5],[0,1],[0,2],[1,-1],[1,1],[0,6],[-1,1],[-3,2],[-1,1],[-7,2],[-4,3],[-1,7],[-2,3],[-1,2],[-5,5],[-1,-3],[-1,-3],[-2,-1],[-2,0],[-3,2],[-8,11],[-2,1],[-2,1],[-1,2],[-6,5],[1,-3],[2,-3],[1,-8],[-1,-7],[-1,-22],[1,-4],[2,-7],[2,-11],[0,-8],[2,-7],[-1,-16],[1,-4],[2,-8],[4,-7],[1,-4],[5,-6],[3,-7],[7,-10],[2,-4],[6,-15],[0,-4],[1,-6],[3,1],[2,-4],[0,-2],[0,-2],[2,1],[1,-1],[3,-17],[2,-2],[2,-1],[3,-2],[0,-4],[0,-4],[2,-5],[-1,-6],[2,-6],[0,-5],[0,-4],[5,-10],[7,-8],[1,-10],[2,-9],[3,-3],[3,-3],[-1,-4],[0,-3],[4,-7],[1,-10],[3,-6],[1,1],[-2,6],[-1,4],[0,6],[0,1],[7,-10],[0,-7],[2,-4],[1,-6],[1,-3],[0,-5],[2,-8],[0,-12],[1,-8],[4,-12],[4,-3],[0,-6],[3,-16],[4,-9],[2,-7],[0,-4],[-1,-7],[0,-5],[2,-14],[3,-8],[4,-1],[0,-1],[0,-2],[1,-2],[1,2],[1,3],[-1,4],[0,3],[1,2],[1,0],[7,-10],[1,-4],[2,-4],[2,-5],[1,-5],[2,-3],[1,-8],[5,-4],[2,-7],[1,-4],[-2,-11],[-1,-3],[-3,-5],[-3,-5],[-3,-4],[-3,-2],[-2,0],[-2,7],[-3,19],[-2,4],[-1,6],[-2,5],[-7,8],[-4,8],[-4,5],[-4,8],[-10,13],[-5,7],[-2,6],[-2,0],[-2,-1],[0,2],[0,4],[-1,2],[-6,10],[-2,5],[0,6],[2,16],[0,10],[0,5],[-1,0],[0,3],[-1,8],[-1,8],[-6,18],[-4,3],[-4,3],[-10,15],[-2,8],[-1,4],[0,9],[-2,-5],[-2,-4],[-4,0],[-5,-4],[-3,4],[-1,5],[-2,5],[-3,1],[-2,0],[-3,7],[-2,2],[-4,1],[-3,4],[-1,3],[-1,6],[-1,3],[-5,6],[-4,7],[-3,4],[-2,4],[0,2],[6,0],[7,-3],[4,1],[2,2],[2,2],[0,-2],[0,-3],[2,-4],[2,-2],[2,0],[-2,3],[-1,6],[1,2],[0,3],[-3,-1],[0,2],[2,4],[3,12],[1,12],[-3,10],[-4,8],[-10,21],[-6,10],[-2,4],[-1,2],[-5,3],[-4,6],[-7,8],[-3,5],[-2,10],[-2,1],[0,8],[0,12],[-1,3],[-4,4],[-1,8],[0,8],[-1,6],[-7,10],[0,4],[0,5],[-1,4],[-3,9],[-4,8],[-2,4],[0,8],[-1,2],[1,0],[1,1],[0,5],[-6,9],[-2,11],[-3,7],[-1,2],[-2,11]],[[1746,7058],[8,1],[8,1],[8,1],[8,2],[8,1],[8,1],[8,1],[8,2],[3,0],[-2,-9],[-1,-3],[13,-8],[13,-9],[13,-8],[14,-9],[13,-8],[13,-9],[13,-8],[13,-9],[10,0],[10,0],[10,0],[10,0],[9,0],[10,0],[10,0],[10,0],[0,7],[0,6],[0,7],[0,6],[6,0],[6,0],[6,0],[6,0],[6,0],[7,0],[6,0],[6,0],[0,-1],[3,-5],[2,-7],[3,-6],[4,-3],[6,-9],[8,-15],[6,-10],[5,-5],[4,-4],[1,-4],[3,-7],[4,-19],[0,-8],[2,-8],[3,-10],[3,-6],[2,-2],[3,-3],[3,-6],[3,-3],[4,-2],[5,-5],[7,-8],[5,-4],[2,0],[2,3],[2,5],[2,3],[2,2],[0,2],[0,3],[1,8],[3,11],[3,6],[4,1],[3,3],[1,3],[2,0],[3,-2],[5,-2],[6,-1],[4,0],[1,2],[1,0],[0,-2],[1,0],[2,0],[2,-2],[2,-6],[7,-10],[1,-4],[2,-5],[5,-7],[3,-7],[0,-5],[3,-9],[4,-12],[2,-6],[-1,-1],[1,-4],[1,-6],[2,-4],[3,-4],[3,-8],[3,-10],[4,-8],[4,-5],[3,-5],[0,-5],[0,-4],[0,-3],[0,-4],[1,-3],[1,-3],[-1,-5],[0,-2],[0,-1],[4,-9],[2,-7],[2,-11],[2,-7],[2,-3],[4,-1],[3,-2],[2,-4],[3,-2],[3,-1],[3,-2],[3,-4],[5,-3],[8,-1],[6,-4],[4,-5],[2,-1],[1,1],[0,1],[2,2],[3,1]],[[9711,5520],[0,-2],[-1,0],[0,1],[1,2],[1,5],[1,2],[1,2],[0,-2],[-2,-2],[-1,-6]],[[9765,5590],[1,-1],[2,0],[2,-4],[-1,1],[-1,1],[-1,1],[-1,-1],[-1,1],[0,2]],[[9752,5595],[3,-3],[5,1],[-1,-1],[-2,0],[-1,-1],[-1,0],[-3,2],[-2,3],[0,1],[2,-2]],[[9689,5605],[-1,-1],[-2,0],[-2,2],[1,0],[2,0],[2,-1]],[[9635,5826],[-1,0],[0,1],[1,0],[0,-1]],[[5598,7617],[2,0],[3,1],[2,2],[1,1],[2,0],[2,0],[2,-1],[3,2],[2,2],[1,-1],[1,-2],[1,0]],[[5117,6286],[0,-10],[0,-15],[0,-17],[0,-15],[0,-18],[0,-14],[0,-17],[0,-17],[-1,-2],[0,-10],[0,-12],[-2,-13],[-3,-10],[-1,-9],[-1,-5],[-1,-3],[0,-3],[-1,-5],[-1,-3],[0,-1],[-3,-2],[-6,-9],[0,-8],[-6,2],[-6,2],[-1,0],[-1,-1],[0,-4],[-9,0],[-7,-1],[-9,0],[-7,-1],[-8,-1],[-7,-1],[-5,-8],[-5,-8],[-7,-2],[-7,2],[-5,0],[-1,-1],[0,-3]],[[4683,5898],[0,5],[-1,3],[-1,1],[1,4],[0,9],[0,3],[1,6],[-1,3],[0,2],[-2,4],[-1,4],[-1,4],[0,3],[-2,5],[-1,1],[-2,0],[0,-1],[-1,-3],[-1,0],[-1,3],[-1,2],[0,2],[-2,4],[-2,7],[0,6],[2,3],[0,2],[0,3],[0,3],[-1,3],[0,5],[0,8],[-2,4],[-1,3],[-2,3],[-1,5],[0,6],[1,5],[-3,9]],[[4658,6037],[5,-4],[1,1],[2,3],[2,4],[2,6],[1,8],[0,7],[1,6],[1,4],[2,5],[2,4],[3,3],[1,0],[3,-5],[5,-11],[5,-7],[1,-5],[2,0],[2,8],[2,7],[1,1],[3,1],[3,0],[2,0],[4,-1],[2,-1],[2,-1],[5,-1],[6,2],[4,2],[4,1],[0,3],[0,4],[1,3],[1,2],[1,1],[0,-9],[1,-1],[4,-1],[5,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[2,17],[1,16],[2,13],[-5,9],[-3,7],[-1,14],[0,14],[-1,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,15],[-1,14],[-1,14],[0,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,14],[-1,15],[-1,14],[0,14],[-1,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,15],[-1,14],[-1,14],[0,15],[-1,14],[-1,14],[-1,13],[9,0],[9,0],[9,0],[13,0],[10,1]],[[5404,7249],[-1,-2],[-3,0],[-2,3],[0,6],[3,-1],[2,-4],[1,-2]],[[5397,7259],[-2,-1],[-1,2],[-1,1],[3,1],[1,-1],[0,-2]],[[7727,5756],[-2,-3],[0,5],[3,4],[2,1],[-1,-3],[-1,-3],[-1,-1]],[[7727,5815],[3,-10],[-1,-2],[0,-1],[-1,1],[0,5],[-2,4],[-2,-1],[1,4],[1,1],[1,-1]],[[7737,5815],[-1,0],[-1,0],[0,1],[1,6],[1,-7]],[[7728,5845],[-1,-1],[0,1],[0,5],[1,5],[1,6],[1,1],[0,-3],[-1,-7],[0,-4],[-1,-3]],[[7737,5860],[-1,-12],[-2,2],[-2,7],[1,2],[-1,4],[4,1],[1,-4]],[[7724,5857],[0,-3],[-2,3],[0,10],[1,-6],[1,-1],[0,-3]],[[7736,5870],[-1,-1],[-1,10],[0,1],[2,-5],[2,-3],[-1,-1],[-1,-1]],[[7725,5884],[0,-1],[-1,1],[-2,4],[1,3],[0,1],[1,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-2]],[[7723,5897],[0,-2],[-1,-4],[-2,3],[0,1],[1,3],[2,-1],[0,1],[0,-1]],[[7733,5909],[1,-1],[0,-6],[-2,-7],[-1,-1],[-1,0],[1,10],[-1,6],[0,4],[2,-2],[1,-3]],[[7730,5938],[0,-9],[-1,4],[-1,6],[1,4],[0,1],[0,-1],[1,-2],[0,-3]],[[7633,6095],[-1,-1],[-1,1],[2,7],[1,-3],[-1,-4]],[[7624,6102],[-2,-5],[-1,8],[3,5],[2,4],[1,3],[1,-3],[-2,-8],[-2,-4]],[[7710,6120],[-1,-1],[-2,4],[0,9],[1,2],[1,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-8]],[[7602,6260],[-1,-1],[-3,5],[-2,7],[4,1],[3,-2],[0,-3],[0,-5],[-1,-2]],[[7602,6310],[4,-4],[1,0],[2,-3],[0,-1],[0,-3],[-1,-2],[-3,-2],[-1,2],[-1,5],[-2,3],[-1,2],[2,3]],[[7596,6330],[1,-8],[-2,3],[-1,4],[0,4],[2,-3]],[[7583,6331],[0,-5],[-1,2],[-2,8],[0,5],[1,-3],[2,-7]],[[7780,6354],[-3,4],[-1,2],[-2,0],[-2,-2],[-1,-3],[-2,0],[-2,-1],[-3,2],[-2,1],[0,-1],[1,-5],[0,-4],[0,-3],[-1,-1],[-2,-2],[-1,-1],[-2,0],[-2,2],[-2,0],[-2,-1],[-1,-1],[0,-2],[-1,-10],[-1,-3],[-1,-2],[-1,-1],[-2,1],[-1,0],[-8,-4],[-1,-1],[-2,0],[-2,0],[-2,0],[-3,4],[-2,1],[-1,-2],[-1,-5],[-2,-4],[-3,-7],[0,-12],[0,-7],[-2,-8],[-1,-4],[2,-18],[-1,-2],[-2,-1],[-2,-2],[-2,-2],[-1,0],[-2,1],[-1,0],[0,-1],[2,-8],[2,-3],[2,0],[1,-1],[0,-2],[1,-4],[2,-8],[0,-6],[-1,-6],[0,-2],[1,-1],[2,-6],[3,-8],[4,-10],[3,-7],[3,-6],[5,-9],[1,-5],[0,-9],[1,-6],[1,-4],[1,-3],[2,-11],[1,-1],[4,6],[1,-1],[0,-2],[0,-3],[-1,-4],[-1,-3],[-6,-8],[-1,-6],[0,-10],[0,-12],[0,-9],[0,-2],[-1,-1],[-2,0],[-3,-4],[-2,-1],[-1,-1],[-1,-2],[-1,-4],[1,-10],[1,-9],[3,-7],[2,-5],[2,-8],[2,-6],[4,-7],[6,-11],[3,-6],[2,-7],[1,-6],[1,-8],[0,-5],[0,-15],[-1,-3],[-1,-4],[1,-5],[1,-4],[0,-4],[1,-8],[2,-5],[3,-4],[0,-2],[0,-5],[1,-4],[0,-5],[1,-7],[2,-6],[2,-18],[0,-1],[-1,-4],[-1,-3],[-1,-1],[-1,-4],[-3,-9],[-4,-17],[-5,-10],[-4,-8],[-3,-4],[-1,-3],[0,-2],[1,-4],[0,-7],[-1,-5],[-1,-5],[0,-4]],[[7741,5771],[-1,-1],[-3,-8],[-1,4],[-1,4],[1,10],[-2,19],[1,2],[1,1],[2,8],[2,7],[0,8],[2,6],[0,5],[0,6],[0,5],[0,4],[1,5],[3,3],[-1,1],[-1,2],[-3,-3],[-2,1],[0,4],[0,3],[0,3],[2,2],[0,6],[-1,4],[1,6],[-2,0],[-1,1],[1,3],[1,3],[-1,5],[1,6],[0,7],[-1,6],[0,5],[-1,8],[-1,10],[-2,7],[-2,11],[-5,15],[0,6],[0,5],[-1,3],[-1,-19],[-1,4],[-1,10],[-1,5],[1,10],[-3,10],[0,8],[-2,11],[0,2],[3,-2],[-2,6],[-2,-1],[-2,7],[0,18],[-2,7],[1,8],[-2,25],[-3,9],[1,7],[0,6],[0,12],[1,3],[2,3],[-2,-1],[-1,-1],[-3,0],[-4,-1],[-1,9],[-2,4],[-1,9],[-1,10],[0,1],[-3,4],[0,3],[-3,6],[-3,5],[0,-3],[1,-2],[-1,-6],[1,-10],[-1,-7],[-2,-8],[-1,-4],[-4,-8],[-3,-3],[-2,-1],[-2,1],[-2,5],[-1,3],[0,6],[-1,1],[-1,0],[2,-8],[-1,-4],[3,-7],[-1,-2],[-4,-4],[-2,1],[-1,-1],[0,-3],[-1,-2],[-7,-5],[-1,-5],[-1,-6],[-3,-8],[-5,-7],[-1,1],[-1,1],[0,7],[1,7],[0,6],[-1,-4],[-3,-9],[-1,-3],[-3,1],[-3,-1],[-2,9],[0,4],[0,2],[0,3],[0,3],[-1,-5],[0,-4],[-1,-3],[-4,-4],[0,5],[-1,4],[1,4],[0,6],[1,9],[0,3],[0,4],[-1,-5],[0,-5],[-1,-2],[-1,-1],[-3,-6],[-1,-5],[-4,-5],[-2,0],[-1,7],[2,22],[1,3],[1,4],[1,13],[2,5],[0,11],[1,2],[2,8],[1,15],[-1,7],[-2,7],[-2,22],[-4,18],[-1,6],[-2,7],[2,0],[-4,6],[-1,3],[-1,15],[1,8],[-1,-1],[-1,-5],[-1,-2],[0,-9],[0,-2],[-1,-4],[-3,4],[-3,4],[-3,9],[-3,10],[1,2],[2,0],[4,-7],[2,-2],[2,2],[2,3],[1,7],[-1,2],[-2,1],[-1,2],[-2,4],[0,2],[-1,3],[-2,2],[-1,3],[1,4],[1,4],[-3,0],[-4,5],[-1,2],[-1,1],[-3,1],[-3,-2],[1,-8],[0,-3],[-2,1],[-3,12],[1,3],[1,3],[-1,1],[-1,-1],[1,12],[0,1],[-1,-3],[-1,-4],[-3,-7],[-1,1],[-1,2],[1,4],[1,1],[1,2],[-2,5],[-1,3],[-2,5],[-1,0],[1,-6],[0,-9],[-3,10],[-7,14],[-1,4]],[[5533,7691],[0,-3],[0,-2],[3,-2],[3,-4],[4,-7],[1,-2],[2,-1],[3,-3],[2,-1],[2,-1],[7,-6],[2,-2],[2,-3],[1,-2],[0,-1]],[[5537,7595],[-5,5],[-1,6],[-7,11],[-7,8],[0,1],[0,1],[0,1],[-1,1],[-1,-1],[-1,0]],[[7439,8015],[3,1],[1,1],[1,2],[3,2],[0,2],[0,5],[2,4],[4,1],[2,1],[1,-1],[3,1],[2,0],[2,-1],[1,-1],[3,0],[1,2],[0,3],[1,0],[1,-2],[1,-1],[1,-1],[3,2],[1,2],[1,3],[1,2],[2,-1],[2,0],[3,3],[3,2],[2,1],[0,2],[-1,5],[0,4],[3,3],[4,0],[3,2],[0,5],[2,1],[1,1],[3,0],[3,2],[1,1],[5,3],[3,1],[2,2],[1,2],[3,1],[2,3],[3,3],[1,0],[5,2],[1,0],[1,1],[3,0],[0,3],[3,2],[2,1],[1,2],[2,3],[2,2],[5,0],[4,0],[2,0],[2,4],[1,3],[0,2],[2,0],[2,-3],[1,-2],[3,-2],[1,-3],[2,0],[1,2],[1,4],[3,0],[2,0],[1,-2],[0,-2],[1,-4],[2,-2],[4,0],[1,0],[3,0],[3,-1],[4,-1],[1,0],[4,0],[5,-1],[2,1],[5,-1],[1,-3],[1,-6],[1,-6],[0,-5],[1,-2],[2,-1],[1,-2],[2,-2],[1,-4],[2,0],[1,1],[3,0],[3,0],[2,-2],[1,-2],[2,-2],[2,0],[4,1],[2,-1],[1,-1],[3,0],[1,1],[4,2],[2,2],[2,0],[1,-1],[1,-2],[2,1],[0,2],[2,0],[1,-1],[3,-2],[3,-3],[1,0],[3,1],[1,0],[1,-1],[2,-1],[1,1],[2,1],[7,-2],[2,-3],[1,-2],[1,-2],[2,-2],[5,1],[1,2],[4,4],[1,4],[2,1],[2,1],[1,0],[2,0],[3,3],[2,1],[2,3],[1,2],[1,4],[1,3],[1,4],[1,7],[1,4],[-1,2],[-1,2],[-3,0],[-1,2],[-2,3],[-1,3],[-1,4],[0,3],[0,2],[-1,2],[-2,3],[0,2],[0,4],[2,7],[0,3],[0,2],[0,1],[1,4],[1,2],[1,4],[2,2],[3,0],[1,1],[0,5],[1,3],[1,2],[1,3],[8,4],[4,6],[1,3],[1,7],[1,3],[2,-1],[2,-4],[2,0],[2,-2],[7,-4],[3,-2],[2,0],[3,-1],[2,-3],[4,-4],[3,-1],[5,-1],[7,0],[2,-1],[5,-3],[5,-3],[5,-3],[4,-2],[2,-2],[2,-2],[3,1],[3,0],[7,-2],[4,-3],[4,-1],[1,-3],[0,-3],[0,-2],[0,-6],[1,-4],[0,-4],[1,-4],[0,-5],[0,-2],[1,-1],[1,-3],[0,-3],[-1,-2],[1,-3],[1,-2],[2,0],[2,-1],[2,-4],[4,-4],[2,-1],[2,-2],[5,-2],[4,-1],[2,-1],[2,-4],[3,-1],[2,-1],[4,-1],[2,1],[3,1],[1,0],[3,-1],[3,0],[3,0],[2,3],[3,4],[3,1],[4,1],[2,1],[8,3],[4,0],[2,2],[2,2],[4,1],[4,-2],[4,-1],[5,-1],[4,-2],[2,-2],[4,-2],[4,1],[6,1],[3,-1],[4,-4],[3,-3],[3,-6],[2,-3],[3,-3],[3,0],[8,0],[4,-2],[4,0],[1,-2],[-1,-4],[1,-6],[-1,-3],[1,-2],[1,-1],[1,-3],[2,-1],[3,-3],[6,-7],[3,-3],[2,-1],[4,0],[5,0],[9,0],[6,-2],[2,-1],[6,-2],[7,-2],[5,-2],[4,3],[3,0],[2,-2],[3,-3],[2,0],[4,2],[10,8],[4,3],[2,-1],[3,1],[1,1],[5,1],[3,0],[2,1],[5,1],[8,5],[3,1],[6,-2],[3,1],[3,3],[4,3],[1,4],[2,6],[4,4],[3,4],[4,4],[4,3],[5,3],[5,6],[4,3],[2,1],[3,-2],[4,0],[4,0],[1,-1],[4,-3],[4,-2],[2,-5],[5,-6],[3,-2],[2,-1],[4,-1],[4,0],[2,1],[3,3],[6,3],[2,0],[4,-2],[6,-3],[2,-2],[1,-3]],[[9034,5999],[-1,-2],[-1,0],[-1,1],[0,2],[2,1],[1,0],[0,-2]],[[9045,6046],[-1,-3],[-1,5],[0,2],[1,1],[1,0],[0,-5]],[[9048,6055],[0,-1],[-2,0],[0,1],[1,5],[2,3],[1,0],[-1,-2],[0,-3],[-1,-3]],[[9047,6125],[-1,0],[-1,0],[0,1],[-1,1],[2,0],[1,-1],[0,-1]],[[9048,6225],[-1,-1],[2,6],[0,1],[1,-3],[-2,-3]],[[9047,6264],[-1,-2],[-1,2],[0,3],[1,0],[1,-1],[0,-2]],[[5913,3637],[-3,0],[-5,0],[-3,0],[-4,0],[-4,1],[-3,0]],[[5891,3638],[0,18],[-1,4],[0,6],[-1,4],[1,4],[0,6],[0,5],[-3,3],[0,1]],[[5887,3689],[-1,4],[0,6],[2,8],[0,16],[0,6],[0,11],[0,13],[0,12],[0,10],[-1,5],[0,2],[-1,6],[-2,11],[-1,9],[-2,5],[-1,3],[-1,4],[-2,7],[-1,4],[-1,4],[0,8],[-2,15],[-1,11],[-2,12],[-1,8],[0,1],[0,3]],[[5869,3893],[3,6],[4,9],[5,10],[4,8],[4,8],[5,11],[5,10],[1,1],[0,1],[-2,9],[4,11],[0,7],[0,7],[0,3],[1,3],[4,5],[3,9],[2,8],[4,14],[0,3],[0,3],[-1,5],[-2,7],[-2,6],[-1,10],[1,9],[1,5],[0,2],[-1,3],[-1,2],[-2,1],[0,4],[0,4],[0,2],[4,4],[1,2],[0,2],[0,4],[1,8],[2,7],[0,3],[-1,2],[0,5],[0,6],[0,19],[1,18],[-1,11],[-2,12],[0,9],[1,7],[1,3],[-2,1],[-2,0],[-2,1],[-3,5],[-5,5],[-6,3],[-8,2],[-7,12],[-6,2],[-2,1],[-5,8],[-8,1],[-9,0],[-5,0],[-1,1],[0,11],[0,9]],[[5844,4283],[-1,8],[-1,9],[-1,3],[-1,6],[-1,7],[0,3],[0,1],[6,5],[3,3],[3,2],[7,4],[6,3],[6,4],[5,3],[3,3],[3,2],[7,5],[2,1],[4,3],[2,1],[8,5],[9,6],[3,3],[6,4]],[[5922,4377],[1,-2],[4,-14],[3,-9],[4,-7],[1,2],[2,1],[6,1],[2,0],[2,3],[3,1],[3,1],[1,-1],[4,-10],[0,-8],[1,-11],[0,-5],[0,-7],[0,-9],[-3,-11],[-1,-5],[-1,-8],[-2,-4],[-1,-3],[0,-3],[1,-3],[2,-5],[1,-3],[0,-3],[0,-4],[0,-3],[1,-2],[3,-2],[2,-7],[4,-7],[5,-12],[2,-3],[2,-1],[1,-4],[-1,-4],[-1,-2],[0,-4],[1,-2],[1,-1],[2,0],[2,1],[1,1],[-1,17],[-1,9],[-1,4],[-1,1],[1,3],[1,8],[2,7],[1,3],[1,2],[6,2],[3,2],[2,2],[1,6],[0,16],[1,15],[-1,9],[1,13],[1,8],[0,2],[-1,11],[-4,12],[-6,15],[-3,8],[-3,9],[-7,15],[-3,5],[-2,2],[-5,2],[-1,3],[-1,4],[-1,9],[0,6],[-1,10],[-1,15],[0,5],[-2,11],[-1,10],[0,3],[0,3],[3,8],[1,5],[1,3],[2,8],[0,4],[1,2],[5,1],[4,0]],[[5971,4517],[6,0],[6,0],[1,-1],[2,-1],[1,1],[2,1],[2,3],[2,4],[4,0],[5,-5],[2,-4],[1,-3],[3,-2],[6,-1],[4,2],[3,4],[3,2],[3,1],[2,-2],[1,-3],[3,-2],[5,-2],[4,2],[5,6],[3,5],[1,6],[1,4],[1,1],[2,1],[5,0],[4,-2],[5,-6],[3,4],[5,7],[5,4],[5,0],[5,2],[3,5],[3,3],[4,2],[3,2],[5,6],[5,7],[5,8],[3,5]],[[6123,4581],[2,-6],[2,-5],[-1,-3],[-2,-3],[3,-4],[-2,-6],[0,-4],[0,-1],[1,-3],[-2,-6],[-2,-5],[0,-4],[1,-7],[0,-12],[1,-10],[1,-6],[0,-4],[-1,-6],[1,-11],[0,-5],[-1,-6],[2,-2],[1,-6],[-1,-7],[0,-4],[-3,-4],[0,-2],[0,-3],[3,0],[0,-4],[0,-4],[0,-6],[0,-4],[1,-5],[-1,-5],[0,-4],[0,-5],[1,-13],[0,-16],[0,-2],[2,-2],[1,-1],[0,-4],[-2,-6],[0,-4],[0,-5],[3,7],[1,0],[1,-3],[0,-3],[0,-2],[0,-4],[1,-5],[0,-4],[-2,-3],[-2,-5],[0,-5],[0,-3],[-2,-1],[0,-2],[1,-4],[0,-4],[-3,-12],[-7,-17],[-3,-6],[-2,-7],[0,-2],[-1,-3],[-3,-9],[-3,-1],[-2,-3],[1,-8],[-2,-2],[-4,-6],[-11,-12],[-1,-3],[-3,-8],[-3,-2],[-2,-2],[-4,-1],[-1,1],[-1,0],[-1,-2],[-7,-5],[-7,-4],[-2,-2],[-1,-3],[-6,-4],[-9,-10],[-7,-10],[-5,-10],[-2,-1],[-2,-4],[0,-5],[-1,-2],[-4,-11],[-6,-12],[-1,-3],[-2,-7],[0,-4],[-3,-2],[-1,5],[-1,-9],[-2,0],[-1,2],[-4,-5],[-4,-4],[-5,-10],[-8,-19],[-12,-18],[-1,-1],[-1,0],[-4,7],[-2,0],[2,-4],[1,-3],[0,-6],[0,-9],[-2,-18],[0,-4],[2,-6],[3,-6],[3,-8],[4,-22],[0,-12],[4,-14],[0,-7],[2,-16],[0,-12],[-1,-8],[2,-4],[1,3],[0,5],[0,8],[1,4],[1,-1],[1,-3],[0,-4],[1,-3],[0,-4],[-2,-16],[1,-7],[2,-11],[-3,-13],[-3,-30],[0,-5],[1,-2],[1,-1],[1,4],[1,0],[1,-2],[-2,-14],[-1,-6],[-5,-15],[-3,-7],[-5,-6],[-10,-10],[-22,-14],[-8,-7],[-5,-4],[-11,-13],[-5,-9],[-2,-10],[-1,-5],[-2,-6],[1,-5],[2,-4],[2,-2],[1,-3],[1,-1],[1,8],[1,2],[1,0],[-1,-9],[-1,-34],[0,-1]],[[5962,4492],[-1,1],[-1,1],[-1,0],[0,-2],[1,-3],[1,0],[1,3]],[[5964,4486],[1,2],[0,1],[0,2],[-1,1],[-1,0],[-1,-2],[0,-3],[1,-1],[1,0]],[[4545,6319],[-2,-6],[-1,2],[0,4],[1,5],[1,3],[2,1],[-1,-9]],[[4658,6037],[-3,4],[-2,5],[-2,4],[-3,3],[-2,2],[-1,4],[-1,2],[-2,1],[0,1],[1,1],[-1,3],[-2,7],[-1,3],[-2,-1],[-1,1],[0,2],[0,2],[-2,2],[-1,0],[-2,5],[-1,9],[-1,7],[-2,5],[-1,2],[-1,0],[0,1],[-1,1],[-1,1],[-2,-2],[-2,1],[0,2],[-2,0],[-1,-2],[-2,1],[-1,3],[-1,3],[-1,3],[-3,6],[-6,10],[-6,4],[-7,0],[-4,0],[-1,1],[-1,0],[-1,-1],[-1,-1],[-1,1],[0,-3],[-3,-1],[-5,0],[-3,-2],[-3,-2],[-4,-2],[-6,1],[-3,1],[-1,1],[-2,1],[-2,-1],[-1,-5],[-2,-8],[-1,-5],[-1,-1],[-1,-6],[-1,-10],[-1,-5]],[[4540,6096],[0,26],[2,10],[0,8],[3,19],[4,15],[4,20],[1,20],[0,19],[-1,18],[-2,11],[-2,16],[-2,9],[-5,8],[-1,4],[1,2],[3,1],[2,6],[-4,-3],[4,19],[2,12],[-1,8],[1,5],[-3,11],[-3,13],[-1,2],[-2,2],[0,-4],[-1,-2],[-1,1],[-3,10],[-4,16],[-2,2],[-1,-2],[-1,-2],[-1,-14]],[[4526,6382],[0,6],[0,6],[1,8],[1,10],[4,0],[6,0],[7,0],[6,0],[6,0],[7,0],[6,0],[6,0],[7,0],[6,0],[7,0],[6,1],[6,0],[7,0],[6,0],[6,0],[7,0],[4,0],[0,7],[0,6],[-1,8],[0,9],[0,8],[-1,7],[0,8],[0,7],[0,7],[-1,3],[-1,8],[0,3],[0,4],[1,4],[3,7],[3,5],[5,6],[3,4],[2,1],[5,2],[4,3],[4,4],[2,1],[0,7],[0,7],[0,8],[0,7],[0,8],[0,8],[0,8],[0,8],[0,8],[0,7],[0,8],[0,8],[0,8],[0,8],[0,8],[0,8],[0,7],[0,8],[0,7],[4,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[0,7],[0,9],[0,13],[0,13],[0,11],[0,12],[0,9]],[[3273,6148],[0,-3],[-2,1],[0,3],[1,3],[1,0],[0,-4]],[[6601,4004],[-4,-2],[-4,1],[-1,3],[0,1],[1,1],[0,4],[0,7],[1,2],[2,3],[1,5],[2,3],[2,0],[2,-6],[2,-6],[-1,-7],[-1,-2],[-1,-4],[-1,-3]],[[5922,4377],[-2,4],[-1,-1],[-2,-3],[-1,-1],[0,1],[-1,2],[-1,5],[-2,4],[-1,1],[-1,2],[0,2],[1,1],[-1,1],[0,2],[-3,3],[0,1],[2,2],[2,3],[1,3],[1,5],[1,6],[1,2],[0,4],[0,4],[1,6],[0,5],[-1,2],[0,3],[0,6],[2,4],[6,5],[4,3],[1,2],[2,3],[0,4],[0,1],[-4,0],[0,1],[-3,11],[1,13],[1,5],[0,6],[-1,5],[-1,2],[-1,2],[1,7],[1,1],[2,9],[1,5],[-2,4],[-1,6],[0,4],[-1,1],[1,3],[2,2],[1,1],[2,1],[5,11],[0,2],[-1,4],[-2,5],[0,3],[0,6],[-1,2],[-3,5],[-2,5],[0,4],[1,6],[-1,3],[-2,3],[-1,4],[0,3],[-2,2],[-1,0],[-1,-2],[-1,0],[-1,1],[0,2],[0,3],[-1,3],[-1,2],[0,2]],[[5914,4642],[1,1],[5,-6],[2,0],[3,-1],[3,-6],[1,0],[2,0],[4,1],[2,-1],[3,-3],[1,0],[1,0],[1,1],[0,1],[-1,4],[1,2],[1,2],[2,-3],[7,-11],[0,-1],[4,-11],[1,-5],[0,-2],[2,-10],[0,-5],[0,-3],[0,-3],[0,-4],[0,-1],[2,-6],[0,-5],[0,-5],[0,-4],[-1,-7],[-1,-3],[1,-2],[1,-3],[1,-3],[1,-4],[1,-4],[0,-1],[1,0],[1,-1],[2,-2],[1,-4],[0,-5],[1,-2]],[[8093,5323],[-1,-1],[-1,2],[0,18],[1,1],[1,-3],[0,-8],[0,-7],[0,-2]],[[7894,5341],[-1,0],[-1,0],[0,2],[1,5],[0,1],[1,-5],[0,-3]],[[7814,5356],[-2,-1],[0,1],[0,2],[1,2],[1,-1],[0,-3]],[[8267,5424],[1,2],[0,3],[1,0],[1,0],[4,-4]],[[7785,5489],[-1,-2],[-2,1],[1,10],[1,1],[2,-2],[0,-2],[-1,-6]],[[7773,5556],[2,-6],[-1,-3],[-1,0],[-1,0],[-1,-2],[-1,0],[-1,4],[-2,2],[0,2],[2,1],[1,-1],[2,2],[1,1]],[[7835,5543],[5,-2],[2,-2],[5,-18],[8,-12],[3,-5],[2,-2],[3,-7],[3,-8],[6,-24],[1,-10],[0,-16],[-1,-24],[-2,-12],[1,-6],[2,-8],[-1,-9],[1,-6],[0,-19],[1,-6],[1,-3],[8,-12],[0,-4],[4,-14],[7,-31],[2,-14],[0,-4],[-1,-1],[-2,-2],[-2,3],[0,2],[0,3],[-1,2],[-1,3],[-1,2],[0,-4],[0,-5],[-2,-1],[-3,2],[-3,-2],[-4,-6],[-2,-1],[-2,6],[-1,4],[-1,3],[-13,14],[-4,4],[-5,10],[-11,12],[-8,12],[-3,7],[-7,6],[-3,8],[-1,1],[-2,3],[2,7],[-1,8],[-1,6],[-5,13],[-3,9],[-4,8],[-2,5],[-2,6],[1,2],[1,2],[-1,4],[-3,7],[-1,9],[0,16],[-4,22],[-3,32],[0,11],[0,11],[-3,12],[-3,8],[-1,7]],[[7780,5555],[1,3],[0,8],[1,2],[1,1],[1,0],[3,-8],[6,-5],[1,-1],[3,2],[1,-1],[1,-2],[1,-6],[1,-4],[3,0],[2,0],[0,-1],[1,-4],[0,-8],[0,-4],[-2,-6],[-1,-5],[1,-2],[2,-3],[1,-3],[1,1],[1,1],[1,4],[1,3],[4,4],[4,3],[1,0],[0,-2],[2,-4],[1,-1],[1,-1],[2,1],[2,2],[1,5],[1,4],[3,7],[0,5],[1,3]],[[8044,5301],[2,-8],[1,-2],[4,-6],[3,-2],[4,-1],[4,-1],[1,1],[1,1],[2,-1],[8,-9],[2,-2],[4,1],[1,-1],[4,-7],[2,0],[2,0],[-3,3],[-2,2],[-1,5],[1,4],[2,3],[1,3],[0,9],[1,5],[1,5],[1,4],[-2,3],[0,6],[0,5],[1,3],[2,-2],[1,-2],[2,0],[1,1],[0,2],[0,5],[0,8],[2,6],[3,4],[3,2],[11,4],[17,9],[5,3],[2,2],[1,2],[3,8],[5,13],[3,10],[8,15],[6,14],[1,3],[1,7],[0,4],[-1,4],[1,1],[1,1],[1,0]],[[8198,5466],[6,2],[2,2],[2,5],[1,2],[1,6],[-3,3],[-2,5],[0,5],[4,8],[1,3],[1,-4],[2,0],[1,-1],[2,1],[2,4],[1,7],[4,9],[1,7],[1,7],[10,22],[1,4],[6,23],[1,0],[2,-2],[0,-7],[0,-3],[-1,-5],[-1,-5],[1,0],[3,3],[3,8],[1,7],[2,3],[3,-1],[0,-2],[0,-5],[0,-2],[1,-7],[3,-3],[3,-3],[3,-3],[1,-2],[1,-3],[0,-4],[1,-5],[-3,-4],[1,-7],[0,-5],[-1,-3],[-3,-3],[9,3],[2,2],[3,4],[2,-4],[1,-7],[-1,-1],[-4,-3],[0,-1],[1,-4],[2,1],[3,2],[3,4],[1,0],[2,-1],[3,-2],[1,-2],[2,-3],[0,-5],[4,-2],[7,-7],[1,-1],[1,0],[4,1],[1,-1],[1,-3],[0,-3],[0,-4],[0,-3],[-1,-2],[-3,-3],[-6,-5],[-6,-3],[-4,0],[-4,3],[-2,-1],[-2,-1],[-2,-9],[4,-9],[7,-10],[0,-2],[0,-3],[-1,-2],[-1,-1],[-4,-1],[-4,-2],[-3,-1],[-3,-2],[-3,0],[-4,5],[-1,0],[-2,-2],[-1,-6],[-1,-2]],[[8253,5597],[-2,-3],[0,3],[0,5],[2,4],[4,1],[0,-3],[0,-4],[-1,-2],[-3,-1]],[[5649,4168],[6,2],[6,2],[6,3],[5,1],[2,1],[12,-2],[6,-2],[2,-1],[2,-4],[5,-9]],[[5554,3757],[0,-24],[0,-26],[0,-26],[0,-25],[0,-26],[0,-26],[0,-25],[0,-26],[0,-8],[-2,0],[-6,-3],[-4,-4],[-1,-5],[-2,-3],[-3,-1],[-1,-3],[0,-4],[-1,-3],[-2,-2],[-4,1],[-5,3],[-7,1],[-8,-2],[-6,1],[-3,3],[-4,2],[-4,1],[-2,1],[-5,3],[-1,4],[0,4],[-2,3],[0,3],[1,2],[0,4],[0,5],[-2,2],[-1,0],[-2,2],[0,3],[-1,3],[-3,3],[-3,-2],[-2,-3],[-1,-6],[-1,-2],[0,-5],[0,-3],[-1,-3],[-1,-1],[-1,0],[-2,-1],[-4,-5],[-1,-3]],[[5456,3535],[-3,5],[-9,18],[-3,4],[-5,11],[-10,33],[-2,7],[-2,16],[-2,12],[0,7],[1,4],[-1,5],[-1,5],[-4,6],[-1,21],[-2,13],[0,11],[-1,10],[0,7],[1,12],[-2,14],[-4,14],[-4,20],[0,9],[0,23],[-1,10],[1,11],[-2,12],[0,6],[1,5],[0,-2],[1,0],[1,6],[0,6],[-2,15],[-4,15],[-9,24],[-3,9],[-1,8],[-11,32],[-5,23],[-3,19],[-3,9],[-16,64],[-4,10],[-7,12],[-1,4],[-3,11],[-4,16],[-2,14],[0,17],[1,12]],[[9653,3881],[-1,-2],[-1,0],[-1,1],[0,1],[0,4],[3,-2],[0,-2]],[[9666,3949],[1,-1],[3,1],[-1,-10],[-3,-2],[-1,0],[-1,2],[-2,2],[0,3],[-1,8],[3,1],[1,2],[0,-2],[1,-2],[0,-2]],[[9649,3965],[-1,0],[-2,4],[-4,2],[-2,3],[-1,5],[2,1],[2,6],[-1,2],[-3,0],[0,2],[5,3],[1,-2],[1,-1],[0,-10],[2,-2],[2,-7],[0,-2],[-1,-4]],[[9625,3992],[-1,-1],[2,5],[0,4],[0,6],[0,2],[2,0],[1,-2],[-2,-2],[0,-2],[0,-4],[0,-1],[0,-3],[-2,-2]],[[9560,4018],[3,-4],[4,2],[4,-6],[11,-17],[3,-4],[3,-1],[1,-3],[2,-4],[2,-3],[1,-3],[0,-3],[1,-2],[4,-6],[2,-5],[3,-3],[1,-3],[2,-1],[2,-3],[3,-3],[7,-8],[5,-9],[2,-5],[3,-5],[4,-3],[3,-5],[2,-9],[-1,-4],[-2,-2],[-2,0],[-1,-1],[-6,6],[-1,1],[-2,0],[-1,1],[0,2],[-4,3],[-3,3],[-1,3],[0,3],[-1,2],[-5,3],[-3,3],[-2,4],[-3,4],[-6,6],[-2,2],[-3,3],[-6,11],[-3,3],[-2,5],[-5,12],[-3,5],[-3,4],[-2,5],[-2,6],[-4,9],[0,4],[0,4],[-1,2],[-2,2],[0,2],[0,4],[0,2],[4,-6]],[[9442,4071],[0,-1],[0,9],[0,4],[1,-7],[-1,-5]],[[5416,6508],[3,-33],[2,-29],[0,-18],[0,-4],[1,-4],[2,-3],[9,-26],[-2,-5],[1,-8],[3,-4],[7,-15],[1,-3],[-1,-3],[-5,-18],[0,-5],[-1,-23],[-1,-17],[-1,-23],[-1,-27],[-1,-23],[-2,-30],[-1,-29],[-7,-16],[-13,-28],[-10,-23],[-6,-15],[-10,-30],[-5,-19],[-3,-11],[-2,-4],[2,-14],[2,-25]],[[5377,5973],[-5,0],[-2,-2],[-4,-5],[-4,-3],[-5,-5],[-3,-4],[-3,-3],[-4,-7],[-1,-6],[-4,-1],[-6,1],[-3,6],[-9,6],[-5,2],[-3,1],[-12,1],[-14,-2],[-6,-3],[-2,-1],[-3,-4],[-4,-4],[-8,-18],[-12,0],[-7,2],[-5,3],[-9,9],[-10,13],[-4,2],[-3,1],[-1,0],[-12,-13],[-2,0],[-3,-1],[-2,-4],[-1,-1],[-2,-1],[-2,1],[-2,2],[-2,4],[-4,15],[-1,2],[-3,5],[-3,6],[-3,4],[-1,0],[-2,0],[-9,6],[-10,6],[-2,-1],[-2,-1],[-3,-5],[-4,-1],[-5,1],[-3,0],[-4,-1],[-3,-2],[-4,-3],[-5,-9],[-1,-1],[-1,-1],[-2,-23],[-1,-7],[-3,-9],[-5,-9],[-3,-5],[0,-8],[-1,-11],[0,-8],[1,-6],[-1,-2],[0,-3],[0,-3],[1,-2],[0,-2],[0,-1],[-2,-3]],[[9664,3512],[1,0],[0,-1],[0,-1],[0,-1],[0,-1],[-1,1],[-1,0],[0,1],[0,1],[1,0],[0,1],[-1,0],[0,1],[1,-1]],[[5202,5438],[-2,-1],[-2,0],[2,8],[1,-2],[2,-1],[-1,-4]],[[5377,5973],[5,-12],[4,-14],[4,-10]],[[5237,5458],[-1,-2],[-2,1],[-1,4],[-2,1],[-2,5],[-1,-1],[3,-14],[-1,-6],[-8,0],[-6,-2],[-4,0],[-2,3],[-1,5],[-1,-1],[0,-3],[-1,-2],[-5,0],[-2,3],[-2,5],[-2,1],[0,-1],[2,-4],[0,-6],[-4,-7],[-2,0],[-2,3],[-1,4],[0,7],[-1,5],[-1,0],[1,-4],[0,-4],[0,-7],[2,-5],[-3,-2],[-1,0],[-2,0],[-1,2],[0,4],[-1,2],[0,-8],[-2,-1],[-1,0],[-5,-1],[-1,0],[0,1],[1,3],[0,3],[-2,-3],[0,-5],[-1,-1],[-3,1],[-3,3],[-1,3],[-3,3],[-6,11],[-1,5],[-2,7],[-1,6],[-2,10],[1,1],[1,-1],[1,2],[-3,1],[0,1],[-1,4],[1,4],[2,2],[1,1],[1,2],[1,3],[-5,-4],[-4,5],[-1,3],[0,2],[2,0],[3,0],[2,2],[-1,1],[-2,0],[-1,1],[0,4],[0,-1],[-1,-3],[-3,-2],[-1,2],[-1,5],[0,2],[-1,2],[-5,13],[-7,11],[-5,7],[-9,4],[-18,0],[-1,1],[1,2],[2,1],[6,6],[-1,1],[-6,-4],[-2,0],[-3,-8],[-15,-1],[-2,0]],[[2690,6047],[-1,-2],[-1,-1],[-2,-7],[0,-1],[0,5],[-1,1],[-2,-2],[0,-2],[1,-4],[1,0],[1,-1],[3,-23],[-1,-4],[-2,-7],[-1,-6],[-2,-3],[-3,-15],[-2,-24],[2,-22],[-1,-20],[1,-4],[0,-6],[-2,-1],[-1,3],[0,4],[1,3],[0,5],[0,3],[-1,-6],[-2,-2],[-1,-1],[-1,-3],[1,-6],[2,-4],[0,-2],[0,-4],[-1,-12],[0,1],[-1,1],[-1,0],[0,-4],[0,-3],[-1,-2],[-1,-2],[1,-1],[1,-1],[2,0],[1,-6],[0,-5],[-3,-4],[0,-4],[-2,-4],[-1,-4],[0,-3],[1,-10],[2,-7],[1,-4],[2,-1]],[[2618,5821],[0,1],[-2,7],[-4,7],[-14,24],[-5,14],[-3,10],[-3,5],[-7,11],[-2,4],[-8,15],[-5,8],[-1,4],[3,4],[1,0],[1,-3],[2,-4],[1,0],[2,2],[0,1]],[[283,4085],[-3,-4],[-1,4],[1,5],[2,1],[1,-4],[0,-2]],[[3105,5883],[-1,-6],[-1,3],[0,5],[-1,2],[-1,1],[-1,2],[1,2],[4,-4],[0,-5]],[[3251,6192],[0,-2],[-1,0],[0,2],[0,2],[0,-1],[1,-1]],[[5093,8143],[2,1],[4,0],[4,-1],[4,-1],[4,2],[3,-2],[3,2]],[[5109,8164],[3,-3],[0,-1],[1,-1],[-4,-2],[-3,4],[-3,-1],[-1,2],[0,1],[3,1],[4,0]],[[5135,8241],[-3,-4],[-1,1],[-1,1],[1,3],[4,5],[0,-6]],[[5141,8254],[-5,-4],[0,1],[3,3],[2,0]],[[5117,8144],[-3,0],[-3,3],[-5,-2],[-4,2],[-3,0],[-2,2],[-2,3],[2,3],[1,0],[5,1],[4,-2],[8,-6],[1,0],[2,0],[-1,2],[-2,1],[-2,2],[-2,3],[5,0],[-1,2],[-1,2],[-5,8],[1,2],[1,5],[2,4],[1,1],[2,2],[5,8],[3,7],[2,7],[3,22],[1,3],[2,4],[2,-1],[1,-1],[5,3],[8,8],[3,7],[2,3],[10,6],[5,2],[8,0],[6,2],[7,0],[2,-4],[2,-3],[3,-1],[3,-1]],[[5166,8107],[-5,0],[-2,0],[-1,1]],[[5147,8259],[-2,-1],[-1,1],[6,2],[4,1],[1,0],[-8,-3]],[[5164,8263],[-5,-1],[-2,1],[1,1],[5,0],[1,-1]],[[5175,8266],[-3,-2],[-1,0],[0,1],[3,1],[1,0]],[[5187,8270],[-3,0],[1,1],[2,2],[1,0],[-1,-3]],[[5141,8657],[0,-6],[-3,0],[-1,3],[0,1],[0,4],[-1,4],[1,2],[1,1],[2,-4],[1,-5]],[[5137,8702],[-2,-1],[-2,1],[1,6],[1,0],[1,1],[2,-3],[-1,-4]],[[5225,8832],[-3,0],[-3,1],[-2,2],[-1,1],[4,2],[4,2],[1,-3],[1,-3],[-1,-2]],[[5235,8851],[-3,0],[-2,1],[4,3],[7,2],[1,2],[1,0],[1,-2],[0,-3],[0,-1],[-9,-2]],[[5311,8920],[-1,-2],[-3,2],[-7,-1],[-2,1],[2,3],[6,3],[3,0],[3,-4],[-1,-2]],[[5332,8964],[-2,-2],[-3,1],[-1,1],[1,3],[2,1],[3,0],[1,-1],[-1,-3]],[[5347,8980],[-2,-1],[0,3],[1,2],[2,1],[3,1],[3,0],[0,-1],[-1,-2],[-6,-3]],[[5344,8988],[-2,-1],[0,3],[2,2],[1,2],[1,2],[1,1],[3,-1],[0,-4],[-1,-3],[-5,-1]],[[5360,9093],[-4,-3],[1,6],[2,5],[3,4],[2,-2],[-1,-2],[0,-3],[0,-1],[-3,-4]],[[5385,9116],[1,-1],[5,0],[1,0],[-1,-2],[-2,-2],[-4,-1],[-2,-3],[-1,0],[-3,0],[-2,-1],[-3,-3],[-2,2],[0,-1],[-1,-2],[-1,-1],[-3,-1],[-1,6],[2,1],[1,3],[2,0],[1,0],[4,5],[4,1],[2,0],[3,0]],[[5422,9155],[3,-6],[2,-3],[-1,-7],[-4,-3],[-5,-1],[-4,1],[-2,1],[-1,2],[-1,0],[-4,-2],[-2,0],[-3,2],[-1,2],[3,4],[2,3],[4,-1],[3,-1],[1,3],[0,3],[1,1],[4,-1],[0,6],[2,1],[1,-1],[1,-1],[1,-2]],[[5437,9133],[1,-1],[3,6],[5,2],[0,2],[1,1],[0,4],[1,2],[2,1],[2,1],[1,0],[3,-2],[1,-2],[2,-5],[-1,-5],[-5,-4],[-4,-1],[-4,-5],[-2,-3],[-2,-1],[-1,0],[-1,1],[-2,0],[-2,-3],[-7,-2],[-2,0],[-1,3],[-1,0],[-3,-4],[-2,-1],[-2,0],[-3,1],[-8,-6],[-8,-1],[-2,0],[-1,4],[6,5],[4,4],[14,2],[9,10],[2,11],[2,4],[-1,2],[-3,0],[0,4],[2,4],[4,5],[3,2],[4,6],[2,1],[2,0],[3,-1],[-1,-3],[-3,-6],[-5,-6],[0,-3],[2,-3],[1,-5],[0,-5],[-4,-7],[-1,-3]],[[5486,9192],[3,-3],[1,1],[3,1],[3,-2],[1,-2],[3,0],[1,-3],[1,-3],[-2,-3],[-2,-1],[-1,-3],[1,-4],[-5,-2],[-6,-1],[-2,2],[-4,-3],[-5,-6],[-2,-1],[0,2],[-3,1],[-5,0],[1,2],[0,1],[4,1],[1,3],[-1,5],[1,3],[0,2],[2,2],[8,-1],[1,2],[-1,1],[-4,3],[1,1],[3,1],[2,1],[1,2],[0,1],[1,0]],[[5832,9204],[-6,-2],[0,2],[1,2],[1,4],[2,0],[3,-2],[1,-2],[-2,-2]],[[5577,9221],[-2,-1],[-2,-1],[-1,1],[-2,0],[-2,0],[-2,3],[0,2],[3,2],[4,2],[4,-1],[1,0],[-1,-7]],[[5534,9220],[3,-4],[2,1],[1,1],[1,0],[3,-1],[0,-3],[-4,-4],[-3,-5],[-4,-1],[-2,1],[-4,-3],[-2,-3],[-3,-4],[0,-2],[-1,-2],[-10,-1],[-4,-1],[-4,1],[-2,3],[1,1],[4,1],[0,2],[1,2],[1,0],[1,3],[2,1],[3,-1],[2,3],[1,0],[1,-2],[1,3],[-1,2],[1,1],[3,4],[2,3],[2,2],[3,0],[0,3],[0,2],[0,2],[2,5],[2,0],[1,-4],[0,-6]],[[5549,9228],[1,-1],[1,1],[2,-1],[2,-3],[2,-1],[0,-1],[-2,-2],[-3,0],[-3,0],[-1,2],[-1,3],[-3,3],[0,3],[2,0],[3,-3]],[[5655,9247],[1,-2],[0,-3],[-2,-3],[-6,-4],[0,-1],[-2,-1],[-3,-1],[-2,1],[0,3],[0,1],[-3,-1],[-2,2],[0,2],[1,1],[2,3],[4,1],[2,0],[9,6],[0,-1],[1,-3]],[[5667,9248],[-6,-2],[-3,2],[-1,2],[0,5],[0,2],[3,2],[2,-1],[0,-1],[3,-1],[3,-3],[-1,-5]],[[5651,9263],[-1,-2],[-1,-2],[-2,-2],[-7,-7],[-4,-1],[-1,-1],[-1,-1],[-5,1],[-2,-2],[-1,-1],[-3,0],[-2,0],[-6,3],[-3,3],[-2,3],[5,-1],[2,1],[3,0],[2,2],[4,0],[8,2],[3,-1],[7,6],[2,0],[3,1],[2,-1]],[[5857,9203],[1,-7],[0,-3],[0,-3],[-1,-1],[-2,0],[-5,0],[-7,3],[-4,3],[-1,0],[-1,-1],[1,-2],[0,-3],[-1,-2],[-1,-2],[-1,-2],[-2,-2],[-5,-2],[-12,-4],[-1,-1],[-4,-10],[-1,-2],[-2,-1],[-4,-2]],[[5572,9160],[-3,0],[-11,-1],[5,-5],[1,-2],[1,-3],[-1,-5],[-2,-5],[-3,-4],[-5,-3],[8,-4],[-5,-5],[-3,-2],[-3,0],[-5,2],[-12,4],[-5,2],[-5,0],[-3,0],[-11,4],[-2,-1],[-4,-1],[0,-4],[0,-8],[0,-7],[-1,-4],[-2,-2],[-4,-8],[-10,5],[-6,3],[-5,-4],[-10,-8],[-6,-15],[-3,-4],[-5,-2],[-3,-1],[-2,-5],[5,-6],[2,-4],[2,-5],[0,-4],[-1,-2],[-4,-4],[-10,-12],[-9,-13],[-4,-3],[2,-11],[-3,-3],[-7,-4],[-3,-1],[-3,-1],[-11,-1],[2,-12],[1,-5],[0,-3],[-1,-3],[-1,-5],[-2,-20],[-2,-2],[-2,-5],[-6,-13],[-6,-9],[-7,-12],[6,-4],[6,-3],[1,-5],[0,-7],[0,-5],[-2,-4],[-2,-4],[-1,-1],[-8,1],[-10,2],[-3,0],[-6,-1],[-5,-3],[-3,-2],[-1,-1],[-3,-6],[-7,-10],[-3,-4],[1,-6],[-6,-12],[4,-11],[0,-1],[2,-4],[-2,-4],[-1,-1],[0,-6],[1,-6],[-1,-3],[0,-4],[5,-18],[0,-4],[0,-2],[-2,-11],[-2,-15],[4,-4],[5,-5],[3,-2],[5,-5],[3,-5],[0,-4],[-1,-4],[-2,-3],[-1,-3],[-1,-3],[0,-1],[-6,0],[-3,-1],[-2,-2],[1,-6],[3,-12],[3,-8],[1,-5],[-1,-6],[-1,-3],[0,-4],[-1,-7],[-2,-4],[-3,-4],[-3,-3],[-3,-1],[-3,-1],[-1,-1],[-1,-5],[-2,-5],[-4,-6],[0,-2],[2,-7],[1,-8],[-1,-8],[-1,-8],[-2,-5],[-3,-2],[-2,1],[-2,7]],[[5316,8584],[0,2],[-1,2],[-6,2],[-1,0],[-3,2],[-1,0],[-4,1],[-2,6],[-3,6],[0,2],[0,10],[-1,4],[0,5],[-2,-4],[1,-6],[-2,-3],[-3,-1],[1,-4],[1,0],[0,-4],[-1,-6],[-5,-12],[-1,-2],[-1,-1],[-2,1],[-4,-4],[-3,0],[-1,4],[-5,5],[-2,0],[2,-3],[2,-3],[-1,-3],[-1,-1],[-2,-1],[-7,-4],[2,-3],[-2,-3],[-2,-1],[-1,-1],[-1,-3],[-7,-6],[-11,-15],[-6,-5],[-4,-4],[-3,0],[-5,-4],[-11,-3],[-8,1],[-5,-1],[-3,3],[0,1],[0,1],[0,2],[-3,0],[0,-1],[-1,-3],[-1,-1],[-3,2],[-1,2],[1,3],[2,2],[0,1],[-1,2],[-1,0],[-3,-1],[-3,1],[-9,6],[-2,3],[-8,6],[-3,5],[-2,6],[0,6],[1,9],[1,2],[7,-3],[7,-5],[1,0],[2,4],[4,3],[-1,1],[-6,-4],[-2,2],[-4,5],[0,2],[2,2],[0,3],[-1,3],[1,3],[3,4],[4,4],[3,4],[3,3],[-1,0],[-3,-1],[-3,-3],[-4,-4],[-5,-4],[-4,-1],[-1,-1],[-3,-1],[-3,-5],[-3,-2],[-5,-1],[-1,4],[2,13],[1,7],[2,4],[3,1],[2,3],[1,0],[1,-1],[6,-2],[2,4],[4,1],[6,4],[0,1],[-4,-1],[-3,0],[-3,-1],[-2,1],[-1,3],[1,3],[6,7],[2,3],[1,2],[0,2],[1,4],[6,7],[5,3],[1,-3],[-1,-8],[0,-3],[4,12],[1,3],[2,2],[5,1],[1,2],[-5,0],[-13,-5],[-6,-4],[-1,-4],[-4,-4],[-2,-4],[0,-4],[-2,-3],[-3,-1],[-4,-6],[-2,-4],[-4,-4],[-2,-3],[-1,-1],[-1,-3],[-2,0],[-1,2],[0,3],[1,6],[2,4],[0,4],[-1,4],[1,3],[2,0],[3,-1],[3,0],[6,3],[-1,2],[-3,0],[-4,0],[-4,3],[-3,5],[-1,8],[1,3],[11,8],[2,3],[-1,1],[-4,-5],[-6,-2],[-3,3],[-2,4],[-1,9],[0,5],[0,6],[2,1],[3,-1],[2,0],[6,1],[14,3],[8,-2],[4,0],[5,3],[5,1],[3,-3],[2,-2],[0,-4],[2,-2],[1,0],[-1,3],[0,5],[14,5],[2,1],[-6,1],[-1,5],[2,6],[0,1],[-3,-3],[-1,-5],[0,-4],[0,-2],[-3,-1],[-7,0],[-4,1],[-4,1],[-1,1],[1,3],[-1,1],[-2,-3],[-1,-5],[-3,-1],[-9,2],[-12,-1],[-5,-3],[-4,1],[-6,4],[-2,4],[-1,7],[0,3],[5,2],[3,0],[2,1],[-2,1],[-3,3],[-2,4],[-3,1],[-2,4],[0,6],[0,4],[2,1],[4,-1],[9,1],[9,-4],[7,-2],[12,1],[7,3],[-1,1],[-8,-2],[-7,0],[-13,4],[-5,2],[-6,-1],[-3,1],[-2,4],[1,8],[3,2],[2,-2],[1,0],[2,3],[2,2],[1,4],[5,4],[2,0],[4,2],[2,-1],[1,-1],[1,-2],[4,0],[10,3],[1,1],[2,3],[-6,-1],[-6,-2],[-3,-1],[-1,3],[2,2],[2,2],[1,4],[2,1],[2,0],[5,1],[4,1],[6,-1],[9,-1],[6,-4],[2,0],[2,1],[1,2],[-4,1],[-1,2],[1,2],[7,2],[8,1],[-1,2],[-18,-3],[-4,2],[-4,0],[-2,-1],[-7,-2],[-1,1],[1,4],[4,7],[0,1],[2,2],[11,4],[5,4],[2,1],[2,-1],[4,1],[6,-1],[4,-6],[2,-1],[9,-7],[0,2],[-8,9],[-3,2],[-2,5],[1,4],[2,3],[9,2],[1,1],[1,3],[-2,2],[-3,0],[-3,1],[0,3],[1,2],[5,4],[2,1],[5,2],[8,-3],[1,-2],[-2,-4],[0,-2],[2,0],[4,6],[6,1],[2,2],[3,0],[4,-5],[1,-2],[1,-1],[2,-5],[1,0],[1,2],[3,2],[5,1],[7,-2],[3,1],[1,0],[-1,4],[-1,2],[1,3],[2,2],[5,3],[4,1],[3,2],[4,3],[0,2],[-1,2],[-3,0],[-1,1],[3,3],[5,3],[-1,2],[-3,1],[-3,-1],[-4,-3],[-4,-3],[1,-2],[2,-3],[-3,-4],[-16,-12],[-8,-3],[-4,1],[-1,3],[-1,2],[-2,5],[-3,0],[-2,-1],[-1,1],[2,5],[2,4],[4,3],[3,4],[2,6],[6,5],[9,14],[7,5],[3,4],[5,2],[3,4],[3,1],[6,3],[3,4],[-2,0],[-5,-2],[-3,-1],[0,4],[2,4],[4,4],[18,12],[2,-2],[2,-3],[6,0],[6,7],[5,7],[-2,-1],[-3,-3],[-6,-4],[-3,-1],[-1,1],[-1,3],[-2,0],[-2,0],[-1,2],[-1,5],[3,7],[1,4],[2,4],[8,10],[2,6],[3,3],[5,-1],[1,1],[-1,3],[-5,3],[0,2],[16,5],[8,0],[3,2],[4,2],[3,2],[-1,2],[-8,-3],[-6,-1],[-2,0],[-2,-1],[-6,0],[-2,11],[1,6],[3,0],[0,6],[3,4],[4,1],[2,1],[3,3],[4,-1],[5,1],[-1,1],[-6,2],[-1,4],[2,1],[2,2],[2,0],[4,6],[2,3],[3,-1],[4,3],[3,-1],[4,2],[5,1],[18,1],[0,2],[-4,1],[-13,0],[-6,0],[-3,0],[-1,1],[0,1],[2,2],[1,3],[5,7],[6,4],[4,-1],[5,-4],[4,-1],[1,-1],[2,-6],[2,0],[-1,5],[3,5],[-1,1],[-4,-1],[-4,1],[-3,4],[-1,3],[2,3],[2,1],[-1,2],[-8,-5],[-5,-1],[-2,1],[1,4],[0,4],[6,8],[3,1],[4,-1],[3,-2],[3,0],[3,2],[0,2],[-7,1],[-2,2],[1,1],[5,2],[4,4],[6,1],[4,3],[1,-1],[1,-1],[1,-10],[4,-8],[2,0],[-2,7],[1,2],[2,1],[1,2],[-2,0],[-2,3],[-2,8],[1,2],[5,4],[6,1],[7,-3],[2,0],[4,1],[7,2],[4,1],[2,0],[1,1],[-2,1],[-1,1],[-1,0],[-7,-1],[-17,0],[-2,2],[0,2],[2,4],[2,2],[6,3],[7,0],[8,7],[2,4],[2,7],[4,6],[11,3],[1,2],[-1,2],[0,6],[3,6],[2,2],[1,0],[2,-2],[3,-4],[4,-2],[6,-1],[2,1],[-5,3],[-3,3],[0,3],[1,2],[3,0],[3,0],[3,2],[0,2],[1,2],[0,2],[5,5],[13,3],[1,-1],[0,-10],[-2,-6],[0,-4],[3,4],[3,13],[3,6],[3,3],[2,1],[2,1],[3,2],[1,-2],[1,-3],[-2,-11],[0,-3],[-1,-5],[-7,-10],[1,-2],[1,1],[2,1],[9,10],[7,-1],[0,1],[-3,3],[-2,3],[-1,3],[0,9],[2,4],[6,-1],[4,1],[2,-2],[3,0],[3,7],[5,0],[4,-4],[5,-3],[5,-4],[1,1],[-2,10],[-3,3],[-5,2],[-6,5],[-2,2],[1,1],[5,2],[6,-2],[6,4],[2,-1],[5,1],[2,-2],[2,1],[1,3],[8,2],[4,-2],[3,-2],[1,-4],[2,-7],[3,-5],[2,-2],[3,0],[1,2],[-2,2],[-1,3],[1,6],[2,2],[8,9],[6,4],[4,1],[7,10],[2,2],[2,0],[-1,3],[-3,1],[-1,3],[5,4],[6,6],[3,1],[2,-2],[6,-3],[4,-3],[2,-2],[2,1],[1,2],[2,1],[4,0],[2,-2],[2,0],[1,-1],[1,-2],[-4,-3],[-5,-6],[-6,-6],[-1,-4],[-2,-10],[-4,-6],[-1,-4],[2,-2],[5,2],[6,5],[1,6],[14,17],[7,9],[8,7],[4,2],[2,-5],[-2,-7],[-3,-4],[3,-2],[-1,-5],[-1,-2],[0,-3],[0,-3],[2,1],[9,5],[2,6],[3,4],[1,4],[3,3],[7,0],[0,1],[-8,5],[-1,2],[3,3],[7,6],[4,-1],[2,-1],[9,-1],[7,-4],[0,-6],[-2,-3],[-1,-1],[-9,-5],[-2,-2],[3,-1],[6,2],[2,-2],[-2,-5],[0,-8],[-1,-5],[0,-4],[1,-2],[2,9],[1,2],[3,4],[2,6],[3,8],[4,5],[2,1],[8,0],[3,-2],[3,-3],[2,-2],[7,-2],[2,-2],[0,-1],[2,0],[5,3],[3,0],[4,-4],[-1,-4],[1,-1],[5,0],[5,-1],[9,-7],[1,-4],[0,-4],[-13,-4],[-6,-4],[-9,-2],[-32,3],[1,-3],[22,-7],[1,-2],[-1,-4],[0,-3],[1,-2],[1,-2],[3,-1],[5,1],[3,-2],[2,2],[1,6],[1,1],[3,-2],[2,-6],[1,0],[1,4],[3,0],[4,0],[4,-1]],[[5710,9281],[8,-2],[2,0],[4,-4],[2,1],[-1,-3],[-3,-1],[-6,-1],[-1,0],[-5,0],[-3,3],[-4,1],[0,1],[3,3],[4,2]],[[4751,9264],[-3,0],[-1,1],[4,3],[12,7],[5,6],[9,3],[1,-4],[-1,-4],[-8,-4],[-9,-2],[-9,-6]],[[5533,9469],[-3,-3],[-5,4],[-3,4],[1,2],[9,0],[2,-2],[1,-2],[-2,-3]],[[5600,9711],[3,-2],[9,1],[4,-10],[3,-10],[4,-1],[8,1],[7,1],[4,-1],[6,-3],[3,-2],[-3,-2],[-5,-1],[-1,-6],[6,-2],[9,-5],[6,0],[10,2],[9,-4],[9,-5],[-21,-5],[-2,-2],[-3,-4],[-3,-3],[-3,-2],[-7,-4],[-3,-1],[-8,0],[-3,-1],[-2,-3],[-3,-2],[-7,-1],[-4,3],[2,1],[0,2],[-1,4],[6,4],[2,2],[-1,1],[-2,0],[-5,1],[-1,0],[-4,-3],[-6,-1],[-5,-1],[-23,-3],[-3,1],[-2,6],[9,4],[2,5],[2,3],[3,3],[5,6],[1,0],[-12,5],[-5,3],[-6,6],[-1,5],[-7,4],[1,6],[-6,-1],[-4,4],[4,2],[19,3],[11,2],[5,0]],[[5746,9714],[-4,0],[-8,4],[-1,4],[1,1],[4,0],[6,-5],[6,-1],[-4,-3]],[[5312,9712],[0,-4],[5,0],[5,-4],[6,-2],[2,-2],[1,-2],[3,-4],[2,-4],[-4,-1],[-6,6],[-5,4],[-6,3],[-4,0],[-3,1],[-7,11],[-2,2],[-4,4],[-2,5],[0,3],[6,0],[5,-3],[4,-5],[1,-2],[-2,-2],[2,-3],[3,-1]],[[5806,9729],[9,0],[8,1],[1,-1],[-10,-3],[-12,1],[-11,1],[-13,-4],[-4,2],[7,3],[7,1],[1,2],[2,0],[10,0],[5,-3]],[[5466,9786],[1,0],[2,1],[1,1],[1,1],[7,-1],[10,-3],[3,-2],[4,-3],[3,-5],[-2,-4],[-4,-4],[-1,-2],[1,-3],[0,-3],[-2,-3],[6,3],[11,10],[2,0],[1,0],[6,-2],[4,-5],[1,-1],[1,-2],[1,-3],[-1,-3],[0,-1],[-3,-2],[-1,-1],[3,0],[3,-1],[3,-4],[3,-1],[11,1],[7,-1],[4,-6],[6,1],[0,3],[2,1],[8,0],[4,-2],[4,-3],[-7,-4],[6,-4],[10,-3],[6,-4],[2,-1],[1,-2],[-4,-2],[-5,-2],[-10,0],[-9,-1],[-17,-2],[-3,0],[-1,-1],[-1,-2],[-6,-5],[-7,-6],[-2,-3],[-2,-5],[-1,-3],[1,-3],[0,-3],[-5,-2],[-3,0],[-4,0],[-3,-1],[-1,-2],[1,-3],[-1,-8],[-1,-7],[-2,-6],[-2,-3],[-3,-1],[-8,-1],[-6,-5],[-5,-10],[-3,-4],[-5,-6],[1,-3],[2,-2],[-3,-4],[-5,-5],[0,-2],[2,-3],[0,-4],[-3,-3],[-7,-1],[-6,1],[-3,2],[-3,4],[-4,2],[-3,1],[-13,7],[-11,12],[-11,4],[-7,2],[-3,2],[-4,3],[-3,3],[-2,4],[-2,3],[0,3],[1,2],[1,1],[9,1],[3,0],[3,-2],[3,-1],[6,10],[36,5],[11,1],[12,0],[-2,2],[-2,4],[-1,0],[-9,-1],[-13,-2],[-7,0],[-7,1],[-6,-1],[-7,-3],[-7,-1],[-7,-1],[-14,0],[-4,2],[-4,3],[-2,2],[-1,2],[-1,6],[2,2],[1,1],[1,0],[4,0],[3,-1],[7,-3],[-2,4],[21,4],[10,4],[5,1],[5,0],[-2,2],[0,2],[4,1],[2,1],[8,1],[17,0],[7,1],[4,3],[-5,-1],[-5,-1],[-2,1],[-5,2],[-3,3],[7,7],[3,3],[-7,-1],[-3,-1],[-8,-6],[-6,-2],[-7,-1],[-7,0],[-2,1],[-2,3],[-1,2],[0,2],[3,3],[1,3],[0,3],[-2,0],[-3,-2],[-2,-4],[-3,-2],[-4,0],[-1,2],[-2,2],[-1,1],[-2,0],[-3,-1],[-3,-2],[1,-2],[1,-3],[-2,-2],[-1,-3],[4,-2],[2,-3],[-4,-1],[-4,-2],[-3,-3],[-4,-2],[-5,0],[-7,-1],[-14,-1],[-7,4],[-1,2],[-1,1],[-5,2],[-6,5],[-5,7],[-3,0],[-5,2],[-3,2],[-2,3],[-1,3],[0,2],[3,1],[-7,3],[-7,4],[3,2],[2,0],[20,-4],[2,0],[2,2],[-1,1],[-3,1],[-5,0],[-1,0],[-2,3],[-1,3],[-1,2],[0,2],[3,3],[2,3],[-3,2],[-8,0],[-3,-1],[1,-4],[-2,-3],[-6,-3],[-3,2],[-3,5],[-4,5],[-1,2],[-1,4],[-2,3],[-2,3],[-1,2],[1,2],[2,3],[-2,3],[-2,2],[0,2],[2,2],[2,0],[1,0],[5,-2],[3,-3],[1,1],[2,3],[3,1],[10,1],[11,-4],[3,-2],[2,0],[-1,2],[-1,3],[2,1],[9,-2],[4,0],[10,3],[16,2],[6,-3],[0,-1],[0,-2],[0,-1],[-4,-2],[-20,-1],[-14,-7],[19,1],[3,-1],[1,-5],[2,-1],[4,-1],[3,-1],[4,-3],[3,-2],[2,0],[1,2],[-1,3],[0,3],[0,3],[0,3],[4,2],[6,6],[6,4],[6,-2],[7,-5],[5,-8],[5,-7],[6,-10],[3,-4],[3,-1],[12,-10],[1,0],[-2,8],[-6,13],[-5,10],[-1,4],[0,5],[0,2],[1,1],[3,6],[4,3],[-2,4],[2,3],[4,3],[4,0],[3,-2],[8,-7]],[[5903,9799],[-26,-3],[-3,2],[43,6],[2,1],[8,1],[7,-2],[-2,-1],[-29,-4]],[[5520,9809],[-6,-3],[-10,2],[1,3],[3,1],[6,0],[6,-3]],[[5580,9806],[3,-1],[15,1],[3,-2],[1,-3],[2,-1],[4,-1],[8,-4],[3,0],[2,2],[2,6],[0,6],[-1,4],[1,2],[3,1],[3,-1],[4,2],[2,2],[4,0],[6,-2],[2,-1],[-2,-2],[0,-4],[-3,-8],[6,0],[9,2],[3,2],[5,3],[5,0],[3,0],[1,2],[0,1],[3,0],[4,-3],[2,-1],[4,1],[1,0],[3,-1],[16,-3],[5,-1],[3,-1],[2,-1],[17,0],[12,-1],[4,-2],[4,-4],[1,-9],[-3,-2],[-24,-11],[-6,-3],[-3,-4],[-5,-7],[-2,-2],[-11,-3],[-3,0],[-8,1],[-3,0],[-10,-4],[-4,-2],[-3,-3],[-5,-1],[-6,1],[-23,1],[-4,2],[-2,4],[5,5],[-27,-2],[-29,1],[-2,1],[-1,2],[-10,1],[-7,1],[-7,3],[-6,3],[2,2],[2,1],[5,0],[5,-1],[9,1],[2,3],[3,1],[3,2],[-9,2],[-10,0],[-6,-2],[-7,-1],[-7,0],[-12,0],[-6,2],[-9,4],[-3,2],[-1,1],[0,3],[9,2],[4,1],[3,3],[-14,1],[-6,2],[-6,3],[5,2],[19,1],[5,-1],[5,-2],[6,-2],[5,3],[-5,1],[-4,5],[-1,2],[0,2],[3,0],[1,-1],[7,-4],[5,-1],[2,4],[0,1],[-1,2],[-3,3],[-2,3],[4,1],[3,0],[7,-3],[7,-1],[3,-2],[6,-4],[6,-3]],[[9637,5154],[-1,-2],[-1,2],[1,1],[0,1],[1,-1],[0,-1]],[[9698,2160],[2,-3],[-3,-1],[-1,1],[-1,1],[-1,2],[2,0],[1,1],[1,-1]],[[9616,2260],[1,-5],[-2,0],[-3,1],[-1,3],[-2,-2],[-2,0],[1,3],[4,5],[1,6],[0,2],[3,0],[1,0],[1,-1],[-1,-1],[-1,-2],[0,-3],[0,-2],[-1,-1],[1,-2],[0,-1]],[[9670,2485],[0,-3],[-3,1],[0,-2],[2,-2],[1,-2],[2,1],[1,-3],[-1,-2],[-1,-2],[-5,-1],[-3,-4],[-3,1],[-3,-4],[-4,-2],[-1,1],[1,3],[2,3],[0,4],[1,2],[3,2],[0,3],[1,3],[-1,6],[1,6],[4,0],[6,-9]],[[9631,2554],[0,-3],[-1,-1],[-1,0],[-1,0],[-1,1],[-1,0],[-1,1],[1,3],[3,1],[1,-1],[1,-1]],[[9637,2582],[2,-7],[-3,1],[-1,2],[2,3],[0,1]],[[106,2631],[-1,-1],[0,4],[0,2],[2,1],[1,-3],[-2,-3]],[[106,2664],[-1,-1],[-2,0],[-2,-6],[0,5],[-1,1],[-3,0],[0,-1],[1,-1],[1,-1],[-2,-2],[2,-6],[1,0],[2,-4],[0,-1],[-3,-2],[-2,-2],[-2,0],[-1,0],[0,4],[0,2],[1,3],[2,3],[-1,3],[-3,2],[-4,-1],[-1,1],[2,3],[3,0],[2,3],[11,-2]],[[9830,2830],[-4,-3],[0,2],[1,5],[2,3],[1,0],[1,2],[0,-4],[-1,-5]],[[9808,2806],[3,0],[3,4],[3,4],[3,2],[5,7],[1,1],[4,1],[1,2],[1,0],[-1,-4],[-2,-1],[0,-2],[1,-2],[-2,-3],[1,-4],[-2,-4],[2,1],[2,3],[-1,2],[1,4],[2,1],[-1,3],[0,2],[3,-1],[1,0],[1,1],[1,0],[1,-2],[2,0],[-1,-3],[-2,-3],[0,-2],[-3,-3],[-2,-2],[3,0],[4,4],[3,4],[0,-5],[-2,-4],[-2,-3],[-2,-1],[-2,-2],[-1,-3],[0,-3],[1,-2],[2,-3],[-2,-6],[2,0],[1,-1],[2,-3],[-1,-5],[-1,-2],[-4,-9],[-2,-4],[-3,-3],[0,-5],[-1,-3],[-7,-12],[-1,-2],[-6,-19],[-3,-8],[-2,-2],[-2,-2],[-6,-4],[-2,-4],[-2,-4],[-3,-1],[0,-1],[2,-1],[1,-2],[-1,-3],[-2,-2],[-2,0],[-1,-2],[5,1],[1,-1],[1,-3],[0,-2],[1,-4],[4,-2],[4,-1],[0,-1],[1,-6],[-1,-3],[-1,-1],[-1,-1],[-3,0],[-2,1],[-2,3],[-6,-1],[-1,-1],[-1,1],[3,4],[-2,1],[-1,1],[-1,-1],[-1,-2],[0,-3],[-1,-1],[-2,-1],[-2,3],[-2,3],[-3,4],[0,-3],[3,-5],[1,-4],[-3,-2],[-3,-3],[-2,-1],[-3,-2],[-2,-3],[-2,-1],[-4,0],[-2,-1],[0,-5],[-2,-2],[-3,-1],[1,-1],[1,-1],[-3,-13],[0,-5],[0,-9],[-2,-8],[-4,0],[1,-2],[3,-2],[-1,-3],[-3,-7],[-2,-4],[-1,-9],[-2,-8],[-3,-10],[0,-1],[1,-3],[1,-2],[0,-3],[0,-1],[-2,-1],[-1,-1],[-7,-2],[-2,-3],[-2,-5],[-3,-5],[-7,-10],[-4,-8],[-1,-3],[-1,-2],[-10,-3],[-7,-1],[-3,1],[-4,2],[-2,1],[-4,-2],[-1,-1],[-3,1],[-3,-1],[0,1],[-1,3],[0,3],[0,3],[-2,1],[-1,2],[-1,1],[-3,1],[-5,-1],[-2,0],[-3,8],[-1,2],[-4,3],[-1,-1],[-3,-4],[-1,-1],[-7,0],[-8,1],[-3,2],[0,4],[6,10],[-2,-2],[-4,-4],[-2,1],[2,4],[1,2],[-1,3],[-3,-4],[-3,-1],[-1,4],[1,4],[0,1],[9,2],[4,2],[1,2],[-5,1],[-1,3],[1,2],[5,4],[-4,-1],[-3,1],[0,4],[1,3],[4,0],[-2,3],[0,3],[1,0],[4,-4],[3,-2],[-1,3],[0,3],[1,0],[2,1],[0,1],[-3,1],[-2,2],[0,3],[0,3],[2,4],[2,-3],[2,1],[-1,2],[-1,3],[0,2],[6,8],[2,-8],[0,3],[0,2],[0,2],[0,2],[0,2],[3,2],[3,6],[3,2],[2,-2],[1,-2],[0,2],[-1,2],[0,6],[4,8],[5,8],[5,8],[2,3],[6,3],[3,-1],[1,0],[5,6],[2,1],[2,-2],[1,-1],[-1,6],[1,2],[4,5],[6,4],[4,2],[3,3],[2,0],[-1,2],[1,3],[1,-1],[1,1],[-2,2],[5,4],[2,5],[1,1],[2,1],[1,4],[2,1],[1,-1],[1,-1],[0,2],[-2,2],[2,2],[2,2],[2,-1],[2,-2],[-2,3],[0,2],[2,2],[2,0],[2,-4],[-1,3],[1,3],[3,5],[3,7],[1,-2],[1,-3],[-1,-4],[1,1],[0,3],[0,7],[4,11],[1,1],[1,1],[2,0],[-1,2],[-1,2],[1,5],[1,7],[1,6],[2,6],[2,10],[1,3],[4,0],[1,2],[3,4],[3,6],[2,6],[2,14],[2,14],[3,11],[6,8],[5,6],[2,1],[3,1],[3,-2],[-6,-1],[0,-4],[-1,-4],[1,-3],[1,-3],[3,-2],[3,-2],[2,-6],[0,-7],[0,-6],[2,-6]],[[9875,3094],[0,-3],[-2,1],[-1,3],[-2,2],[0,1],[-1,4],[2,3],[0,1],[1,0],[0,-2],[2,-4],[1,-6]],[[9812,3172],[0,-3],[2,2],[1,3],[2,3],[0,-5],[1,-1],[6,-3],[1,-3],[1,-1],[1,1],[1,1],[2,-1],[5,-5],[1,-2],[-1,-3],[1,-2],[0,-2],[2,-1],[2,3],[1,1],[2,-5],[0,-2],[1,-3],[1,-2],[2,-8],[0,-2],[-1,-3],[2,-6],[-1,-1],[-4,1],[0,-1],[3,-5],[2,-7],[1,-4],[6,-14],[-1,-4],[0,-3],[-1,-3],[2,-7],[-1,-2],[-1,-7],[-1,-2],[0,-2],[3,-1],[1,-1],[1,-2],[1,2],[1,1],[2,-3],[6,-4],[1,-1],[1,-3],[1,-6],[1,-3],[2,-1],[2,1],[1,2],[-1,7],[-1,10],[0,4],[0,3],[0,4],[-1,3],[-1,2],[-1,2],[0,3],[2,2],[1,-3],[1,-3],[4,-10],[3,1],[0,-4],[2,-4],[0,-5],[2,-14],[2,-14],[3,-5],[0,-3],[-2,1],[0,-1],[0,-1],[2,-2],[2,-2],[2,0],[1,-1],[9,-8],[4,-4],[11,-5],[3,-1],[2,1],[3,2],[3,3],[3,5],[2,6],[2,3],[3,2],[1,2],[2,2],[7,-1],[2,-3],[4,-2],[1,-2],[0,-4],[-2,-6],[-2,-6],[-1,-14],[-1,-14],[-1,-6],[-3,-4],[-2,-4],[-3,-2],[-1,-7],[-1,-10],[0,-2],[1,-2],[1,-3],[-2,-5],[-1,0],[-1,5],[-1,2],[-4,2],[-4,0],[-3,0],[-3,-2],[-5,-4],[-1,-2],[-1,-3],[-3,-6],[0,-7],[0,-4],[1,-2],[4,-4],[-4,-14],[-4,-14],[-2,-4],[-2,-4],[-2,-9],[-4,-7],[-2,-6],[-2,-5],[-2,-7],[-4,-8],[-1,-6],[-3,-5],[-4,-6],[-4,-5],[-6,-8],[-2,-2],[-2,-2],[-3,2],[0,2],[-1,5],[0,2],[-3,2],[-4,-3],[-1,1],[0,1],[0,7],[0,2],[-1,1],[-1,0],[0,-2],[1,-1],[-3,-2],[-2,-1],[-1,1],[0,2],[1,2],[0,2],[5,9],[5,12],[4,13],[1,7],[1,12],[-1,5],[-2,5],[-4,10],[-5,5],[-4,1],[-3,2],[-3,4],[-3,5],[-6,5],[-5,3],[-4,5],[-1,3],[0,3],[0,3],[0,3],[1,3],[1,1],[6,7],[7,3],[1,0],[1,1],[2,2],[3,5],[1,3],[1,10],[0,10],[2,12],[3,7],[1,5],[-1,7],[1,3],[1,1],[1,1],[-2,7],[-3,11],[0,3],[0,3],[1,3],[-2,1],[-1,3],[-2,10],[0,2],[2,-1],[2,-8],[0,4],[2,2],[1,2],[2,0],[-4,8],[-1,0],[-2,-2],[-2,-1],[-2,1],[-1,2],[-1,3],[-1,7],[-1,2],[-5,14],[1,0],[5,-6],[0,2],[1,3],[0,3],[-1,3],[-2,2],[0,3],[1,2],[0,2],[-2,4],[-1,1],[-1,-2],[1,-3],[-1,0],[-6,7],[-1,6],[-2,7],[0,-3],[0,-4],[2,-7],[4,-8],[1,-3],[-1,-2],[-1,-1],[-1,2],[-2,7],[-1,3],[-15,37],[2,4],[3,4],[1,2],[0,2],[-1,1],[-1,-1],[-2,-2],[-1,-2],[-1,-5],[-1,-1],[-2,3],[0,2],[0,3],[-1,1],[-1,1],[-2,5],[-1,2],[2,5],[0,6],[-2,6],[-3,6],[-4,10],[-5,10],[5,2],[5,0],[-2,-6],[1,-4],[1,-3],[3,-9],[1,-3],[1,-2],[1,-2]],[[245,4645],[-1,1],[1,0],[0,-1]],[[209,4690],[0,-1],[0,1],[-1,1],[0,1],[1,-1],[0,-1]],[[6631,6348],[-2,-1],[-1,1],[0,7],[4,9],[3,11],[2,-10],[-3,-5],[-2,-9],[-1,-3]],[[6566,6623],[3,-16],[4,-14],[3,-8],[4,-10],[6,-10],[3,-3],[11,-7],[6,-3],[8,-2],[5,-6],[2,0],[3,2],[3,0],[5,-8],[2,-7],[2,-3],[2,-6],[1,-6],[5,-9],[3,-10],[3,-8],[3,-5],[5,-2],[3,-2],[0,-5],[0,-6],[-1,-5],[-3,-10],[-1,-6],[-3,-10],[-4,-16],[-2,-4],[-7,-8],[-5,-10],[-5,-18],[-5,-17],[-1,-6],[-4,-1],[-2,1],[-2,1],[1,5],[0,5],[-2,0],[-2,-1],[-4,-13],[-2,-6],[-1,-7],[-1,-10],[-2,-8],[0,-8],[0,-4],[1,-10],[0,-10],[1,-6],[0,-8],[-2,-2],[-2,-1],[-6,-1],[-7,-2],[-7,-5],[-3,-4],[-5,-10],[-3,-24],[-4,-10],[-4,-2],[-7,-1],[-11,-3],[-4,-2],[-6,-15],[0,-5],[1,-3],[0,-4],[0,-4],[-3,-9],[-3,-7],[-8,-4],[-3,2],[-3,2],[-5,0],[-9,-2],[-3,-5],[-5,-3],[-4,-6],[-9,-2],[-6,-4]],[[6474,6143],[-2,7],[-1,8],[-2,7],[-2,8],[-1,5],[-2,2],[-1,6],[-1,6],[-2,5],[-1,6],[-1,6],[-1,6],[-2,5],[-1,6],[-1,6],[-1,6],[-1,5],[-2,6],[-1,6],[-1,6],[-1,5],[-2,6],[-1,6]],[[6443,6278],[4,3],[5,3],[5,3],[4,4],[5,3],[5,3],[5,3],[5,4],[4,3],[5,3],[5,4],[5,3],[4,3],[5,4],[5,3],[5,3],[5,3],[3,3],[1,7],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[-2,6],[-2,7],[-3,8],[-2,8],[-2,5],[-2,7]],[[6557,6685],[2,8],[1,2],[1,-1],[2,1],[2,4],[0,3],[1,0],[1,-2],[0,-7],[-1,-5],[-1,-18],[-1,-3],[-1,-2],[0,-4]],[[6893,6558],[-1,-4],[-1,-2],[-1,4],[-1,1],[-1,-1],[-1,0],[-3,5],[-1,-5],[-4,-1],[-1,4],[0,3],[-2,-3],[-2,4],[0,4],[-1,1],[-1,2],[-1,1],[-2,5],[0,5],[-1,6],[-3,23],[-2,2],[-11,4],[0,4],[0,10],[0,7],[-4,9],[-1,6],[-2,5],[-3,1],[-3,0],[-2,-2],[-1,-4],[7,1],[1,-1],[2,-3],[-2,0],[-2,2],[-3,0],[-10,-3],[-5,-4],[-8,1],[-9,-3],[-8,-1],[-4,-7],[-1,2],[-2,1],[-11,6],[0,2],[-2,2],[-2,-3],[-2,-1],[-6,3],[-4,-2],[-2,-3],[0,-5],[-6,1],[-3,1],[-4,-1],[-10,2],[-3,-1],[-3,-3],[-2,-2],[-2,-1],[-2,3],[-1,2],[-1,-1],[-2,-3],[-5,-2],[-5,1],[-4,2],[0,1]],[[2733,5606],[-2,0],[-3,2],[-2,5],[0,2],[0,1],[1,5],[2,2],[2,-6],[-1,-2],[0,-4],[3,-2],[0,-3]],[[2803,5659],[-1,-2],[0,2],[1,3],[0,-3]],[[2808,5660],[0,-2],[-2,5],[0,2],[0,5],[2,1],[1,0],[0,-1],[1,-5],[-1,-3],[-1,-2]],[[2715,5724],[0,-3],[-2,5],[1,1],[1,0],[0,-3]],[[2836,5600],[-1,2],[-7,16],[-5,21],[-2,9],[2,1],[1,-1],[1,2],[1,3],[-1,6],[3,5],[1,3],[1,-1],[2,-5],[2,-3],[4,-5],[2,-1],[-3,5],[-4,6],[-2,4],[-1,6],[-1,-2],[-1,-2],[-1,-2],[-1,2],[0,2],[-3,0],[0,2],[-1,1],[0,-4],[1,-2],[0,-3],[-1,0],[-1,3],[-1,2],[-1,11],[-3,5],[-2,1],[-1,1],[-1,3],[-3,2],[-2,5],[-4,4],[-5,1],[-5,0],[-2,-3],[-1,-2],[-1,-1],[-3,-3],[-1,-5],[-1,-3],[-1,-5],[1,-2],[-10,-14],[-2,-2],[-5,-2],[-1,-1],[-1,-3],[0,-4],[0,-4],[1,-3],[1,-2],[3,-8],[5,-11],[1,-3],[1,-6],[-1,-3],[-2,-1],[-4,0],[-2,-3],[-1,-3],[-2,-3],[-6,-3],[-5,0],[-2,3],[0,9],[-3,16],[-1,11],[-1,-2],[-2,-1],[0,-2],[-1,-9],[0,-2],[-2,0],[-3,3],[-3,3],[-5,17],[-1,3],[0,4],[-4,1],[-3,3],[-4,0],[-1,-1],[-2,2],[-1,5],[-3,-3],[-5,1],[-4,2],[-3,-1],[-2,-3],[0,-9],[0,-1]],[[2706,5735],[2,-3],[4,-5],[0,-3],[0,-2],[1,-8],[1,-1],[2,2],[1,-2],[-1,-1],[-1,-2],[0,-6],[3,-3],[2,-3],[5,2],[2,-1],[1,1],[-1,5],[-2,4],[0,1],[1,-1],[1,-3],[3,-3],[5,-11],[5,-2],[4,0],[4,1],[6,5],[5,7],[3,4],[12,7],[4,8],[2,1],[2,1],[3,6],[2,4],[2,3],[6,-2],[4,-2],[3,0],[3,-1],[1,-4],[1,-1],[7,0],[5,-1],[12,-10],[7,-10],[3,-10],[9,-13]],[[1436,3779],[0,-1],[-1,0],[0,2],[0,2],[0,1],[1,-1],[0,-2],[0,-1]],[[3044,4127],[-2,4],[-9,13],[-4,7],[-3,3],[-8,11],[-1,4],[-1,11],[-1,4],[-2,4],[-7,5],[-3,3],[-2,5],[-4,3],[-5,8],[-2,6],[-3,3],[-9,6],[-5,5],[-8,8],[-4,5],[-9,6],[-3,2],[-9,14],[-6,5],[-5,8],[-16,16],[-2,5],[-2,9],[-4,4],[-3,12],[-6,6],[-6,9],[-2,8],[-3,10],[-1,5],[-3,6],[-1,10],[-2,5],[2,3],[1,1],[2,16],[-1,9],[-5,15],[-2,7],[-2,9],[-2,6],[-3,11],[-3,11],[-4,7],[-1,3],[-1,3],[-2,3],[-1,8],[-1,15],[-3,8],[-9,14],[0,5],[-1,10],[-2,11],[-10,33],[-2,10],[-3,16],[-2,9],[-2,16],[-4,12],[-2,11],[-3,13],[0,7],[-5,13],[-2,11],[-4,9],[-4,7],[-2,5],[-6,24],[-1,8],[-4,13],[-4,9],[-2,8],[-4,7],[-19,21],[-7,9],[-2,4],[-1,7],[0,3],[2,4],[3,-3],[2,1],[1,5],[0,7],[-2,9],[-6,18],[1,4],[1,4],[-3,9],[-2,7],[-2,5],[2,20],[1,5],[10,20],[2,9],[4,5],[5,8],[4,7]],[[8339,5487],[0,-4],[-1,-2],[-1,1],[-1,2],[-1,-2],[-2,-2],[-2,-4],[-2,-1],[-1,1],[0,3],[4,6],[3,2],[2,4],[1,0],[1,-3],[0,-1]],[[8365,5534],[1,-4],[2,1],[3,-1],[1,-3],[0,-1],[-4,-4],[-2,4],[-3,-3],[-2,2],[-3,-2],[-1,4],[0,3],[4,5],[4,-1]],[[8391,5554],[-3,-1],[-1,0],[-2,6],[0,3],[-2,3],[0,3],[3,0],[4,4],[6,-6],[1,-2],[-2,-1],[-1,-6],[-3,-3]],[[8493,5585],[0,-3],[-2,7],[-1,2],[1,7],[2,-3],[0,-10]],[[8414,5611],[0,-2],[0,-1],[-3,-3],[-1,0],[0,5],[1,2],[1,-2],[1,2],[1,-1]],[[8251,5638],[-1,-4],[-2,5],[1,7],[0,1],[2,2],[0,-11]],[[8259,5657],[-2,-1],[0,3],[0,4],[1,-1],[1,-1],[0,-4]],[[8466,5710],[-1,-3],[-3,3],[-1,2],[1,3],[1,1],[1,0],[2,-3],[0,-3]],[[8435,5716],[0,-6],[-2,-2],[-2,2],[-1,3],[0,2],[1,-1],[2,4],[1,0],[1,-2]],[[8498,5736],[0,-1],[-1,3],[1,7],[0,1],[1,-4],[-1,-6]],[[8499,5721],[3,-4],[3,1],[-1,-9],[1,-2],[3,-8],[0,-6],[-2,-6],[-1,-2],[-2,-4],[0,-2],[1,-2],[3,-1],[2,-4],[1,-9],[2,-7],[0,-3],[-1,-13],[0,-5],[2,-4],[1,-2],[1,-3],[1,-8],[0,-12],[-1,-5],[-1,-4],[-3,-9],[-4,-8],[-2,1],[-1,-3],[2,-6],[-1,-15],[-1,-10],[-1,5],[-1,6],[-1,14],[-1,6],[-1,6],[-1,5],[-2,5],[-2,12],[-1,0],[-2,-4],[-1,-2],[0,-4],[-1,-3],[-3,-5],[-2,-6],[-1,-7],[-1,-6],[1,-5],[2,-2],[2,-4],[1,-2],[2,-14],[0,-14],[-2,-6],[-4,-12],[-3,-4],[-2,2],[-1,7],[0,3],[1,7],[0,6],[-1,2],[-1,0],[-1,-1],[-3,-8],[-1,-2],[-1,0],[-2,0],[-8,7],[-6,7],[-5,7],[-4,10],[-1,7],[0,8],[-2,11],[0,4],[0,4],[2,7],[2,3],[1,3],[1,2],[1,4],[-1,4],[0,2],[-4,8],[-2,5],[-6,5],[-1,2],[-2,2],[-1,1],[-2,0],[-1,-1],[-1,-3],[0,-3],[0,-3],[-2,-15],[-3,4],[-3,3],[-1,3],[0,3],[-1,2],[0,2],[-2,-5],[-1,-4],[-2,0],[-3,-1],[0,2],[-1,10],[-2,3],[-3,-1],[-3,-5],[-1,-2],[0,-5],[-4,-12],[-2,-10],[-2,-10],[-1,-3],[-1,-2],[-2,1],[-2,2],[-2,6],[1,7],[2,5],[1,5],[2,17],[0,6],[1,3],[3,7],[2,5],[2,1],[5,3],[3,2],[3,0],[3,2],[3,3],[0,4],[0,4],[0,3],[1,2],[1,2],[2,2],[4,2],[1,1],[1,3],[2,5],[2,-1],[1,-2],[4,-2],[3,-4],[1,-6],[1,-4],[0,-11],[0,-2],[-3,-5],[1,-1],[4,5],[2,2],[4,2],[1,2],[1,2],[1,7],[2,7],[1,3],[1,2],[1,1],[5,-5],[3,2],[1,7],[0,11],[1,3],[2,3],[2,-1],[3,-4],[2,-1],[1,3],[1,6],[1,0],[4,-2],[3,1],[1,7],[0,8],[-3,23],[1,5],[2,0],[3,-6],[7,-8],[2,-5],[1,-6]],[[8501,5746],[-1,0],[-1,4],[0,6],[2,7],[2,-6],[0,-3],[0,-2],[1,-4],[-1,-2],[-2,0]],[[8479,5759],[0,-3],[-3,7],[-1,6],[1,-1],[2,-2],[1,-7]],[[8460,5748],[0,-3],[-2,1],[-1,-1],[-2,-5],[-1,-2],[-7,-1],[-5,1],[-2,3],[-1,5],[0,3],[1,4],[1,2],[4,5],[1,3],[2,5],[5,1],[0,-1],[1,-1],[1,0],[2,-3],[3,-3],[-1,-8],[1,-3],[0,-2]],[[8491,5755],[-1,-2],[-1,4],[-1,3],[-2,5],[-1,2],[1,4],[0,7],[1,3],[1,1],[1,3],[1,0],[0,-3],[-1,-8],[2,-10],[-1,-6],[1,-2],[0,-1]],[[8330,5788],[-3,-2],[-1,6],[2,5],[3,-2],[2,-2],[-1,-2],[-2,-3]],[[8452,5795],[0,-1],[1,6],[1,0],[0,-1],[0,-3],[-2,-1]],[[8406,5787],[-1,-1],[-2,-2],[-1,4],[1,7],[2,5],[1,1],[1,1],[1,0],[0,-2],[1,-3],[-2,-9],[-1,-1]],[[8419,5706],[-1,-1],[-2,1],[-2,2],[-2,13],[-2,3],[-3,2],[-2,2],[-1,2],[-5,12],[0,8],[1,4],[1,4],[2,1],[3,0],[2,0],[4,6],[0,2],[0,9],[0,7],[-1,6],[1,3],[1,2],[2,6],[0,4],[0,4],[0,3],[2,1],[5,5],[1,0],[7,-4],[1,-6],[1,-2],[-2,-7],[0,-5],[-3,-7],[-2,-7],[-1,-12],[-1,-4],[-2,-7],[-1,-4],[0,-9],[0,-3],[0,-3],[4,-14],[1,-3],[0,-2],[-1,-3],[-2,-6],[-1,-2],[-2,-1]],[[8426,5728],[-1,-1],[0,3],[0,5],[2,18],[0,5],[3,10],[2,9],[4,10],[0,5],[3,10],[3,13],[0,5],[0,2],[1,3],[0,3],[2,5],[0,-3],[0,-6],[0,-4],[0,-1],[0,-6],[-1,-9],[1,-10],[-1,-11],[-2,-5],[-2,-3],[-2,-2],[-3,-6],[-1,-6],[-1,-6],[-3,-19],[-4,-8]],[[8437,5834],[1,-8],[-2,0],[-1,6],[1,1],[1,1]],[[8258,5670],[-3,-4],[1,5],[0,5],[3,10],[2,3],[3,8],[2,3],[4,8],[4,8],[1,1],[1,0],[2,1],[2,4],[7,15],[5,11],[5,14],[3,4],[0,1],[5,13],[2,2],[2,1],[1,2],[1,2],[2,6],[0,6],[0,4],[-1,5],[1,8],[1,3],[4,15],[1,3],[1,-2],[0,-2],[0,-7],[0,-3],[0,-3],[-1,-5],[3,-14],[2,-9],[0,-3],[-3,-6],[-1,-1],[-4,-2],[-1,-1],[-2,-5],[-2,-5],[0,-3],[-1,-3],[-7,-4],[-3,-2],[-1,-2],[-1,-3],[0,-6],[-5,-19],[-2,-6],[-2,-4],[-2,-3],[-4,-2],[-2,-4],[-2,-7],[-2,-6],[-3,-4],[-3,-4],[-3,-3],[-3,-2],[-1,-3],[0,-3],[-2,-2],[-1,-1],[-3,-3]],[[8329,5848],[0,-3],[-1,-5],[0,-1],[-1,2],[-2,1],[0,3],[1,0],[2,2],[1,1]],[[8460,5837],[2,-2],[2,1],[2,5],[3,-2],[2,-7],[1,-2],[1,-5],[-1,-10],[0,-10],[0,-2],[2,-2],[1,-2],[1,-2],[1,-4],[0,-7],[2,-6],[0,-2],[-1,-3],[-2,0],[-1,-2],[0,-2],[-1,1],[-1,6],[-2,3],[1,-10],[0,-5],[0,-4],[-3,3],[-3,3],[-1,1],[1,7],[0,3],[-2,6],[2,14],[0,3],[-1,3],[-1,5],[-2,5],[-1,0],[-3,-3],[-2,1],[-1,13],[-1,13],[-1,3],[-1,3],[1,3],[1,-1],[2,-3],[2,-2],[1,-2],[1,-3]],[[8461,5846],[-4,-1],[-1,3],[-2,8],[2,1],[2,0],[1,-3],[2,-5],[0,-3]],[[8467,5852],[0,-3],[-1,0],[-1,2],[-1,4],[0,4],[2,-2],[0,-4],[1,-1]],[[8402,5853],[3,-3],[3,2],[3,0],[3,-4],[-1,-3],[0,-2],[6,6],[1,-1],[0,-5],[0,-5],[-1,-4],[-1,-5],[-2,-5],[-2,-3],[-2,-2],[-2,-2],[0,-3],[0,-4],[-1,-3],[-2,-1],[-4,-6],[-9,-4],[-3,-3],[-2,-4],[-1,-3],[-1,-1],[-1,2],[0,1],[2,9],[-1,3],[0,3],[0,7],[2,6],[0,7],[1,13],[1,18],[0,3],[-1,2],[-4,2],[-1,2],[1,4],[1,2],[2,0],[1,-2],[6,-5],[3,-4],[3,-5]],[[8334,5858],[-2,-2],[-1,1],[0,3],[0,2],[-2,10],[1,2],[1,-1],[1,-2],[2,-1],[0,-3],[0,-2],[1,-2],[-1,-5]],[[8335,5885],[2,-1],[1,1],[1,3],[1,-5],[2,-4],[-1,-3],[-2,-1],[-2,1],[-2,-1],[-2,0],[-2,4],[-1,6],[-1,1],[0,3],[0,2],[0,1],[1,1],[2,-2],[3,-5],[0,-1]],[[8406,5893],[-1,-2],[-3,6],[-2,3],[0,1],[1,2],[4,0],[2,-4],[0,-2],[-1,-4]],[[8478,5905],[2,-4],[0,-4],[0,-3],[1,-2],[2,-1],[2,-2],[1,-3],[-1,-3],[1,-5],[-2,-6],[0,-10],[1,-4],[0,-3],[0,-3],[0,-3],[3,-10],[0,-3],[0,-3],[-1,-2],[2,0],[2,-4],[1,-5],[0,-2],[-2,4],[-1,1],[-6,-1],[-3,2],[-2,0],[-2,7],[-2,1],[-2,3],[-2,8],[-1,5],[2,4],[0,4],[0,3],[-1,0],[-2,1],[-2,4],[0,3],[-2,2],[-2,5],[-3,2],[-1,2],[-2,4],[-2,5],[-1,9],[-1,10],[7,-3],[8,1],[9,2],[2,-3]],[[8436,5892],[5,-7],[4,-12],[0,-9],[0,-3],[-2,4],[-4,5],[-2,1],[-1,1],[0,3],[-1,3],[-1,1],[-1,1],[-2,6],[-2,1],[-2,-1],[-3,-9],[-4,-6],[0,2],[2,8],[1,13],[0,4],[-1,5],[0,6],[3,-3],[4,-2],[2,-3],[1,-3],[4,-6]],[[8397,5905],[-1,-1],[-1,0],[0,3],[1,2],[1,-4]],[[8391,5895],[-3,-14],[-1,5],[1,3],[-2,3],[0,2],[0,3],[2,3],[0,9],[3,3],[1,1],[0,-3],[0,-4],[-1,-11]],[[8437,5901],[0,-5],[-1,2],[-3,10],[-1,3],[1,3],[3,-4],[1,-9]],[[8424,5924],[2,-9],[-3,6],[-3,4],[-3,7],[-2,3],[-1,1],[1,3],[1,0],[1,0],[5,-12],[2,-3]],[[8352,5960],[1,0],[5,1],[2,0],[1,-4],[1,-1],[2,-1],[2,2],[2,-3],[2,-6],[3,-5],[2,-3],[0,-2],[-1,-4],[-1,-5],[1,-6],[1,-11],[0,-3],[-2,-5],[-1,-5],[0,-2],[-1,-1],[0,-4],[-1,1],[-1,-1],[-1,-1],[-1,-3],[-2,1],[-1,1],[-1,2],[0,3],[-1,1],[-3,5],[-1,3],[0,4],[-1,4],[-1,4],[-1,2],[-1,3],[0,2],[0,8],[-3,9],[0,2],[-3,3],[-1,3],[-1,2],[-1,5],[0,1],[-2,0],[-1,0],[0,4],[2,2],[2,1],[5,-2],[1,-1]],[[8386,5964],[1,0],[1,0],[3,-5],[0,-2],[0,-3],[-1,-6],[-1,-2],[-1,-2],[-3,5],[-2,3],[0,5],[1,8],[2,-1]],[[8340,5976],[0,-4],[-5,6],[0,2],[0,1],[1,1],[2,-2],[2,-4]],[[8453,5969],[0,-4],[-1,2],[-2,-1],[-2,-3],[-3,4],[0,4],[2,7],[0,11],[1,3],[1,2],[1,1],[2,-8],[1,-1],[2,-3],[0,-7],[0,-4],[-2,-3]],[[8393,5993],[0,-2],[-6,8],[0,2],[0,1],[0,1],[6,-10]],[[8389,6048],[0,-2],[-2,-4],[2,-8],[-1,-6],[-2,0],[0,1],[0,2],[0,2],[0,3],[-1,3],[-1,4],[-1,3],[1,4],[3,0],[2,-2]],[[8363,6256],[4,-3],[10,-11],[3,-2],[4,-2],[3,-1],[2,2],[1,3],[2,7],[2,0],[1,-2],[1,-3],[1,-5],[-1,-5],[-2,-4],[-1,-6],[-1,-17],[0,-6],[1,-5],[2,-8],[1,-2],[2,-3],[1,-2],[0,-4],[0,-4],[2,-1],[1,-2],[0,-4],[-1,-4],[-1,-9],[-6,-23],[0,-4],[-2,-10],[-5,-2],[-5,-4],[-3,-4],[-2,-4],[-1,-7],[1,-2],[0,-3],[0,-4],[-1,-2],[-2,-7],[-1,-5],[-1,-3],[-1,-3],[0,-3],[1,-3],[3,-12],[4,-12],[0,-2],[1,-1],[-2,-4],[0,-5],[0,-6],[3,-14],[1,-4],[1,-3],[1,-3],[2,-3],[4,-4],[2,-1],[2,0],[0,3],[2,1],[0,3],[-2,4],[0,2],[1,1],[1,1],[3,4],[3,4],[3,-1],[4,-1],[3,-2],[2,-4],[2,-6],[2,-7],[0,-3],[-1,-4],[0,-3],[2,-2],[3,0],[2,5],[0,6],[-1,2],[1,3],[1,2],[1,-2],[2,-4],[5,-4],[2,0],[1,0],[2,-3],[2,-2],[-2,-5],[-5,-1],[-2,-3],[2,-7],[2,-6],[2,-4],[2,-5],[0,-4],[-1,-5],[2,0],[2,-1],[4,-4],[1,0],[1,1],[-1,-14],[-2,-13],[-2,1],[-3,6],[1,6],[1,7],[-1,1],[-1,0],[-2,-2],[-2,0],[-3,0],[-6,7],[-3,1],[0,3],[0,7],[-2,8],[-1,3],[-1,2],[-7,9],[-1,1],[-2,7],[-5,10],[-2,1],[-1,0],[-1,-2],[1,-4],[0,-3],[0,-4],[0,-3],[3,-5],[0,-3],[2,-7],[0,-8],[-2,-3],[-3,4],[0,3],[0,3],[-3,7],[0,2],[-5,7],[-4,8],[-8,9],[-1,0],[-2,-1],[-1,-1],[-4,-4],[-1,-3],[0,-4],[-3,-4],[-4,-1],[-3,3],[-3,4],[-2,0],[-2,8],[-3,0],[-3,-5],[0,11],[0,11],[0,3],[2,3],[6,12],[1,3],[0,5],[-2,4],[-2,3],[-3,1],[-2,2],[-1,4],[-1,-7],[1,-10],[0,-6],[-1,-2],[-2,0],[-1,0],[-1,3],[-1,6],[-3,5],[-1,6],[-1,1],[-2,-1],[-1,3],[-1,8],[0,7],[-1,7],[-2,6],[0,6],[-2,23],[0,2],[0,2],[-2,3],[-1,3],[0,3],[0,11],[1,3],[1,1],[1,-2],[2,-3],[1,-1],[1,-2],[3,-7],[1,-1],[3,0],[2,1],[1,3],[0,3],[0,3],[-1,10],[-1,8],[0,7],[0,6],[3,11],[0,8],[0,11],[0,6],[0,3],[-1,6],[-1,6],[5,30],[1,6],[1,6],[0,8],[3,2],[3,3],[2,0],[1,-1],[4,2],[1,0]],[[8386,6272],[-2,-4],[-1,1],[1,4],[0,2],[1,3],[1,1],[2,-3],[-2,-4]],[[8367,6283],[0,-4],[-1,2],[-1,3],[1,2],[0,3],[1,-3],[0,-3]],[[8375,6299],[0,-5],[-2,0],[-2,3],[0,2],[0,1],[0,1],[4,-2]],[[8387,6357],[-1,-1],[0,6],[2,1],[1,0],[-2,-6]],[[8385,6381],[-2,-5],[-1,0],[0,3],[2,5],[1,-3]],[[8643,5358],[-1,0],[0,1],[0,1],[1,0],[0,-1],[0,-1]],[[8738,5609],[-2,-1],[-1,4],[1,5],[1,4],[1,1],[0,1],[1,5],[1,-3],[-1,-9],[-1,-4],[0,-3]],[[9264,4523],[5,-3],[1,-4],[-1,-1],[-5,-1],[0,2],[-4,2],[-1,4],[-2,-2],[1,3],[-2,3],[-1,4],[0,2],[3,-2],[6,-7]],[[9285,4529],[-1,-3],[-1,1],[-3,-1],[-1,0],[-1,3],[0,1],[2,-1],[0,3],[3,-1],[2,-2]],[[9191,4575],[-1,-4],[-2,1],[0,1],[0,3],[2,0],[1,-1]],[[9196,4607],[1,0],[2,4],[2,1],[1,-2],[-2,-13],[-2,2],[-6,3],[0,6],[-1,2],[-1,5],[-2,6],[-1,4],[1,-2],[2,-4],[5,-8],[0,-2],[1,-2]],[[9180,4645],[4,-4],[2,1],[2,-1],[2,-5],[0,-4],[1,-4],[0,-1],[-2,-2],[0,2],[-1,1],[-3,0],[-3,1],[-4,0],[2,4],[0,2],[-2,5],[0,3],[0,2],[2,1],[0,-1]],[[9175,4637],[0,-1],[-2,1],[-4,8],[1,5],[2,4],[3,-4],[1,-5],[0,-2],[-1,-6]],[[9239,4668],[1,-1],[4,0],[1,-3],[1,-1],[2,-2],[1,-2],[0,-1],[0,-1],[-1,-1],[0,-3],[-1,1],[-2,-2],[-3,3],[-1,1],[0,2],[-2,4],[-3,3],[1,2],[2,1]],[[8988,4687],[0,-3],[-4,3],[-4,6],[-2,2],[-1,4],[2,-3],[5,-3],[4,-6]],[[9196,4681],[1,-4],[-2,4],[1,5],[0,3],[0,1],[-2,3],[1,4],[1,1],[1,1],[0,-6],[0,-3],[-1,-9]],[[8988,4695],[-2,0],[-4,4],[-2,3],[6,-1],[1,-1],[1,-3],[0,-2]],[[9111,4848],[-1,0],[-1,2],[-2,3],[-3,7],[0,6],[1,1],[1,1],[6,-7],[0,-3],[0,-6],[-1,-4]],[[9331,4799],[0,-6],[-1,-1],[-1,2],[-2,-2],[-1,-2],[-1,-1],[-3,0],[-3,1],[-3,3],[-2,4],[-2,5],[-2,6],[1,7],[-1,5],[-4,5],[-1,1],[-2,6],[-2,3],[-2,5],[-1,2],[-1,7],[0,4],[0,11],[0,6],[1,0],[2,-3],[1,-1],[4,-1],[2,-5],[3,-9],[0,-3],[1,-2],[3,-4],[1,-2],[3,-10],[1,-2],[2,-1],[1,-2],[3,-4],[2,-5],[2,-5],[1,-5],[1,-7]],[[9087,4871],[-1,0],[-3,5],[0,2],[0,3],[3,4],[2,-4],[1,-7],[-2,-3]],[[9295,4871],[-1,-1],[-1,8],[0,5],[-1,4],[0,2],[2,5],[0,1],[2,-2],[0,-5],[1,-5],[-1,-9],[-1,-3]],[[9055,4912],[-2,-2],[-1,1],[-1,4],[1,4],[2,2],[1,1],[1,-2],[0,-3],[-1,-5]],[[9219,4936],[1,-1],[5,6],[2,-4],[3,-2],[3,-1],[-2,-9],[1,-4],[1,-4],[-1,-6],[-1,-5],[-3,-8],[-1,-1],[-1,-1],[-4,0],[-1,-4],[0,-5],[2,-5],[2,-7],[-2,-6],[-3,-4],[-2,-2],[-5,2],[-5,-1],[-1,-2],[0,-4],[-1,-3],[-1,-2],[-2,-6],[-3,-4],[-4,-5],[-1,-1],[-4,0],[-3,-3],[-1,-2],[-2,-2],[-3,-3],[-3,-4],[-1,-1],[-7,0],[-9,-1],[-3,0],[-3,0],[-1,2],[-4,8],[-2,3],[-3,0],[-5,-3],[-8,12],[-3,3],[-2,2],[-4,1],[-3,3],[-1,5],[0,7],[2,5],[4,-2],[1,0],[2,1],[1,-1],[2,-1],[6,2],[3,-2],[4,-3],[3,-1],[3,1],[5,3],[1,0],[4,0],[4,4],[1,18],[1,6],[1,1],[1,0],[1,-3],[-1,-4],[-1,-3],[0,-7],[1,-7],[2,-5],[3,-1],[3,4],[3,0],[3,-3],[3,0],[2,3],[1,1],[2,0],[1,1],[2,6],[1,7],[2,5],[6,9],[1,1],[2,1],[3,-1],[3,4],[0,7],[0,7],[-3,17],[0,2],[0,3],[1,3],[3,0],[3,-1],[2,-3],[1,-2]],[[9267,4948],[0,-2],[-1,2],[1,3],[0,-3]],[[9240,5003],[-1,-5],[-1,3],[-2,4],[1,2],[2,2],[1,-6]],[[9224,5014],[0,-3],[-1,0],[-2,6],[-1,1],[1,2],[2,-4],[1,-2]],[[9220,5021],[-1,0],[0,4],[1,3],[1,-2],[1,-4],[-2,-1]],[[8915,5022],[0,7],[0,4]],[[8915,5033],[1,0],[3,0],[2,-1],[14,-12],[4,-5],[1,-1],[2,0],[1,-1],[6,-7],[10,-7],[10,-6],[3,-2],[3,0],[7,-3],[3,-2],[6,-8],[2,-3],[3,-4],[4,-5],[1,-1],[1,-1],[4,0],[4,1],[1,-1],[1,-1],[2,-1],[0,-4],[3,-4],[3,-2],[3,-4],[2,-5],[2,-5],[2,-5],[4,-1],[3,-1],[12,-25],[1,-4],[0,-16],[-1,-13],[3,-4],[4,-2],[5,-3],[6,-4],[17,-17],[3,-2],[3,0],[4,0],[1,-1],[3,-3],[1,-2],[3,-6],[2,-6],[1,-2],[1,-1],[0,-3],[1,-11],[0,-6],[-1,-2],[-3,-1],[-10,-2],[-6,2],[-5,-7],[0,-3],[0,-2],[4,-14],[3,-12],[2,-5],[3,-4],[2,-5],[3,-5],[5,-10],[2,-3],[3,-3],[6,-7],[0,-3],[2,-10],[1,-7],[0,-3],[0,-3],[5,-6],[1,-2],[2,-14],[1,-7],[3,-2],[3,0],[9,4],[1,1],[1,-1],[2,-3],[0,-6],[-1,-7],[0,-6],[1,-5],[5,-4],[1,-1],[8,-2],[3,-1],[3,-2],[1,-1],[-1,-3],[-1,-1],[-2,-1],[-3,-2],[0,-4],[2,-3],[1,-5],[2,-2],[1,-1],[3,-1],[3,-2],[3,-3],[2,-1],[5,-1],[3,-3],[5,1],[-4,-4],[-2,-2],[-5,2],[-1,-2],[2,-5],[4,-3],[1,-2],[-1,-2],[-4,-5],[-1,-1],[-3,0],[-5,2],[-4,3],[-1,3],[-1,2],[-3,5],[-2,2],[-3,1],[-3,0],[-5,3],[-12,2],[-3,1],[-3,4],[-2,1],[-1,-1],[-5,-1],[-1,0],[-3,3],[-4,2],[-1,-1],[-1,-1],[-5,3],[-3,1],[-3,3],[-2,3],[-1,3],[-2,7],[-2,7],[-3,5],[-7,9],[-1,2],[-3,8],[0,6],[1,5],[-1,-2],[-2,0],[-4,4],[-2,4],[-3,12],[-2,6],[-4,11],[-1,6],[-2,6],[-1,2],[-1,2],[-1,3],[-1,3],[-7,4],[-1,2],[-1,1],[-4,0],[-3,1],[-5,4],[-3,1],[-3,1],[-3,1],[-1,2],[-1,2],[-1,6],[-2,0],[-3,1],[-2,2],[-3,1],[-1,-2],[-1,-5],[-1,0],[-1,1],[-1,0],[-1,-3],[-2,-2],[-2,0],[-5,3],[-2,2],[-2,3],[-1,4],[-2,3],[-1,2],[2,-5],[6,-23],[-2,0],[-1,0],[1,-4],[-2,-1],[-1,0],[-3,2],[-3,1],[-1,-1],[0,-2],[1,-4],[1,-6],[-4,-2],[-5,-1],[-5,-3],[-5,0],[-3,1],[-3,1],[-2,-1],[-3,-2],[-2,1],[-1,3],[-1,3],[-1,2],[-2,0],[-2,-1],[4,0],[1,-3],[0,-4],[3,-3],[3,2],[6,-1],[6,-6],[1,0],[1,-1],[4,-6],[2,-5],[2,-6],[0,-2],[0,-6],[0,-3],[-4,-5],[-4,-3],[-7,-6],[-5,-7],[-4,1],[-2,4],[-1,1],[-3,2],[-2,1],[-7,-2],[-7,-1],[-3,0],[-3,1],[-3,3],[-3,-1],[-2,-3],[-3,0],[-4,6]],[[9248,4910],[-2,-5],[-1,5],[-2,3],[-1,4],[-2,8],[0,4],[1,4],[0,4],[-1,9],[-2,8],[-7,19],[-2,4],[-2,5],[-2,1],[-3,1],[-1,1],[-3,3],[-2,4],[-6,10],[-4,3],[-1,4],[-10,12],[-2,3],[-4,0],[-3,2],[3,2],[0,4],[0,4],[4,-7],[5,-6],[2,-5],[2,0],[5,-4],[3,-3],[3,-4],[3,-6],[6,-4],[1,-2],[3,-8],[4,-6],[2,-4],[18,-30],[3,-8],[0,-6],[-1,-2],[-2,-5],[0,-6],[0,-5],[-2,-5]],[[9178,5030],[-6,0],[-2,1],[-1,3],[-2,5],[-2,1],[0,1],[4,4],[3,1],[6,-4],[0,-3],[0,-2],[0,-5],[0,-2]],[[9107,5052],[-1,-3],[-2,1],[-1,0],[1,1],[1,3],[1,0],[1,-2]],[[9084,5071],[10,-4],[0,2],[1,-1],[0,-3],[-2,0],[-1,0],[-1,-2],[-3,-5],[-2,1],[-2,-1],[-4,0],[-5,2],[-1,-2],[-2,1],[-1,-3],[-1,1],[-1,3],[0,1],[3,2],[-1,5],[2,2],[3,0],[2,2],[6,-1]],[[9159,5094],[0,-2],[-2,1],[-4,6],[0,4],[1,3],[2,-1],[2,-4],[1,-7]],[[5544,8321],[1,-1],[8,-1],[8,-1],[12,0],[14,-1],[13,-1],[15,-1],[16,-1],[1,1]],[[5655,8151],[2,-4],[0,-3],[0,-2],[0,-3],[1,-2],[4,-8],[2,-8],[2,-3],[3,-4],[0,-2],[-1,-1],[-1,0],[-1,-1],[0,-1],[0,-1],[1,-3],[2,-6],[0,-5],[-1,-1],[-2,-3],[-1,-3],[-7,-2],[-2,-2],[-4,-6],[-2,-3],[-4,-6],[-7,-10],[-2,-4],[-2,-4],[-5,-9],[-1,-4],[0,-3],[2,-7],[0,-4],[0,-3],[-1,-3],[0,-1],[2,-2],[2,-3],[0,-1],[0,-2],[-1,-1],[-3,1],[-3,3],[-1,-1]],[[5626,8010],[-2,1],[-8,4],[-5,3],[0,2],[-1,3],[-2,3],[-5,2],[-2,2],[-8,1],[-4,0],[-2,-1],[-2,0],[-2,-4],[-2,-2],[-2,0],[-2,1],[-2,2],[-3,2],[-2,-1],[-2,1],[-1,0],[-1,-1],[-1,0],[-2,-1],[-1,-1],[-2,-2],[-2,-2],[-1,-5],[-4,2],[-2,-1],[-1,-1],[-2,1],[1,2],[0,2],[0,2],[0,4],[-1,1],[-2,0],[-1,1],[0,1],[-1,1],[-2,3],[-1,4],[-2,2],[-1,-2],[-2,-3],[-2,0],[-3,-7],[-5,0],[0,3],[0,3],[-3,1]],[[5396,8279],[6,-4],[3,-2],[-1,2],[0,2],[0,3],[0,4],[-6,2],[-4,1]],[[5394,8291],[1,-1],[4,0],[9,5],[16,7],[17,7],[4,0],[4,2],[2,2],[1,2],[2,4],[5,7],[9,2],[4,4],[7,4],[16,5],[7,1],[6,0],[6,-4],[7,-4],[1,-3],[-4,1],[-5,5],[-1,0],[4,-13],[2,-5],[5,-4],[4,-1],[12,2],[4,3],[1,2]],[[3114,6224],[0,1],[-1,1],[0,1],[0,1],[2,0],[0,-1],[0,-1],[0,-1],[-1,-1]],[[3182,6227],[-2,-1],[-1,1],[-1,1],[3,2],[3,0],[2,-1],[0,-1],[-4,-1]],[[3163,6246],[1,-1],[0,3],[6,-2],[3,-2],[4,-1],[0,-8],[-3,-4],[-2,-3],[-1,-4],[-4,-5],[-4,-1],[-3,0],[-2,0],[-1,1],[-2,-1],[-3,2],[-2,-1],[-5,1],[-2,-2],[-2,0],[-1,0],[-2,1],[-3,0],[-2,1],[1,9],[0,4],[-1,4],[-1,2],[-1,3],[2,1],[1,3],[0,3],[1,1],[2,1],[7,-2],[17,-1],[1,0],[1,-2]],[[8469,7461],[-2,-2],[0,3],[1,3],[2,0],[-1,-4]],[[8625,7634],[1,-4],[1,-3],[1,-3],[1,-2],[0,-2]],[[8629,7620],[-1,-1],[-2,1],[-3,0],[-4,-5],[-2,-2],[-2,-4],[-3,-3],[-2,-4],[-2,-5],[-1,-5],[-4,-6],[-1,-6],[-1,-6],[3,-6],[0,-5],[-2,-11],[1,-11],[-1,-4],[-10,-7],[-3,-4],[-3,-10],[-5,-4],[-3,-4],[-4,-2],[-2,-7],[-3,-4],[-3,-2],[-3,-3],[-5,0],[-4,-3],[-3,-5],[-8,-7],[-1,-5],[0,-7],[0,-6],[-1,-5],[-1,1],[-1,-1],[-1,-5],[0,-5],[3,-2],[2,-2],[3,-1],[3,-2],[5,-11],[4,-4],[1,-2],[3,-3],[2,-3],[1,-4]],[[8517,7360],[-1,0],[-1,1],[-6,5],[-4,-3],[-1,-4],[-2,-1],[-1,7],[-3,0],[-5,7],[-2,-2],[-1,-2],[-2,-6],[-4,-5],[-1,-1],[-2,1],[1,1],[-2,6],[-6,2],[-2,2],[-1,1],[6,6],[1,1],[-1,1],[-1,1],[-5,-1],[-2,2],[-4,-1],[-2,2],[5,6],[0,4],[0,2],[3,8],[2,5],[7,6],[3,1],[2,-1],[2,1],[-2,2],[-2,2],[-3,-1],[-4,4],[0,4],[7,24],[0,2],[-1,6],[-1,5],[-5,4],[-2,0],[-6,7],[-3,3],[-1,-1],[0,-5],[-1,-1],[-2,-1],[-1,5],[-1,5],[-4,4],[-2,2],[1,6]],[[4522,7077],[4,-3],[3,1],[5,-3],[2,-1],[-2,-3],[-2,-4],[-5,1],[-4,4],[-2,2],[0,2],[1,4]],[[4304,7313],[0,-1],[-1,0],[-2,0],[-1,3],[1,1],[2,0],[1,-1],[0,-2]],[[4287,7363],[2,0],[9,1],[2,-1],[0,-4],[-2,-2],[-5,-1],[-8,3],[-3,4],[0,2],[0,1],[1,1],[4,-4]],[[4218,7399],[2,-3],[-3,0],[-2,-1],[-2,1],[-4,0],[-2,3],[0,3],[1,2],[3,0],[7,-5]],[[4204,7403],[-3,0],[-3,4],[4,2],[2,-1],[0,-2],[1,-2],[-1,-1]],[[4228,7405],[-1,-1],[-8,4],[-2,2],[-4,5],[10,-6],[5,-4]],[[4247,7410],[0,-1],[-6,2],[-1,2],[-1,4],[1,1],[2,1],[4,-1],[2,-3],[0,-3],[-1,-2]],[[4135,7454],[-2,-3],[-2,1],[0,1],[0,6],[2,1],[2,-2],[0,-4]],[[4794,7325],[-3,0],[-9,-10],[-3,0],[-5,4],[-10,2],[-3,1],[-4,-3],[-3,0],[-3,-3],[-1,1],[2,8],[3,15],[0,9],[0,8],[-1,8],[-1,5],[2,13],[0,7],[-2,8],[6,-1],[-2,3],[-2,2],[-2,0],[-1,0],[-5,-3],[-3,-1],[0,6],[-1,6],[2,2],[2,1],[2,3],[1,3],[0,6],[1,5],[4,5],[-2,-1],[-2,-3],[-4,-10],[-1,-6],[-3,-1],[-3,-1],[-2,0],[-2,2],[0,4],[0,3],[2,6],[0,9],[2,7],[0,3],[-1,3],[2,3],[2,2],[2,6],[4,16],[5,17],[0,2],[-1,2],[0,5],[3,20],[1,2],[1,6],[1,10],[0,6],[0,3],[0,4],[-2,8],[-2,16],[0,5],[1,3],[-2,0],[-1,3],[0,4],[3,7]],[[5949,6988],[6,9],[2,6]],[[1153,3982],[-1,-1],[0,2],[-1,3],[0,1],[1,-2],[1,-3]],[[1214,4116],[-1,-2],[0,2],[-2,1],[-1,2],[-1,0],[0,1],[1,0],[2,-2],[1,-1],[1,-1]],[[1092,4125],[0,-2],[0,1],[-2,2],[-1,2],[3,-3]],[[1195,4127],[0,-1],[-3,6],[2,-1],[1,-4]],[[1088,4136],[0,-1],[-1,1],[-1,3],[-2,3],[0,2],[1,-2],[1,-2],[2,-4]],[[1089,4155],[0,-1],[-1,0],[-1,1],[0,2],[1,2],[1,2],[1,2],[2,2],[1,1],[0,-1],[-4,-4],[-1,-3],[0,-2],[1,-1]],[[852,4165],[4,-3],[1,-4],[-1,-3],[-2,1],[-1,1],[-1,5],[-4,-1],[-3,1],[-2,7],[0,3],[1,2],[3,2],[3,-1],[2,-4],[0,-6]],[[838,4173],[0,-1],[-2,1],[0,1],[0,2],[0,2],[3,-1],[-1,-4]],[[794,4212],[-1,0],[-1,0],[0,6],[1,2],[1,-2],[1,-6],[-1,0]],[[1015,4227],[2,-3],[-2,2],[-3,0],[1,1],[2,0]],[[1012,4226],[-1,-1],[-3,4],[1,0],[2,-2],[1,-1]],[[793,4224],[-1,0],[-1,1],[0,2],[0,2],[2,-2],[0,-1],[0,-2]],[[959,4243],[0,-1],[-1,0],[-1,3],[0,3],[-1,3],[-1,2],[0,2],[0,3],[1,-5],[1,-4],[1,-3],[1,-3]],[[1041,4257],[0,-1],[0,5],[1,0],[-1,-4]],[[971,4271],[0,-3],[-1,2],[-2,4],[0,2],[3,-5]],[[1148,4578],[-1,-1],[0,6],[2,-1],[0,-1],[0,-2],[-1,-1]],[[1137,4612],[-2,-5],[0,5],[1,1],[1,-1]],[[1138,4625],[4,-3],[2,1],[-2,-3],[-4,-2],[-1,-1],[-2,1],[-1,3],[4,4]],[[1109,4641],[-1,-1],[-1,3],[0,2],[2,2],[1,-1],[-1,-5]],[[1123,4669],[-1,-1],[-1,3],[1,2],[1,0],[1,0],[1,-2],[0,-1],[-2,-1]],[[1109,4671],[-3,-2],[-1,0],[-1,5],[0,3],[1,1],[4,-1],[1,-2],[0,-2],[-1,-2]],[[6423,6601],[-2,-1],[-2,-1],[-2,0],[-2,0],[-1,1],[-2,5],[-1,7]],[[6411,6612],[0,3],[1,2],[-2,17],[-1,13],[0,2],[2,3],[1,7],[1,6],[3,15],[3,6],[4,4],[4,-8],[4,-6],[1,-7],[-1,-6],[-1,-9],[0,-4],[0,-4],[2,-6],[1,-8],[0,-5],[-1,-5],[-1,-5],[-3,-12],[-1,-2],[-4,-2]],[[5783,7802],[3,-6],[4,-3],[8,-4],[1,1],[0,1],[-1,1],[1,2],[1,0],[2,-2],[4,2],[5,5],[5,1],[5,-3],[2,-3],[2,-3]],[[5825,7791],[-1,-4],[0,-3],[-1,-9],[-1,-4],[-2,-4],[-14,-5],[1,2],[0,4],[-1,3],[2,3],[-4,1],[-1,-1],[-1,-3],[1,-6],[-2,-4],[0,-2],[0,-4],[-1,-2],[0,-2],[2,0],[-1,-4],[-4,-7],[-2,-5],[0,-18],[-1,-11],[-1,-3]],[[5630,7732],[0,3],[-1,1],[-2,2],[-2,2],[-1,3],[1,3],[1,3],[2,2],[2,-1],[1,1],[0,2],[-3,3],[-4,3],[-4,-2],[-4,-7],[-3,-1],[-2,5],[-3,2],[-5,1],[-3,2],[-1,3],[-2,2],[-4,2],[0,2],[2,0],[2,1],[1,1],[0,1],[-2,1],[-2,1],[-1,1],[0,1],[0,1],[0,1],[1,0],[0,1],[1,2],[1,2],[0,1],[0,1],[0,2],[-1,1],[-2,1],[-4,2],[-2,3],[-1,0],[-3,1],[-2,3],[-2,3],[-2,3],[0,1],[-1,1],[1,1],[0,1],[-1,3],[1,4],[0,3],[0,2],[-1,0],[-1,-1],[-2,3],[-2,5],[-1,2],[-3,2],[-2,2],[-2,4],[-1,4]],[[5635,7945],[1,1],[4,3],[1,2],[1,3],[2,-1],[6,-5],[6,0],[1,0],[1,0],[8,-3],[1,0],[1,0],[3,-2],[3,0],[3,2],[3,0],[2,0],[2,-4],[5,-6],[2,-3],[2,1],[3,1],[3,4],[8,5],[6,2],[6,2],[7,1],[2,4],[1,3],[1,5],[4,2],[4,1],[1,0]],[[9056,7684],[-1,1],[1,1],[1,0],[0,-1],[-1,-1]],[[9051,7687],[1,0],[1,0],[0,-1],[0,-1],[-1,0],[-1,1],[0,1]],[[9065,7697],[-1,-1],[-1,1],[-1,0],[1,0],[0,1],[1,0],[1,-1]],[[9074,7703],[0,-1],[-2,1],[0,3],[0,1],[6,3],[1,-2],[1,-1],[-6,-4]],[[9060,7747],[5,-4],[5,0],[-1,-3],[-2,0],[-4,-6],[-4,0],[-1,-2],[-6,-8],[0,-3],[-4,-6],[-5,-6],[-1,-10],[-3,4],[0,4],[1,4],[5,7],[3,4],[0,4],[3,3],[1,3],[1,2],[5,13],[2,0]],[[9127,7794],[-5,-4],[-5,-2],[-7,-8],[-2,-5],[-4,-2],[-3,1],[-1,-1],[-1,-4],[-1,-3],[-7,-9],[-3,-7],[-3,-1],[-5,-8],[1,7],[1,3],[4,5],[1,6],[2,5],[5,6],[4,6],[3,2],[3,6],[3,2],[0,4],[1,5],[1,-1],[3,-6],[2,0],[5,1],[8,12],[3,2],[2,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-3],[-1,-3],[-5,0]],[[6332,7804],[0,-1],[-2,5],[0,3],[1,2],[1,-5],[0,-4]],[[9157,7813],[-4,-3],[-3,0],[6,14],[4,2],[5,9],[9,10],[1,1],[6,-1],[-9,-11],[-1,-5],[-4,-4],[-3,-2],[-1,-2],[-6,-8]],[[9221,7885],[-5,-6],[-2,0],[0,2],[-1,1],[5,1],[4,9],[4,5],[2,2],[1,0],[-8,-14]],[[9252,7935],[-1,-3],[-2,0],[0,1],[1,4],[1,1],[1,-3]],[[9279,7994],[-1,-3],[-1,1],[0,1],[2,3],[1,5],[2,0],[1,-1],[0,-2],[-4,-4]],[[9299,8024],[-2,-2],[-3,1],[0,5],[6,15],[2,-1],[-1,-3],[-2,-6],[1,-7],[-1,-2]],[[9330,8081],[-3,-6],[-5,-1],[-3,-2],[-2,-4],[-1,-2],[-3,1],[-2,2],[0,7],[-1,3],[1,2],[3,0],[3,4],[7,2],[2,5],[3,11],[3,4],[3,1],[1,-6],[-1,-6],[-1,-6],[-4,-9]],[[9344,8102],[-1,-2],[-2,1],[-3,3],[-1,2],[1,3],[5,4],[2,0],[1,-1],[0,-5],[-2,-5]],[[9323,8111],[-3,-1],[-1,2],[-1,2],[0,2],[2,2],[2,-2],[1,-4],[0,-1]],[[8965,8317],[6,-15],[0,-3],[-1,-3],[-1,-4],[0,-5],[1,-4],[-1,-1],[5,-17],[4,-11],[1,-5],[0,-5],[1,-10],[1,-15],[-1,-5],[0,-5],[-1,-3],[-2,-2],[-1,-5],[0,-15],[1,-8],[1,-6],[2,-6],[0,-6],[0,-3],[3,-4],[1,-3],[0,-4],[0,-5],[1,-2],[1,-1],[6,-43],[2,-13],[6,-22],[3,-14],[2,-6],[1,-7],[1,-7],[2,-7],[2,-8],[5,-7],[2,-3],[1,-3],[0,-11],[-1,3],[-2,7],[-2,5],[-3,5],[-4,5],[-4,8],[-3,2],[-2,2],[-4,2],[-2,0],[-10,-1],[-4,-2],[-4,-3],[-2,-6],[-1,-11],[-9,-38],[-2,-10],[-1,-11],[0,-9],[1,-3],[2,-8],[2,-5],[2,-2],[2,-2],[1,-1],[1,-2],[1,-6],[3,-13],[2,-9],[1,-3],[3,1],[2,0],[2,-1],[1,-2],[1,-11],[1,-9],[0,-3],[-2,-7],[0,-4],[0,-3],[-1,-3],[-1,-2],[0,11],[-1,8],[-1,7],[-2,5],[-6,1],[-6,1],[-1,1],[-2,3],[-1,2],[-2,1],[-1,-1],[-3,-4],[-2,-5],[-2,-5],[-1,-6],[-3,-16],[-1,-5],[-2,-4],[-2,2],[-2,3],[0,4],[-1,5],[-2,16],[1,14],[4,20],[1,6],[-1,6],[-1,6],[0,11],[0,3],[1,6],[2,6],[2,6],[1,6],[-2,16],[-3,11],[-3,10],[-1,3],[0,3],[3,13],[1,6],[1,13],[2,7],[1,8],[0,37],[0,6],[-2,11],[-1,7],[1,8],[2,7],[1,6],[0,13],[-3,12],[-2,5],[-4,7],[-3,3],[-1,3],[1,1],[1,2],[-2,3],[-2,5],[0,20],[1,5],[2,5],[1,6],[2,14],[0,14],[-1,5],[0,12],[0,3],[4,4],[4,2],[2,-1],[3,-4],[2,0],[1,0],[3,2],[2,5],[-2,3],[1,4],[3,1],[1,4],[-2,0],[2,5],[0,4],[-1,4],[-5,11],[-4,7],[6,0],[2,2],[1,3],[1,3],[2,-1]],[[9667,8327],[1,-3],[-11,10],[-6,6],[-1,3],[2,0],[2,-3],[4,-2],[4,-4],[5,-7]],[[8810,8357],[-4,-10],[-2,0],[-2,2],[-4,0],[-1,0],[2,3],[6,5],[2,0],[2,1],[1,-1]],[[8831,8357],[2,-2],[4,0],[1,-1],[-3,-3],[-2,-5],[-1,-5],[-1,-1],[-2,-3],[-2,-3],[-2,-2],[-2,0],[-4,10],[-1,2],[-6,-4],[-1,0],[1,5],[3,7],[2,1],[3,8],[1,2],[9,-5],[1,-1]],[[5544,8321],[4,4],[3,6],[2,6],[1,5],[0,5],[4,2],[8,0],[3,2],[5,7],[4,7],[2,3]],[[5582,8368],[-3,-6],[-7,-11],[2,-2],[3,0],[3,-3],[3,0],[5,2],[1,10],[0,9]],[[9628,8342],[0,-8],[-3,4],[-2,4],[-2,0],[-2,2],[-2,4],[-4,5],[-1,3],[0,4],[-2,3],[-7,6],[2,0],[3,3],[8,-2],[2,0],[-1,-4],[0,-5],[4,-9],[2,-3],[3,-3],[2,-4]],[[9182,8583],[-2,0],[-1,1],[0,1],[3,3],[2,3],[2,-2],[0,-1],[-4,-5]],[[9544,8559],[-4,-5],[-1,1],[0,1],[0,2],[4,3],[4,10],[2,7],[-1,3],[0,2],[12,5],[9,7],[2,0],[1,-6],[1,-9],[-1,-4],[-10,-3],[-9,-6],[-9,-8]],[[5994,8938],[1,-2],[0,-4],[0,-2],[0,-2],[-2,-2],[-2,5],[-2,0],[-2,2],[-1,3],[2,1],[1,0],[3,2],[2,-1]],[[6944,9014],[-5,0],[-5,4],[-5,9],[1,2],[3,-1],[5,0],[3,-2],[5,-1],[-1,-4],[0,-1],[2,-2],[-2,-3],[-1,-1]],[[6186,9026],[-1,-1],[-6,3],[0,2],[0,1],[2,0],[3,-1],[1,-2],[1,-2]],[[6396,9169],[0,-6],[-2,-2],[-1,-1],[-1,4],[-1,1],[-5,-4],[-2,-4],[-6,-7],[-13,-5],[-7,-2],[-7,0],[-6,4],[-4,8],[0,2],[-1,3],[0,4],[1,5],[1,5],[2,4],[6,5],[6,4],[3,0],[8,1],[21,-12],[5,-3],[3,-4]],[[6870,9189],[-2,-5],[-5,0],[-1,1],[-1,1],[5,5],[4,0],[0,-2]],[[9484,9152],[-1,0],[1,4],[0,2],[-3,3],[-5,2],[-1,1],[0,5],[1,8],[-2,4],[0,4],[6,4],[3,3],[2,3],[1,0],[2,-3],[0,-5],[-2,-4],[-4,-1],[-1,-3],[1,-4],[0,-6],[0,-5],[3,-5],[1,-3],[-1,-2],[-1,-2]],[[9699,9192],[-8,-1],[-16,5],[-5,3],[-4,4],[-5,2],[-1,1],[1,2],[1,2],[5,4],[4,2],[5,1],[28,-8],[1,-2],[1,-1],[-1,-3],[-2,-1],[-1,-2],[-1,-6],[-1,-1],[-1,-1]],[[6679,9212],[0,-3],[0,-5],[-1,-4],[-3,-1],[-3,-1],[-5,1],[-3,-1],[-3,0],[-3,1],[-2,1],[-2,1],[0,3],[-2,4],[-3,1],[-3,1],[-4,1],[-1,0],[-3,-2],[-1,1],[-8,9],[-1,2],[-1,2],[-1,2],[-2,6],[1,3],[3,2],[1,0],[4,5],[5,1],[2,0],[1,-1],[6,-4],[3,-3],[3,-4],[3,-3],[9,-5],[6,-5],[6,-3],[2,-2]],[[6848,9247],[0,-2],[-1,0],[-2,3],[-1,3],[0,7],[0,1],[1,1],[1,0],[-1,-4],[3,-9]],[[9463,9263],[-1,-1],[-4,1],[-2,2],[0,4],[3,0],[2,-2],[2,-4]],[[6469,9294],[2,-4],[3,-3],[2,0],[1,-1],[0,-4],[-3,-5],[-1,-2],[2,-2],[0,-1],[-3,-1],[0,3],[-2,2],[-3,2],[-1,2],[-2,4],[-5,4],[-3,-1],[-4,2],[-1,1],[-1,2],[2,2],[6,1],[3,0],[3,-1],[0,2],[0,1],[1,-1],[4,-2]],[[8831,9303],[-7,-5],[-2,0],[-3,3],[-2,0],[-1,0],[-2,-1],[-2,0],[-5,2],[-1,2],[1,1],[1,0],[1,0],[4,2],[14,0],[2,0],[2,-2],[0,-2]],[[0,9304],[4,1],[5,2],[4,0],[4,-1],[4,0],[4,2],[3,-1],[3,0],[12,-3],[3,0],[4,-3],[2,-1],[2,-2],[2,-2],[5,-3],[6,-3],[2,-2],[0,-2],[0,-3],[-8,-6],[-7,-1],[-13,-2],[-18,-4],[-7,-1],[-2,0],[-7,3],[-7,1],[9996,-1],[-7,-5],[-14,-1],[-8,-3],[-2,0],[-4,10],[0,3],[1,3],[4,5],[2,3],[10,5],[8,7],[5,1],[5,3],[-9996,1]],[[7156,9348],[-14,-1],[-6,1],[-1,1],[0,3],[7,4],[3,3],[4,4],[5,4],[5,0],[15,-4],[2,-3],[0,-1],[-6,-4],[-4,-2],[-6,-4],[-4,-1]],[[7208,9372],[-2,0],[-16,2],[-5,3],[-1,3],[0,2],[14,12],[6,-3],[1,-3],[4,-4],[0,-9],[-1,-3]],[[7073,9381],[-2,1],[-4,1],[-7,4],[-2,3],[1,3],[1,2],[6,1],[6,-1],[3,0],[7,-3],[-7,-2],[-2,-3],[0,-3],[1,-1],[-1,-2]],[[8340,9394],[-7,-3],[-6,0],[-4,5],[3,1],[6,1],[3,0],[4,-3],[1,-1]],[[6536,9406],[13,-2],[10,-1],[6,-2],[2,-1],[-1,-4],[-2,-1],[-4,-5],[0,-2],[0,-5],[0,-3],[-2,-3],[-1,-1],[-7,0],[-3,-1],[0,-3],[0,-2],[-3,-5],[-5,-1],[-1,-1],[1,-3],[-2,-2],[0,-4],[1,-1],[0,-4],[4,-5],[-1,-3],[-3,-4],[0,-5],[-3,-5],[5,-4],[2,-5],[2,-5],[6,-10],[6,-10],[12,-14],[12,-10],[5,-3],[11,-5],[2,-1],[2,-2],[-5,-4],[-5,-2],[0,-1],[-3,-1],[-14,3],[-1,0],[-1,3],[-2,2],[-3,0],[-4,-1],[2,-2],[2,-1],[4,-4],[-1,-2],[-2,0],[-8,6],[-1,-1],[-1,-2],[-4,2],[-1,-1],[-3,-1],[-2,2],[0,2],[-1,1],[-12,-2],[-5,0],[-6,1],[-6,3],[-1,-1],[0,-2],[-2,1],[-5,3],[-4,1],[-13,3],[-10,3],[3,2],[4,0],[0,2],[-1,3],[0,3],[2,2],[5,-1],[0,4],[2,0],[5,-2],[2,2],[-8,4],[-8,5],[1,2],[-3,1],[-3,0],[-3,3],[1,5],[2,3],[-1,0],[-13,-2],[-6,0],[-8,2],[-6,-2],[-7,-1],[-3,1],[-4,2],[-3,2],[-2,5],[-2,7],[0,3],[0,6],[1,3],[3,5],[2,2],[4,2],[3,1],[5,-2],[5,0],[2,2],[2,2],[2,3],[3,2],[1,1],[1,2],[1,3],[1,3],[1,3],[3,4],[-1,2],[0,2],[2,2],[-6,1],[-2,1],[-3,2],[1,2],[1,1],[6,5],[3,2],[3,1],[3,-1],[4,0],[3,1],[-4,3],[0,2],[-1,5],[0,3],[2,2],[3,2],[4,1],[3,1],[4,2],[3,1],[6,-2],[3,1],[3,1],[10,4],[4,1],[3,0],[6,-2],[5,-3]],[[6962,9394],[-8,-3],[-2,0],[-5,1],[-2,-1],[-3,2],[0,3],[1,2],[1,3],[0,8],[4,5],[5,2],[17,2],[2,0],[3,-2],[3,-2],[3,-4],[3,-2],[4,-3],[1,-4],[0,-2],[-8,-1],[-13,-3],[-6,-1]],[[7131,9414],[-2,0],[-12,2],[-4,3],[1,1],[3,0],[14,-6]],[[7097,9415],[-5,-2],[1,3],[5,4],[10,2],[4,-1],[0,-1],[-4,-4],[-2,-1],[-9,0]],[[8949,9440],[7,-2],[5,-3],[20,-14],[2,-3],[1,-3],[1,-12],[-1,-1],[-7,-1],[-10,2],[-7,0],[-7,0],[-6,2],[-15,1],[-11,5],[-12,3],[-3,1],[-7,-1],[-10,-5],[-3,0],[-4,0],[-3,4],[7,1],[6,1],[7,1],[5,5],[3,4],[6,8],[2,3],[3,2],[3,1],[3,0],[11,2],[7,0],[7,-1]],[[8459,9437],[-2,0],[-3,2],[-1,2],[0,1],[3,1],[3,-1],[2,-2],[1,0],[-3,-3]],[[7320,9450],[-1,-1],[-2,0],[-1,-1],[-7,2],[-9,1],[2,3],[7,1],[10,-2],[3,-2],[-2,-1]],[[7297,9451],[-3,-2],[-4,1],[-2,2],[-2,2],[2,1],[4,0],[2,0],[2,-3],[1,-1]],[[8782,9441],[-2,-2],[-2,3],[-9,8],[-2,3],[-5,3],[-2,2],[0,3],[7,-2],[11,-8],[6,-6],[-2,-4]],[[8916,9446],[-14,-5],[-3,1],[-6,4],[-2,11],[2,3],[3,1],[3,0],[13,1],[2,-1],[3,-1],[1,-2],[0,-2],[-1,-7],[-1,-3]],[[7354,9473],[-2,-4],[-7,2],[-2,1],[5,2],[3,2],[6,0],[-3,-3]],[[8149,9469],[-1,-3],[-2,-2],[-1,-2],[-2,-2],[-6,-3],[-4,-5],[-1,0],[-16,3],[-3,0],[-5,4],[-8,3],[-3,4],[1,1],[2,1],[7,-1],[2,1],[1,4],[0,3],[1,1],[2,2],[24,-4],[9,-3],[3,-2]],[[7406,9503],[3,-1],[7,1],[1,0],[2,-3],[-3,-4],[-2,-2],[-7,1],[-8,0],[-4,3],[2,2],[5,2],[3,1],[1,0]],[[7282,9528],[1,-2],[0,-2],[-1,-1],[-4,0],[-2,-5],[-2,1],[-1,3],[-4,-2],[-2,0],[-2,3],[-1,0],[-1,2],[6,5],[4,-3],[2,0],[0,3],[0,2],[3,1],[4,0],[0,-5]],[[9077,9525],[7,0],[11,4],[1,0],[26,-2],[2,-1],[1,-3],[-1,-1],[-1,-3],[4,-2],[8,0],[5,2],[16,-1],[13,-2],[5,-3],[3,-2],[3,-2],[3,2],[2,2],[2,0],[2,0],[-5,-13],[-2,-1],[-7,-3],[-14,-4],[-6,-1],[-16,0],[-21,1],[-5,2],[-4,1],[-6,5],[-3,1],[-10,2],[-4,1],[-6,3],[-6,3],[-15,5],[1,6],[2,5],[2,5],[3,5],[3,1],[6,-4],[-1,-5],[2,-3]],[[8775,9527],[-5,-1],[-8,0],[0,4],[2,2],[2,5],[-1,3],[0,5],[1,3],[3,4],[2,-2],[2,-4],[1,-2],[6,-4],[2,-1],[-6,-5],[0,-2],[1,-3],[-2,-2]],[[9246,9568],[-3,-2],[-6,4],[2,1],[5,2],[0,-1],[1,-1],[1,-3]],[[8889,9551],[3,-1],[4,1],[3,-1],[3,-7],[1,-1],[2,-1],[1,-1],[5,0],[2,1],[1,3],[0,3],[0,3],[0,4],[0,3],[1,2],[2,2],[7,4],[5,4],[7,-1],[8,-4],[12,-8],[6,-3],[7,-2],[7,0],[4,0],[7,2],[3,0],[44,-16],[1,-1],[2,-2],[-9,-2],[-7,-4],[-2,-3],[3,-3],[2,-3],[-14,-9],[-5,-3],[-5,-1],[-11,3],[-7,-1],[-6,2],[-7,6],[-3,3],[-2,4],[-1,7],[1,5],[4,2],[3,3],[0,2],[-1,3],[-11,0],[-7,-1],[-6,-2],[2,-12],[1,-4],[2,-2],[10,-13],[2,-1],[6,-3],[6,-5],[-10,-6],[-4,-2],[-4,-1],[-3,1],[-2,1],[-3,3],[-3,3],[-3,2],[-6,0],[-6,-2],[-7,-2],[-18,-2],[-5,-2],[-6,0],[-7,3],[-7,4],[-2,0],[-2,-1],[-2,-3],[-1,-4],[-2,-5],[-3,-3],[-3,-2],[-3,0],[-3,1],[-4,1],[-21,6],[-3,2],[-2,2],[-6,8],[-4,2],[-3,1],[-6,4],[-6,6],[-1,2],[-1,3],[1,3],[5,-1],[4,0],[-2,12],[1,11],[3,2],[9,-2],[-3,4],[-2,5],[1,3],[2,2],[4,1],[6,1],[2,1],[1,2],[3,2],[6,1],[11,4],[3,0],[3,-2],[2,-3],[3,-2],[9,-4],[6,-3],[8,-8]],[[7681,9577],[2,-1],[-1,-2],[-3,1],[-3,-2],[0,-1],[-2,-4],[-5,2],[-7,1],[-5,1],[-10,2],[0,2],[2,2],[6,-2],[5,2],[10,-1],[3,2],[8,-2]],[[7690,9573],[-2,-1],[-1,1],[-1,0],[0,3],[3,4],[0,1],[1,1],[3,-1],[2,-2],[-2,-4],[-3,-2]],[[8124,9597],[4,-4],[1,-2],[-2,-1],[0,-1],[-1,-2],[-1,0],[-4,2],[-2,3],[-4,1],[-5,3],[-1,1],[2,1],[7,-1],[3,1],[3,-1]],[[7710,9596],[-1,-1],[-3,0],[-3,3],[-1,3],[2,1],[6,-6]],[[9142,9599],[-21,0],[2,1],[7,4],[19,2],[-4,-2],[-1,-4],[-2,-1]],[[6882,9575],[-11,-4],[-7,-3],[-7,-3],[-6,-1],[-11,-4],[-18,-4],[-12,-4],[-12,-3],[-14,-4],[-13,-3],[-3,0],[-10,-4],[-7,-1],[-28,-9],[-12,-6],[-4,0],[-3,0],[-3,-2],[-3,-3],[-6,-4],[-3,-3],[-3,-2],[-2,-1],[-3,0],[-2,0],[-5,-3],[-1,-2],[6,-1],[1,-3],[-2,-1],[-4,-3],[-2,-2],[-4,-2],[-2,-1],[-7,0],[0,-3],[1,-2],[-1,-1],[-2,-2],[-2,0],[-10,5],[-2,-2],[0,-3],[-1,-3],[-1,-3],[-2,-1],[-3,-1],[-11,2],[-1,-2],[2,-3],[2,-5],[1,-2],[-1,-4],[-5,-5],[-19,-7],[0,-2],[2,-5],[1,-3],[-1,-2],[-2,-2],[-3,0],[-2,0],[-4,3],[-4,1],[0,-2],[5,-4],[2,-5],[-3,-2],[-9,-6],[-4,-8],[-9,-4],[-6,0],[-6,1],[-5,1],[-14,1],[-7,2],[-8,4],[-6,-1],[-6,-1],[-7,-4],[-5,7],[2,4],[-10,9],[-2,4],[2,2],[3,1],[6,4],[6,2],[6,1],[1,1],[3,4],[2,4],[3,2],[3,3],[9,13],[2,1],[18,3],[2,1],[-6,2],[-5,0],[-2,1],[-2,2],[-1,2],[2,2],[8,8],[8,6],[8,3],[-2,1],[-3,2],[-9,0],[-4,3],[-1,2],[0,2],[3,2],[3,2],[3,-1],[4,-1],[3,-1],[2,-3],[3,0],[8,9],[-1,2],[-1,3],[1,1],[4,1],[3,1],[6,-1],[9,-2],[0,1],[2,6],[2,3],[9,5],[-1,1],[0,3],[10,3],[7,3],[6,5],[3,1],[3,0],[7,2],[12,2],[7,2],[2,5],[5,2],[9,1],[3,-1],[2,-2],[4,0],[2,1],[1,2],[0,3],[0,4],[3,2],[1,1],[11,0],[6,0],[12,-3],[7,0],[8,0],[6,0],[15,4],[26,4],[7,3],[6,3],[4,1],[3,0],[3,1],[7,3],[3,1],[3,0],[3,2],[3,4],[2,3],[8,5],[14,5],[12,3],[7,2],[4,1],[10,-2],[13,-3],[6,-4],[4,-4],[2,-2],[0,-3],[-1,-3],[-1,-3],[1,-2],[-9,-7],[-10,-8],[-1,-1],[-11,-3]],[[7674,9620],[-1,-1],[-1,-1],[-4,1],[-6,-2],[-3,1],[-2,2],[-9,0],[-2,0],[4,2],[12,2],[19,7],[1,-3],[-1,-2],[-3,-3],[-4,-3]],[[7486,9630],[-6,-1],[-4,2],[-1,1],[2,3],[2,1],[10,1],[1,-2],[0,-1],[-4,-4]],[[7983,9633],[-3,0],[-1,3],[3,3],[3,0],[3,-1],[1,-1],[1,-1],[0,-2],[-7,-1]],[[6367,7853],[0,-3],[-3,0],[0,-4],[-1,-2],[-8,-5],[-2,0],[-1,-1],[0,-3],[0,-3],[2,-3],[-1,-2],[-1,0],[-2,1],[-1,2],[-1,0],[-2,0],[-6,-9],[-3,-3],[-3,-1],[-6,-3],[-2,0],[-2,1],[-1,-1],[0,-5],[-2,3],[-2,3],[-1,0],[1,-5],[1,-4],[-1,-2],[0,-2],[-1,-1],[-2,-1],[0,-7],[-1,-5],[-2,-4],[-2,-7],[-2,-3],[-1,-4],[-1,-5],[-1,1],[-1,3],[-1,-3],[0,-3],[-3,-3],[-3,-4],[-1,-6],[0,-3],[0,-3],[1,-2],[5,-2],[3,-2],[2,-5],[3,-4],[2,-5],[2,-6],[2,-13],[1,-12],[3,16],[2,2],[-1,-4],[-1,-7],[-2,-10],[0,-7],[0,-7],[0,-3],[-1,-10],[1,-2],[1,-2],[3,-4],[2,-5],[0,-8],[1,-2],[2,-2],[7,-15],[4,-10],[2,-5],[2,-8],[2,-1],[1,-2],[3,-3]],[[6110,7685],[-3,3],[-10,14],[-5,10],[-17,23],[-2,1],[-9,4],[-4,2],[-9,16],[-4,-2],[-4,1],[-2,1],[-2,2],[-2,4],[-2,6],[-2,4],[-7,6],[-9,3],[0,1],[0,2],[7,4],[2,2],[-4,3],[-1,1],[-2,1],[2,2],[2,1],[4,-2],[3,-5],[3,-2],[2,3],[10,3],[1,3],[0,4],[-1,0],[-1,0],[0,4],[2,5],[5,9],[2,11],[2,3],[2,-2],[0,-2],[0,-2],[2,3],[1,6],[4,0],[2,-1],[3,1],[-5,8],[-7,9],[-3,-1],[-1,2],[-3,7],[-2,6],[3,0],[3,-1],[5,4],[2,1],[3,-2],[5,0],[0,3],[-2,5],[5,4],[5,2],[9,6],[4,1],[1,2],[0,2],[-1,5],[-2,4],[-5,1],[-2,-6],[-7,-2],[-4,1],[3,3],[2,2],[1,1],[-5,-1],[-3,-4],[-7,-5]],[[6061,7896],[0,3],[0,2],[0,2],[1,2],[1,1],[0,1],[-1,0],[-1,1],[0,1],[0,2],[1,1],[0,2],[0,5],[1,4],[2,3],[4,1],[4,2],[2,3],[3,7],[2,1],[4,0],[3,-1],[7,0],[7,0],[2,1],[1,2],[0,4],[1,5],[2,7],[2,4],[0,2],[-1,1],[-1,0],[-1,1],[0,2],[1,1],[0,4],[0,3],[-1,4],[-2,1],[-3,2],[0,4],[1,4],[2,3],[1,1],[3,-1],[2,1],[1,1],[-1,2],[-3,1],[-3,2],[-2,3],[0,3],[2,1],[3,2],[3,4],[2,4],[2,3],[0,3],[0,3],[-2,4],[0,4],[1,2],[0,2],[-2,1],[-2,0],[-2,-1],[-3,0],[-4,5],[-4,4],[-3,0],[-2,1],[-1,2],[-1,3],[-1,1],[-2,0],[-2,-2],[-4,1],[-3,3],[-4,4],[-3,0],[-3,1],[-5,5],[-1,0],[-1,-2],[-1,-4],[0,-1],[-1,0],[-2,-1],[-2,3],[-7,8],[-3,6],[-1,5],[-2,2],[-2,4],[-2,1],[-3,-2],[-2,-1],[-1,-1],[-4,-1],[-7,-2],[-1,-3],[-2,-2],[-2,1],[-2,3],[-3,1],[-2,-1],[-2,2],[-1,3],[-2,2],[-3,1],[-4,1],[-2,-2],[-4,-3],[-2,1],[-1,4],[-2,1],[-2,5],[0,4],[0,2],[1,2],[0,3],[-1,2],[-1,2],[-1,6],[-1,2],[0,3],[1,2],[-1,1],[-1,0],[-2,0],[-1,1],[-1,3],[-1,4],[-1,1],[-2,0],[-3,-1],[-3,-1],[-1,0],[-3,2],[-4,2],[-7,0],[0,1],[0,1],[2,2],[-1,2],[-1,1],[0,4],[0,3],[-1,4],[-1,3],[-1,2],[0,2],[3,1],[4,2],[1,1],[0,2],[-8,12],[-3,10],[-2,5],[-3,4],[-2,2],[-4,-1],[-4,0],[-5,1],[-4,0],[-7,-5],[-2,-1],[-5,2],[-4,2],[-2,0],[-1,-1],[-1,-1],[-2,-10],[-2,-1],[-2,-2],[-3,0],[-1,0],[-3,1],[-3,2]],[[5778,8610],[1,4],[-1,5],[0,5],[1,3],[2,0],[2,-3],[3,-2],[3,2],[1,5],[2,2],[2,-2],[4,0],[3,0],[3,1],[0,1],[1,3],[2,3],[2,3],[15,-3],[12,-5],[1,2],[1,3],[-4,3],[-2,1],[-3,6],[-4,4],[-4,0],[-6,-1],[-8,1],[-7,8],[-5,2],[-3,7],[-1,3],[3,-3],[1,3],[0,4],[-2,2],[-2,2],[-9,-6],[-10,-2]],[[5857,9203],[5,-1],[11,-4],[3,0],[3,2],[3,5],[3,1],[3,-1],[1,1],[-2,5],[1,2],[11,-5],[5,-3],[10,-4],[2,-1],[0,-3],[0,-3],[-2,-1],[-5,0],[-16,4],[-2,-2],[2,-3],[4,-2],[2,-4],[7,0],[7,-1],[3,0],[1,-1],[-3,-4],[1,-1],[8,4],[4,1],[2,-1],[0,-3],[-1,-4],[0,-3],[-3,-6],[-3,-2],[-2,-3],[5,2],[3,2],[5,9],[2,1],[15,0],[4,0],[14,-5],[4,0],[5,0],[1,2],[2,1],[15,-5],[22,-11],[30,-18],[18,-16],[2,-3],[6,-2],[2,1],[3,-1],[21,-14],[7,-1],[-1,3],[-2,3],[2,-1],[3,-2],[3,-6],[5,-4],[5,-6],[4,-3],[4,-1],[3,-1],[5,-2],[3,-16],[2,-3],[0,-7],[4,-3],[2,0],[0,-5],[-2,-12],[-2,-5],[-19,-22],[-12,-8],[-22,-10],[-18,-4],[-7,0],[-14,2],[-7,2],[-10,5],[-8,3],[-6,1],[-11,1],[-24,5],[-4,2],[-15,10],[-6,-2],[-4,-1],[-2,4],[1,1],[0,1],[-8,3],[-7,0],[-4,3],[-4,1],[-2,-1],[-2,0],[-9,5],[-4,4],[-4,6],[1,2],[1,2],[-15,4],[-14,0],[3,-2],[6,-1],[4,-2],[4,-4],[-1,-5],[6,-5],[5,-5],[0,-1],[2,-1],[7,-2],[1,-4],[-1,-2],[1,-2],[5,-3],[3,-1],[4,-1],[-1,-4],[-4,-2],[-3,-1],[2,-1],[4,1],[15,-6],[8,-5],[8,-10],[3,-6],[0,-2],[-1,-3],[-1,-3],[0,-3],[-3,-9],[-2,-3],[-4,-4],[4,-6],[3,-7],[4,-10],[1,-4],[0,-7],[3,-2],[-1,-1],[-1,-2],[0,-9],[5,-7],[7,-4],[4,-1],[6,2],[4,-3],[9,-8],[5,-9],[2,-2],[9,-3],[7,-2],[12,-5],[1,-1],[6,5],[9,3],[3,5],[0,3],[-3,7],[0,7],[-3,2],[-3,2],[-9,-1],[-4,0],[-3,2],[-4,4],[-7,12],[-4,3],[-2,3],[-1,3],[0,5],[4,0],[3,3],[3,11],[5,1],[2,0],[11,-5],[13,-13],[3,-2],[3,0],[5,0],[1,-1],[3,-2],[2,-1],[12,-4],[14,-8],[6,0],[2,5],[0,2],[6,4],[4,1],[6,-1],[1,1],[-2,7],[-3,6],[-4,3],[-6,11],[-3,6],[-1,5],[0,5],[1,4],[15,9],[5,5],[5,7],[2,2],[8,2],[11,5],[9,8],[8,12],[4,3],[3,0],[4,-2],[4,-3],[5,-1],[6,1],[6,-1],[9,-5],[2,-2],[1,-2],[-3,-5],[0,-3],[2,2],[3,0],[3,-1],[3,-2],[2,-3],[3,-2],[0,3],[1,3],[-2,7],[4,10],[2,4],[5,11],[-1,7],[0,8],[-1,4],[-3,6],[-6,4],[-6,1],[-2,4],[0,4],[2,6],[5,14],[5,18],[0,5],[0,2],[0,2],[-1,6],[-1,4],[-21,17],[-1,1],[-1,2],[2,1],[2,0],[16,-8],[3,0],[26,2],[12,-2],[10,-4],[8,-11],[7,-10],[7,-8],[0,-7],[-7,-2],[-7,0],[-18,-3],[-4,-4],[-12,-13],[-1,-3],[1,-4],[5,-4],[12,-5],[5,-12],[4,-5],[3,-3],[2,0],[6,0],[5,-2],[1,-1],[1,1],[4,1],[23,6],[4,3],[2,3],[1,14],[2,4],[2,6],[-1,4],[0,4],[11,3],[11,3],[5,-1],[1,3],[-3,6],[-2,2],[2,1],[2,-1],[3,-1],[6,1],[21,11],[9,7],[5,2],[8,6],[4,2],[6,0],[7,3],[8,4],[11,4],[1,0],[2,-1],[5,-4],[-2,-2],[-1,-3],[2,-1],[2,-1],[2,1],[2,2],[5,2],[2,3],[-2,2],[-3,5],[-3,1],[-3,0],[10,7],[20,10],[11,5],[11,0],[8,0],[-3,-2],[-14,-2],[-2,-1],[0,-2],[3,0],[2,-2],[-2,-2],[-1,0],[-1,-6],[-2,-4],[4,-6],[0,-5],[-2,-3],[-4,1],[-4,-2],[-6,-2],[-1,-2],[-1,-2],[4,-1],[3,0],[11,-1],[1,0],[4,1],[4,1],[4,0],[3,1],[2,-1],[4,-5],[4,1],[2,10],[6,6],[8,5],[7,1],[7,3],[3,1],[7,-2],[9,0],[8,-3],[6,-1],[9,5],[20,15],[2,-3],[3,4],[16,5],[4,0],[0,-1],[1,-5],[3,-3],[5,-6],[-2,-2],[-3,-1],[-3,-4],[0,-10],[6,-2],[8,-3],[3,0],[3,1],[1,1],[1,2],[1,3],[0,2],[-2,5],[1,6],[7,0],[10,1],[4,4],[5,6],[3,5],[-2,9],[-6,-2],[-9,20],[-4,8],[3,4],[8,2],[7,7],[2,2],[3,0],[21,-5],[24,-1],[20,-4],[23,-8],[12,-6],[9,-6],[-1,-5],[4,2],[8,-4],[6,-2],[5,-2],[2,-3],[8,-3],[8,-4],[1,-1],[10,-3],[6,-1],[5,-7],[13,-10],[3,-4],[12,-6],[6,-5],[3,2],[9,12],[6,15],[3,7],[-6,1],[-5,-3],[-2,1],[-4,2],[-5,6],[-7,10],[-1,10],[-2,4],[-6,3],[-4,3],[-16,6],[-3,-2],[0,-4],[-1,-2],[-2,3],[-1,3],[0,5],[1,6],[2,10],[4,-1],[2,1],[3,5],[-1,4],[-2,2],[1,5],[2,11],[1,14],[-2,4],[-2,2],[-9,-2],[-3,1],[-1,2],[0,3],[3,3],[2,6],[-4,-1],[-2,2],[4,3],[4,9],[10,3],[7,4],[12,8],[9,8],[5,9],[4,10],[6,21],[6,16],[10,17],[6,1],[2,0],[1,-1],[-2,-1],[0,-2],[2,-1],[5,0],[8,1],[13,-1],[23,2],[4,-1],[8,-5],[5,1],[10,-3],[5,-2],[5,-3],[-1,-12],[-1,-8],[-3,-16],[-2,-3],[-5,-11],[-3,-8],[-4,-5],[-6,-3],[-1,-2],[0,-3],[6,-9],[13,-9],[4,-11],[1,-8],[-1,-21],[-2,-3],[-2,-3],[-3,-4],[2,-6],[2,-22],[0,-18],[-1,-6],[-1,-13],[0,-4],[1,-7],[3,-5],[4,-4],[10,-6],[10,-7],[1,-3],[1,-3],[-4,-3],[-6,-8],[-3,-6],[0,-5],[1,-7],[-1,-6],[-2,-6],[-3,-4],[-10,-6],[-21,-34],[-5,-4],[-8,2],[2,-5],[3,-7],[0,-4],[-6,0],[-8,-5],[-3,-3],[-6,-2],[-5,2],[-5,3],[1,3],[1,1],[4,2],[3,2],[-2,1],[-1,0],[-4,-4],[-4,0],[-6,4],[-4,4],[-2,1],[-3,-2],[-15,1],[-4,-1],[-2,-1],[1,-2],[2,-2],[1,-5],[1,-3],[6,-4],[8,-2],[8,-5],[10,-3],[23,1],[5,0],[6,-1],[10,-5],[4,0],[7,4],[2,10],[1,4],[26,14],[4,3],[8,8],[3,5],[2,14],[3,5],[17,16],[2,4],[1,8],[-1,5],[-1,5],[-3,8],[-3,5],[-3,7],[2,13],[3,6],[15,6],[13,2],[14,5],[6,1],[4,-1],[4,-5],[4,-7],[10,-10],[4,-7],[0,-9],[0,-22],[-2,-9],[4,-3],[2,-2],[5,-3],[3,-3],[3,-1],[6,-1],[16,1],[10,1],[-1,1],[-2,1],[-8,1],[-11,2],[-15,4],[-2,9],[0,6],[4,10],[2,2],[3,1],[4,1],[-1,7],[-2,6],[-3,9],[-4,16],[-5,0],[-4,3],[-19,9],[-18,7],[-12,1],[-4,-1],[-10,-7],[-7,-2],[-12,3],[-11,-1],[-4,1],[-1,4],[3,12],[-2,5],[-4,7],[-3,5],[0,5],[7,22],[3,5],[8,10],[3,8],[-1,4],[-16,24],[-4,9],[-2,2],[-4,4],[-6,3],[-2,4],[17,23],[7,4],[10,2],[5,3],[9,4],[5,4],[2,3],[1,4],[0,9],[-1,7],[-1,5],[-3,5],[-3,6],[2,1],[2,1],[6,0],[6,-3],[3,-7],[3,-6],[0,-4],[0,-3],[2,-4],[1,-2],[1,-3],[-1,-3],[-1,-1],[-3,-3],[-4,-11],[-4,-1],[0,-9],[7,-9],[-1,-7],[-2,-2],[-4,-4],[1,-3],[1,-2],[11,-4],[10,-3],[18,-1],[5,-4],[2,3],[17,-1],[13,-10],[7,-4],[6,-1],[11,1],[2,1],[2,3],[-5,0],[-3,-1],[-2,0],[-4,1],[-2,2],[-3,3],[-5,11],[-9,3],[-5,-1],[-6,0],[-11,6],[-6,2],[-13,6],[-3,3],[-3,5],[-3,8],[-2,5],[3,1],[8,4],[13,2],[5,-2],[13,-9],[7,-1],[11,5],[1,2],[-2,5],[-4,3],[-6,1],[-8,-2],[-2,2],[0,3],[1,2],[5,0],[3,2],[6,6],[7,3],[7,1],[26,-1],[15,-9],[15,-4],[6,-3],[2,-1],[1,-2],[1,-5],[18,-13],[5,-1],[11,-1],[13,3],[6,0],[6,-1],[4,-1],[3,-3],[-2,-4],[-1,-2],[-4,-7],[-1,-2],[-12,-7],[-5,-2],[-1,-9],[-1,-2],[0,-4],[2,-7],[0,-4],[-1,-6],[-3,-6],[0,-5],[1,-7],[1,2],[-1,4],[1,3],[6,8],[4,12],[4,3],[3,1],[4,-4],[1,-4],[0,-7],[0,-7],[-3,-10],[-5,-7],[-2,-4],[2,-3],[3,-3],[3,-1],[3,0],[1,1],[0,3],[-1,3],[0,4],[6,2],[6,2],[4,4],[1,3],[1,4],[-2,7],[-2,6],[-7,13],[-5,6],[3,10],[6,11],[2,3],[0,2],[1,3],[-1,3],[0,2],[-6,8],[-4,3],[-12,1],[-3,2],[-9,8],[-1,2],[-2,6],[-1,2],[-2,1],[-9,4],[-5,1],[-9,1],[-5,1],[-8,6],[0,2],[-3,7],[-1,4],[0,3],[3,5],[2,6],[-2,4],[-4,1],[-3,2],[-2,4],[-1,5],[0,3],[0,4],[1,3],[4,4],[-1,2],[1,3],[24,4],[10,1],[48,1],[3,1],[21,2],[9,2],[10,-2],[3,0],[7,1],[4,5],[11,2],[17,2],[8,0],[2,-2],[2,-2],[-9,-6],[-10,-6],[-7,-2],[-8,-5],[0,-2],[-1,-1],[1,-4],[0,-3],[8,-3],[6,-4],[5,-3],[5,-2],[1,1],[-16,10],[-5,2],[-1,3],[0,4],[2,1],[3,2],[1,1],[7,2],[20,3],[5,5],[2,3],[6,3],[-2,1],[-5,1],[-3,2],[-14,18],[-4,3],[-11,2],[-5,2],[5,6],[6,2],[4,0],[4,-2],[6,-5],[9,2],[-3,2],[-6,3],[-5,4],[-8,4],[-9,2],[-9,1],[3,6],[5,-1],[1,2],[3,3],[12,-8],[6,2],[5,4],[11,9],[1,4],[-5,3],[-4,1],[-6,0],[0,2],[2,3],[5,2],[14,-4],[23,9],[6,5],[16,6],[8,-1],[16,8],[23,3],[13,0],[11,4],[15,2],[6,2],[26,4],[14,3],[3,3],[-13,-2],[-3,2],[-3,-2],[-2,-1],[-6,3],[-2,-1],[-2,-2],[-2,0],[-2,0],[-1,4],[3,6],[3,-3],[5,4],[3,0],[8,-3],[5,3],[7,1],[8,-1],[3,0],[2,3],[13,-2],[9,1],[6,0],[10,-1],[4,-2],[-2,-4],[-10,-7],[3,-1],[5,3],[16,5],[3,-1],[-2,-4],[-1,-2],[10,2],[9,5],[4,1],[5,-3],[3,3],[1,3],[7,0],[3,3],[5,2],[4,1],[9,3],[3,-1],[6,-1],[5,-1],[11,-4],[1,-2],[2,0],[3,-3],[-3,-4],[-2,-6],[-4,-3],[2,0],[2,0],[4,4],[3,3],[-1,12],[-6,6],[-4,2],[-10,6],[-4,3],[-4,3],[2,2],[19,-3],[10,1],[11,0],[14,3],[6,-3],[7,0],[8,-2],[3,2],[-13,3],[-6,0],[-2,1],[2,4],[3,5],[-3,4],[-2,3],[-1,4],[3,5],[5,3],[3,4],[6,5],[31,18],[14,7],[6,1],[6,-1],[13,6],[4,0],[18,-5],[4,-3],[9,-2],[12,-2],[5,-2],[2,-2],[2,-4],[-9,-2],[-9,-6],[-14,-4],[-16,-2],[-3,-2],[31,-1],[9,1],[2,-6],[3,0],[9,2],[5,1],[10,-2],[2,1],[5,0],[9,-3],[4,-3],[-6,-6],[-7,-6],[-9,-9],[-2,1],[-5,0],[1,-4],[8,0],[4,-2],[9,2],[13,0],[2,0],[5,3],[2,5],[2,4],[4,1],[5,-1],[8,0],[20,1],[17,-2],[14,3],[18,-2],[7,-2],[6,-4],[5,-1],[5,-3],[4,-4],[-2,-3],[-2,-3],[5,3],[5,0],[3,-1],[6,-2],[1,-9],[2,-2],[1,-3],[-2,-3],[-1,-2],[4,1],[6,3],[2,1],[1,2],[-2,3],[-2,1],[2,1],[6,0],[2,-4],[2,-4],[4,-13],[8,2],[0,-4],[-3,-9],[-4,-6],[-1,-2],[-2,0],[0,4],[-1,2],[-2,1],[-7,1],[-14,8],[-4,1],[-1,-1],[0,-1],[8,-5],[6,-9],[6,2],[2,0],[3,-5],[6,-1],[4,-3],[-3,-9],[-19,-16],[-20,-10],[-9,-6],[-16,-5],[-11,-6],[-15,-5],[-4,-5],[-11,-3],[1,-2],[1,-2],[-1,-3],[-2,-2],[-8,-5],[-12,-3],[-24,-20],[-12,-4],[-14,0],[-3,-2],[-10,-12],[-3,-2],[-14,-2],[-14,-20],[-8,-7],[-7,-3],[7,0],[9,3],[10,7],[2,3],[1,3],[3,3],[5,2],[17,2],[8,-1],[10,0],[7,4],[4,1],[4,1],[2,2],[6,1],[14,3],[3,2],[4,5],[9,-2],[6,1],[16,9],[9,3],[3,3],[-2,1],[-2,1],[-9,-3],[-9,-1],[-9,1],[-1,1],[-2,4],[3,4],[3,3],[6,4],[5,1],[18,-4],[4,0],[2,6],[6,0],[6,-1],[-3,-2],[-6,-2],[2,-5],[3,-3],[11,-5],[9,-2],[7,0],[11,2],[2,2],[2,4],[-2,7],[2,-1],[3,-2],[4,-4],[4,-8],[3,-3],[-2,-4],[-6,-7],[4,-4],[6,-3],[0,-11],[-1,-6],[-3,-6],[-3,-2],[-3,-4],[0,-4],[1,-2],[4,-4],[10,-2],[1,2],[-2,1],[-7,2],[-3,1],[-2,4],[3,4],[3,4],[3,7],[1,5],[0,5],[2,2],[3,3],[2,0],[2,1],[-3,2],[-2,0],[-5,3],[-1,5],[10,1],[6,3],[21,1],[14,6],[32,-2],[23,-4],[31,-1],[12,-3],[1,-1],[1,-2],[-5,-1],[-8,0],[-3,-5],[2,-7],[15,-8],[13,-3],[9,-5],[4,0],[19,0],[11,-2],[10,2],[11,0],[4,-1],[4,-3],[6,-1],[8,-1],[4,1],[2,1],[-1,2],[-6,2],[1,2],[2,1],[11,-4],[4,0],[4,3],[3,4],[2,4],[1,1],[2,1],[1,1],[-3,4],[-4,4],[0,4],[-1,1],[-1,6],[3,6],[2,2],[9,-2],[4,3],[2,2],[10,2],[5,0],[7,-3],[23,-11],[-1,-4],[5,1],[3,2],[6,1],[4,2],[1,-1],[2,-1],[-1,-3],[-2,-2],[1,-2],[1,0],[7,-3],[7,5],[4,6],[2,1],[19,-4],[6,-2],[2,-1],[0,-2],[4,-2],[4,-1],[-1,-2],[0,-2],[9,0],[4,-2],[4,-3],[0,-2],[1,-2],[4,0],[1,0],[-1,-4],[-6,-4],[-3,-2],[-4,-3],[2,0],[10,-1],[6,-5],[0,-4],[-3,-2],[-9,-5],[-5,-2],[-3,-1],[-3,0],[4,-3],[16,0],[4,-3],[4,-7],[0,-9],[-4,-4],[-9,-1],[-13,10],[-8,4],[-11,7],[-2,-1],[3,-6],[5,-4],[10,-9],[15,-19],[4,1],[2,3],[1,3],[-1,4],[2,-2],[3,-4],[4,-6],[-6,0],[-8,-2],[-3,-2],[2,-4],[6,-1],[3,-4],[4,-6],[11,-17],[7,-3],[7,-7],[7,-3],[4,0],[2,4],[2,-1],[2,-8],[4,-3],[3,-1],[3,2],[5,3],[4,5],[5,11],[4,6],[4,2],[-1,3],[0,3],[3,8],[3,9],[3,5],[6,10],[3,2],[2,-4],[1,-4],[1,-2],[1,0],[8,-9],[8,-6],[8,-4],[11,-3],[17,1],[3,4],[6,3],[9,2],[6,3],[9,2],[5,-1],[9,-3],[20,-9],[5,-3],[3,-3],[7,-6],[4,-2],[4,-2],[1,1],[0,1],[-2,1],[-2,2],[5,2],[0,2],[2,1],[6,1],[-6,2],[-2,0],[-3,1],[0,3],[2,2],[2,4],[2,2],[3,2],[2,0],[6,-2],[4,4],[3,0],[6,-5],[6,-6],[3,0],[9,2],[10,1],[-2,3],[-6,9],[0,10],[-4,3],[-6,1],[8,3],[6,8],[4,1],[5,2],[-1,1],[-15,1],[-3,-1],[-2,-3],[-7,0],[-1,6],[0,4],[9,8],[4,1],[24,0],[7,2],[10,4],[-3,2],[0,5],[-9,7],[1,2],[1,1],[2,0],[14,-2],[6,-4],[15,-4],[41,-1],[4,-1],[18,-2],[7,-2],[17,-2],[8,-2],[7,-2],[10,-2],[5,-2],[-1,-5],[-21,1],[-7,2],[-9,0],[-3,-1],[-6,-5],[-6,-2],[-5,0],[3,-4],[5,-1],[16,5],[43,2],[7,0],[-1,-3],[-6,-7],[-5,-5],[-8,-5],[-3,0],[6,11],[-3,0],[-2,0],[-7,5],[-1,0],[-1,-1],[0,-2],[-2,-6],[3,-3],[0,-4],[-10,-3],[-4,0],[-4,2],[-1,0],[-1,-2],[1,-2],[0,-2],[-2,-2],[0,-2],[2,-3],[3,-1],[17,3],[8,4],[8,6],[15,16],[6,6],[4,2],[4,1],[27,-2],[16,-4],[15,-5],[7,-4],[6,-6],[1,-2],[0,-3],[-4,-3],[-16,-1],[-7,-2],[-2,-2],[0,-1],[-1,-2],[1,-1],[8,0],[7,-1],[10,-4],[1,-1],[3,-4],[1,0],[15,0],[1,-1],[1,-2],[-4,-4],[-4,-3],[-8,-7],[5,3],[16,5],[4,1],[5,0],[12,-5],[5,-4],[9,-11],[-3,-2],[-6,-1],[20,-8],[8,0],[19,2],[9,0],[17,6],[17,3],[16,1],[8,3],[22,0],[22,-1],[16,-2],[18,-6],[18,-9],[11,-8],[2,-2],[3,-6],[1,-5],[2,-6],[-1,-6],[-3,-3],[-1,-5],[0,-5],[-3,-7],[3,-5],[8,-3],[17,-4],[5,-3],[0,-8],[2,-8],[1,-13],[3,-4],[5,-3],[1,-4],[-6,-15],[-4,-3],[-4,-4],[7,2],[4,5],[3,10],[4,1],[2,4],[0,9],[-2,8],[0,5],[1,5],[12,9],[6,4],[5,2],[16,2],[7,2],[9,-1],[5,1],[7,1],[6,0],[10,-7],[35,-1],[6,-2],[23,-3],[2,0],[5,3],[15,11],[7,-1],[2,-2],[3,-4],[3,-3],[2,-7],[2,-10],[3,-2],[5,-1],[10,-4],[10,-4],[3,-10],[5,-7],[13,0],[13,2],[13,13],[0,5],[-3,7],[-5,7],[-4,12],[-11,2],[1,3],[4,4],[4,6],[1,5],[-1,10],[10,-1],[11,-1],[20,-4],[16,-2],[9,-3],[5,-3],[6,-2],[2,5],[3,2],[8,-4],[6,-1],[10,1],[13,-2],[14,1],[13,2],[5,0],[5,-2],[8,-6],[15,-7],[13,-2],[15,-6],[14,-3],[11,-4],[2,-1],[0,-2],[1,-2],[9,-2],[16,-14],[-9995,-2],[6,-2],[5,-2],[2,0],[2,0],[3,-3],[2,-2],[11,-4],[5,-5],[5,-5],[-2,1],[-4,4],[0,-4],[1,-3],[6,-3],[7,-2],[4,-2],[1,-2],[1,-4],[-1,-3],[4,1],[3,3],[-2,2],[-11,8],[-3,3],[4,-1],[15,-11],[5,-4],[-2,0],[-1,-3],[1,-1],[2,1],[3,1],[3,-2],[4,-2],[7,-4],[43,-25],[1,-4],[1,-2],[1,-3],[0,-4],[-4,-6],[7,1],[0,1],[2,2],[2,1],[2,-2],[2,-3],[-1,-5],[-1,-3],[0,-7],[1,-5],[2,-2],[1,-3],[0,-8],[-3,-3],[-1,-6],[2,0],[5,-1],[2,-1],[3,-3],[0,-2],[1,-4],[1,-3],[1,-2],[4,5],[1,1],[3,2],[2,-6],[-1,-8],[1,0],[1,0],[1,3],[1,1],[2,3],[2,4],[-2,3],[-2,2],[-5,1],[-3,3],[-1,3],[3,1],[2,2],[2,5],[-1,3],[0,3],[-2,4],[-2,2],[-3,1],[-2,2],[-2,0],[-3,1],[-1,1],[0,1],[3,1],[16,0],[6,2],[2,0],[3,-2],[9,-2],[0,-1],[-2,-1],[-3,-5],[0,-2],[0,-4],[2,0],[3,1],[-2,3],[0,3],[1,2],[1,0],[3,-3],[2,0],[9,-1],[3,0],[1,1],[-2,2],[-12,3],[0,2],[11,-3],[5,-2],[5,-1],[6,0],[7,-2],[6,-7],[6,-8],[6,-5],[6,-3],[10,-10],[2,-1],[1,-1],[-2,-2],[-2,-2],[3,1],[4,1],[1,0],[2,-1],[1,-2],[0,-2],[-1,-2],[10,0],[3,-1],[1,-5],[-3,-4],[-1,1],[-2,1],[-1,0],[-5,-1],[-6,-5],[-4,-3],[-1,-3],[1,-6],[-1,-4],[-3,-2],[-6,2],[-3,1],[-3,2],[-3,2],[-4,4],[-2,0],[-1,-1],[2,-2],[3,-3],[4,-4],[2,-5],[-1,-2],[-2,0],[-1,0],[-4,1],[-3,0],[-9,-1],[-3,-1],[-1,1],[-1,2],[-4,1],[-3,1],[-2,0],[-1,2],[-3,3],[-5,1],[-3,1],[-2,-1],[7,-4],[5,-7],[-1,-1],[0,-1],[3,-1],[2,1],[0,-2],[-1,-7],[-1,-1],[-10,-2],[2,-1],[3,-1],[3,1],[2,-1],[2,-5],[0,-5],[-2,-2],[-3,-2],[-5,-4],[-6,-1],[-3,0],[-3,0],[-1,-2],[-1,-2],[2,1],[3,0],[3,-2],[0,-2],[-3,-2],[0,-1],[1,-3],[-1,-2],[1,-1],[3,0],[4,-2],[4,-2],[1,-1],[1,-3],[1,-2],[-1,-1],[-8,0],[-1,0],[-1,3],[-1,2],[-3,1],[-1,-1],[1,-8],[-1,-2],[-2,-2],[-4,-1],[-3,1],[-3,4],[0,3],[2,2],[0,2],[-1,3],[-2,-3],[-2,-3],[-3,-4],[-2,0],[-2,0],[-5,3],[-2,2],[-6,7],[-3,4],[-7,4],[-7,4],[-6,2],[-3,0],[-3,-1],[-4,0],[-1,1],[-2,2],[-1,1],[-5,5],[-4,3],[0,3],[1,3],[-1,7],[-2,7],[-4,7],[-13,4],[-11,3],[-3,1],[-4,-1],[-8,-5],[-6,-1],[-17,0],[-3,0],[-2,3],[-1,3],[1,6],[0,2],[-1,1],[-1,0],[-3,3],[-3,4],[-3,4],[-2,5],[3,0],[3,-1],[0,1],[1,5],[2,3],[1,2],[2,7],[0,4],[-3,-2],[-3,-7],[-2,-2],[-2,-1],[-1,0],[-3,1],[-2,2],[0,6],[-1,2],[-1,-1],[-1,-3],[-2,0],[-2,-1],[1,-4],[0,-3],[-3,-2],[-5,0],[-2,3],[-2,-5],[-1,-5],[0,-6],[2,-6],[2,-3],[5,-4],[3,-3],[0,-3],[0,-4],[-3,-4],[-2,-3],[-3,-8],[-2,-4],[-8,-6],[9994,-2],[-5,-7],[-5,-6],[-9,-2],[-12,-9],[-5,-1],[-7,4],[-15,2],[-4,4],[-7,9],[-2,1],[-2,4],[-9,3],[-7,-2],[-6,2],[-2,-2],[3,-1],[6,-1],[8,1],[3,-1],[2,-3],[3,-5],[-2,-4],[-2,-1],[-7,4],[-8,-1],[-3,1],[-10,6],[-8,-6],[-11,-4],[-8,0],[-15,-6],[4,0],[11,4],[6,0],[10,2],[5,3],[2,2],[3,2],[4,-1],[2,-2],[1,-4],[2,-4],[-2,-3],[-2,-1],[-2,-3],[10,5],[6,-3],[3,1],[6,5],[9,3],[2,-1],[1,-1],[-2,-10],[1,-7],[7,-8],[7,-5],[3,0],[2,1],[1,4],[2,3],[2,-3],[2,-3],[3,-8],[0,-2],[-1,-4],[2,-2],[4,-1],[1,-7],[1,-10],[-2,-1],[-1,0],[-5,-3],[0,-1],[6,-1],[1,-2],[-1,-5],[0,-2],[2,-1],[1,3],[0,4],[0,2],[4,-8],[0,-4],[3,-3],[8,-6],[2,-2],[0,-4],[-2,-1],[-2,-3],[2,-4],[2,-3],[3,-1],[2,-6],[0,-4],[-3,-5],[-5,-6],[-3,-2],[-1,-4],[0,-5],[-3,1],[-2,1],[-26,11],[-10,2],[-9,1],[-1,0],[0,3],[0,2],[2,3],[-1,3],[-1,0],[-1,-2],[-3,0],[-2,2],[-2,0],[-1,-3],[0,-2],[0,-2],[1,-2],[5,-2],[-1,-2],[-7,-1],[-6,-2],[-7,-5],[-3,-4],[-20,-9],[-5,-4],[-2,0],[-2,-1],[-3,-4],[-10,-6],[-3,1],[-3,-5],[-2,-2],[-7,-1],[-4,-1],[-9,-7],[-5,3],[-7,-10],[-7,-8],[-2,0],[-5,3],[-2,-2],[1,-3],[2,-4],[-1,-1],[-2,1],[-2,0],[-1,-1],[0,-2],[-3,-4],[-2,0],[-3,-1],[-1,-3],[1,-3],[-5,-4],[-4,-5],[-2,0],[-2,-3],[-3,-1],[-3,0],[-6,-6],[-15,-12],[-5,-2],[-5,-3],[0,-3],[0,-3],[-3,-4],[-2,-13],[-1,-2],[-1,-2],[-5,1],[-5,5],[-2,2],[-1,2],[0,4],[-1,2],[-1,1],[-5,10],[-10,7],[-1,2],[-12,-2],[-4,0],[-5,2],[-9,-1],[-11,-4],[-4,-2],[-11,-4],[-7,-6],[-14,-20],[-4,-5],[-1,-1],[-3,0],[-1,4],[0,4],[1,6],[2,5],[1,10],[1,4],[1,4],[-5,-1],[-6,-7],[-10,-7],[-5,-1],[-4,-5],[-2,0],[-3,-2],[-1,-8],[-1,-5],[-2,-1],[-3,0],[-2,1],[-3,8],[-4,3],[-2,1],[-2,-1],[-3,-5],[-4,-4],[0,5],[-3,2],[-3,1],[-4,0],[-1,-1],[-1,-3],[-3,-3],[-2,-2],[-3,-3],[-1,-3],[-1,-4],[-2,-11],[0,-12],[-5,-10],[-2,1],[-1,-1],[-1,-1],[2,-6],[-1,-2],[-1,-1],[-2,-1],[-6,-8],[-5,-6],[-9,-15],[-3,-10],[-2,-11],[1,-6],[1,-3],[2,-3],[3,-2],[5,-3],[0,-2],[0,-2],[2,3],[2,8],[3,3],[2,-1],[12,-6],[2,-3],[0,-6],[-1,-2],[-2,-5],[-4,-5],[-5,-6],[-1,-5],[0,-2],[2,-8],[0,-5],[-1,-8],[0,-4],[2,-3],[2,-2],[3,1],[3,-1],[3,-2],[0,-7],[1,-7],[1,-12],[-2,-4],[-2,-2],[-4,-5],[-2,-1],[-4,2],[-5,10],[2,5],[5,4],[2,3],[2,4],[-3,0],[-2,-2],[-5,1],[-3,-2],[-2,-4],[1,-8],[-2,-1],[-4,-3],[-5,-3],[-2,-3],[-4,-14],[-4,-11],[-2,-9],[1,-8],[1,-8],[1,-4],[5,-8],[2,-7],[1,-8],[-4,-3],[-7,-9],[-2,-1],[-10,0],[-4,5],[-6,-2],[-4,-2],[-7,-6],[-6,-8],[-6,-6],[-2,-3],[-3,-7],[-2,-13],[1,-7],[1,-3],[1,-4],[-1,-6],[0,-4],[3,-6],[0,-8],[-2,0],[-5,6],[-5,0],[-12,-7],[-6,-4],[-5,-8],[-2,2],[-1,4],[-2,2],[-3,-1],[-1,-4],[4,-2],[1,-3],[-2,-10],[-2,-4],[1,-10],[0,-4],[-1,-5],[-4,-12],[-6,-16],[-8,-12],[-5,-4],[-3,-3],[-1,-4],[-8,-11],[-10,-12],[-3,-2],[0,4],[-1,4],[-1,6],[-4,5],[0,4],[-1,6],[0,25],[-3,26],[0,8],[-4,7],[-2,7],[-2,7],[0,8],[-4,42],[-1,11],[-6,34],[-2,20],[-2,19],[0,9],[3,25],[2,16],[7,36],[1,4],[1,1],[13,14],[6,8],[3,8],[4,10],[-1,5],[0,3],[-2,4],[-3,4],[1,2],[2,1],[3,2],[6,-3],[7,1],[6,13],[8,-2],[7,2],[2,-1],[1,4],[3,5],[7,7],[10,8],[5,5],[2,6],[4,5],[4,6],[7,18],[14,16],[6,9],[4,3],[4,1],[10,13],[7,10],[8,7],[3,5],[4,11],[2,3],[5,4],[13,7],[7,7],[11,1],[3,3],[3,1],[4,3],[-5,6],[1,3],[1,2],[8,7],[3,6],[-1,3],[0,1],[-5,3],[1,5],[1,5],[4,4],[1,10],[1,9],[3,15],[3,3],[8,7],[2,0],[6,-2],[7,-1],[2,-3],[1,2],[-1,3],[2,1],[4,-1],[-1,2],[-9,2],[-7,3],[-7,6],[-4,1],[-4,0],[-26,-8],[-1,-3],[-1,-3],[1,-5],[-1,-2],[-1,-1],[-2,-3],[-1,-6],[0,-6],[-3,-9],[0,-6],[6,-3],[1,-2],[-2,-4],[-1,-1],[-2,-3],[-1,-1],[-1,0],[-2,3],[-2,6],[-3,0],[-1,-1],[-1,-2],[-2,0],[-3,1],[-3,-1],[-6,-7],[-32,-33],[-3,-4],[-4,-8],[-8,-1],[-3,-1],[-3,-3],[-3,-2],[0,3],[1,3],[1,6],[4,11],[-3,1],[-2,0],[-5,-2],[-4,-4],[-2,1],[1,3],[3,7],[-1,6],[-1,3],[2,2],[6,12],[2,7],[2,8],[0,3],[0,3],[-2,0],[-1,0],[-13,-8],[-5,-2],[-1,3],[-3,2],[-3,6],[-3,1],[-3,-1],[-7,-4],[-8,-2],[-6,1],[-5,-4],[-2,0],[-8,2],[-9,0],[-3,-3],[-7,-4],[-6,-6],[-3,-2],[-3,-3],[-1,-12],[-4,-4],[-4,-3],[-8,-9],[-6,-13],[-3,-5],[-8,-8],[-13,-10],[-11,-16],[-4,-12],[-1,0],[-3,-3],[-1,-6],[0,-4],[-1,-3],[-2,-4],[2,-3],[1,-1],[3,1],[6,3],[11,-5],[5,-5],[0,-5],[0,-5],[-4,0],[-5,0],[-4,-3],[-6,5],[-3,-2],[-3,-5],[-7,-2],[-3,3],[-6,6],[-9,-1],[-2,-7],[-2,1],[-4,-1],[-5,-8],[-2,-1],[-7,1],[-5,5],[-2,0],[-4,-2],[-2,-5],[-11,-3],[-10,1],[-6,12],[11,5],[6,-1],[7,0],[8,4],[-3,3],[-2,1],[-4,-1],[-4,3],[-9,11],[-4,2],[-5,2],[-4,0],[-1,-1],[-2,-3],[-1,-3],[-1,0],[-3,0],[-3,2],[-4,0],[2,1],[3,2],[-6,2],[-3,3],[-4,1],[-15,6],[-6,0],[-4,-2],[-6,-6],[2,-4],[1,-2],[1,-2],[-2,0],[-6,-1],[-4,4],[-2,-5],[1,-4],[4,1],[2,-2],[-1,-5],[-6,-1],[-6,0],[-7,9],[-10,-2],[-5,-5],[-5,-1],[-13,5],[-7,1],[-7,4],[-3,-1],[-5,-12],[-6,-3],[-3,2],[-3,7],[-2,3],[-6,2],[-29,-2],[-10,2],[-8,0],[-9,-4],[-9,1],[-17,-7],[-7,-5],[-9,-9],[-7,-15],[-4,-5],[-8,-7],[-10,-6],[-5,-7],[-3,-5],[-5,-20],[-2,-3],[-12,-7],[-4,-8],[-1,-2],[-6,-4],[-3,-5],[-1,-2],[-8,-4],[-6,-10],[-8,-7],[-12,-19],[-2,-3],[-1,-5],[-1,-4],[-11,-17],[-3,-1],[-6,-8],[-5,-5],[-5,-5],[-6,-6],[-9,-7],[-3,-4],[-5,-9],[-12,-11],[-6,-3],[-8,-10],[0,-2],[-1,-3],[1,-7],[2,-1],[3,-1],[12,-6],[11,1],[9,0],[4,1],[2,0],[1,-4],[0,-6],[-2,-6],[-1,-16],[-1,-8],[1,-7],[2,-1],[3,3],[3,0],[4,-1],[3,12],[-3,1],[-2,5],[2,3],[6,5],[4,1],[4,-1],[-4,-7],[-2,-1],[-1,-1],[-2,-1],[4,-4],[4,-4],[6,-1],[-1,-2],[-4,-3],[-4,-9],[-6,-4],[-2,-3],[1,-2],[2,0],[11,1],[6,2],[8,7],[4,11],[3,3],[1,0],[1,-1],[0,-7],[-4,-9],[-3,-4],[-2,-4],[2,0],[4,0],[2,2],[4,10],[1,8],[0,10],[0,6],[0,4],[-1,4],[1,2],[11,-6],[6,-2],[11,5],[2,-1],[2,-3],[9,-9],[2,-3],[3,-11],[9,-12],[9,-6],[0,-2],[6,-7],[4,-3],[1,-6],[-2,-5],[-4,-5],[-8,5],[-2,0],[1,-3],[6,-8],[5,-4],[0,-10],[0,-6],[-4,-7],[1,-4],[5,-5],[2,-3],[2,-3],[-3,-7],[0,-8],[-3,-3],[-4,-8],[-5,-6],[-3,-12],[-4,-10],[0,-11],[-1,-3],[-4,-11],[-1,-15],[2,-24],[1,-1],[1,-2],[0,-1],[-1,-1],[-3,-7],[0,-5],[1,-4],[0,-10],[-2,-15],[-1,-2],[-1,-4],[0,-4],[-1,-2],[0,-4],[0,-3],[2,-2],[-5,-11],[-1,-14],[-2,-6],[-3,-6],[-7,-8],[-2,-5],[-4,-7],[-4,-5],[-6,-15],[-5,-14],[-11,-19],[-2,-4],[-1,-5],[-3,-9],[-1,-11],[-4,-5],[-3,-12],[-9,-19],[-2,-6],[-8,-10],[-7,-15],[-10,-12],[-2,-6],[-3,-6],[-4,-9],[-6,-8],[-1,-6],[-2,-5],[-4,-3],[-4,-3],[-9,-24],[-1,-4],[0,-3],[-7,-9],[-3,-9],[-6,-6],[-6,-8],[-15,-14],[-4,-5],[-9,-7],[-3,0],[-7,-4],[-5,-4],[-3,2],[-2,4],[-2,0],[-1,0],[-5,4],[-3,0],[-3,2],[-5,-1],[1,20],[-1,5],[-2,-4],[-5,-8],[-3,-1],[-2,0],[1,4],[3,7],[-1,1],[-1,0],[-4,-3],[-2,-3],[-6,-12],[-3,-10],[-3,-3],[-1,-4],[-3,-4],[-3,1],[-2,-1],[-6,3],[-1,-1],[3,-8],[-2,-11],[-2,-2]],[[7991,9684],[-3,-3],[-3,-1],[-4,2],[-10,0],[-16,3],[5,1],[26,1],[1,0],[4,-3]],[[7951,9688],[-3,0],[-4,1],[1,3],[8,0],[3,4],[5,0],[2,-1],[1,-2],[0,-1],[-1,0],[-5,0],[-1,-1],[-6,-3]],[[7857,9749],[-3,-5],[-1,-4],[-8,-13],[-1,-2],[5,2],[4,4],[3,4],[3,2],[3,0],[4,1],[6,3],[7,2],[4,0],[3,-2],[2,-3],[3,-3],[8,-2],[2,-1],[0,-2],[0,-3],[5,-2],[7,1],[3,-1],[4,-1],[2,-3],[1,-2],[1,-4],[1,-4],[0,-6],[-14,-8],[-2,-1],[-6,1],[-7,-1],[-16,-5],[-20,0],[-5,-4],[-2,0],[-2,1],[-1,1],[-12,-1],[-14,0],[-14,0],[-4,-3],[-14,-6],[-13,-4],[-6,-1],[-10,1],[-3,2],[-3,2],[4,2],[3,6],[4,3],[10,6],[1,2],[1,6],[2,2],[1,1],[1,3],[0,3],[1,3],[4,4],[2,2],[3,0],[7,0],[3,0],[-2,1],[-1,5],[0,2],[1,3],[2,1],[2,1],[1,5],[-1,1],[3,2],[1,3],[3,1],[7,2],[0,3],[1,2],[2,1],[3,0],[2,0],[2,-3],[3,-3],[3,0],[4,0],[-3,3],[1,4],[1,2],[1,1],[4,0],[10,-2],[7,-4],[2,-2],[-1,-1],[-3,0],[-2,-1]],[[7117,9772],[4,-2],[2,1],[25,-5],[5,-2],[2,-1],[-22,-1],[-5,0],[0,3],[-5,0],[-8,2],[-3,3],[0,1],[3,1],[2,0]],[[7781,9769],[-6,0],[0,4],[1,1],[3,0],[2,-1],[4,0],[-4,-4]],[[7574,9774],[-7,-1],[-8,1],[-13,6],[-9,2],[-6,4],[-2,5],[4,2],[6,2],[9,0],[12,-1],[11,-3],[25,-3],[9,-2],[-6,-5],[-6,-2],[-6,-2],[-6,-2],[-7,-1]],[[6427,9788],[1,0],[0,-1],[-10,1],[-17,-1],[-10,4],[10,3],[6,0],[7,3],[9,-3],[0,-2],[0,-1],[2,-1],[2,-2]],[[6657,9789],[-10,-2],[-3,1],[-1,1],[-2,1],[-5,1],[1,3],[1,1],[15,4],[7,-3],[4,-5],[-7,-2]],[[7712,9801],[7,-4],[3,-4],[-3,-1],[-3,-3],[-1,-3],[-4,-3],[-1,-4],[2,-1],[2,1],[4,4],[5,3],[6,-2],[2,1],[4,4],[0,3],[1,2],[2,1],[8,-1],[11,-1],[3,-2],[2,-1],[2,-2],[5,-1],[3,-1],[4,-3],[3,-4],[-4,-2],[-2,-4],[-1,-1],[-1,-2],[0,-3],[-1,-3],[-1,-2],[0,-1],[0,-5],[-1,-3],[-4,-3],[-4,0],[-6,2],[-2,0],[-2,-1],[8,-4],[6,-5],[6,-2],[2,0],[2,-6],[1,-2],[-11,-6],[-3,-1],[-17,-1],[-11,-2],[-4,0],[-6,2],[-4,-1],[-6,1],[-4,0],[-8,2],[-9,4],[-2,2],[-2,1],[-10,1],[-2,1],[-16,-1],[-2,1],[-5,5],[-3,0],[-8,-3],[-3,0],[-7,2],[-4,2],[0,1],[0,3],[-4,2],[-5,5],[-3,5],[-12,3],[-8,1],[-6,-1],[-5,3],[9,7],[12,4],[5,4],[6,4],[3,6],[10,4],[3,2],[4,3],[1,0],[8,-4],[2,1],[1,2],[3,2],[10,0],[8,-1],[4,1],[3,0],[20,2],[13,1],[2,0]],[[6390,9796],[-3,-1],[-10,5],[-1,1],[9,4],[10,-1],[2,-2],[-7,-4],[0,-2]],[[6540,9807],[-7,-2],[-5,0],[-1,1],[3,3],[4,1],[3,0],[2,-1],[1,-2]],[[6585,9812],[1,-2],[0,-7],[-1,-3],[0,-3],[-3,-1],[-22,0],[-10,1],[-3,1],[6,3],[2,2],[0,7],[1,1],[17,0],[2,2],[6,0],[4,-1]],[[6486,9802],[-18,0],[-7,0],[0,1],[-2,0],[-6,1],[-3,3],[1,1],[9,1],[3,1],[1,2],[4,3],[9,0],[4,0],[0,-2],[4,-3],[10,-3],[-2,-2],[-3,-1],[-4,-2]],[[6609,9799],[-4,-1],[-11,2],[-2,1],[-2,2],[-1,8],[0,2],[-1,1],[-3,3],[-2,2],[2,1],[12,-1],[27,-1],[13,-2],[4,-2],[4,-3],[-23,-1],[-4,-1],[0,-3],[0,-3],[-3,0],[-6,-4]],[[6511,9819],[-4,-3],[-13,3],[1,2],[2,0],[0,2],[-2,1],[1,3],[8,-2],[1,-1],[6,-1],[1,-3],[-1,-1]],[[6317,9841],[13,-3],[9,1],[3,0],[3,-1],[3,-1],[4,-4],[0,-5],[-2,0],[-16,2],[-7,5],[-2,1],[-3,-2],[-3,-3],[-3,0],[-3,-4],[-3,0],[-1,0],[-4,-3],[-9,0],[-2,-1],[-3,-4],[-3,-1],[-7,-1],[-2,3],[-1,3],[-2,1],[-9,-1],[-7,1],[-6,2],[-7,1],[6,2],[33,5],[13,1],[7,4],[9,2],[2,0]],[[6726,9840],[2,-3],[-1,-3],[-2,-3],[-1,-4],[-9,-1],[-2,-1],[-3,-3],[-8,-1],[-7,-5],[-9,1],[-12,3],[-11,-3],[-7,0],[-8,4],[-1,1],[-1,3],[1,2],[2,6],[3,3],[1,1],[2,2],[3,1],[11,1],[4,-1],[1,-2],[5,0],[10,1],[13,2],[8,2],[7,0],[7,-1],[2,-2]],[[6396,9845],[4,-1],[11,0],[3,-1],[15,-8],[3,-1],[4,-3],[-16,-5],[-5,-3],[-19,-1],[-12,-2],[-3,-1],[2,-3],[-6,-3],[-19,0],[-3,-1],[-3,-3],[0,-1],[6,0],[1,-1],[1,-1],[1,-2],[-1,-3],[-3,0],[-2,0],[-6,2],[-1,-1],[-1,-1],[-1,-3],[-3,-1],[-6,2],[-2,0],[-2,-2],[-2,0],[-6,-1],[-3,2],[3,2],[7,4],[-2,1],[-7,1],[-6,-1],[-3,-2],[-2,-1],[-7,0],[-4,3],[-3,2],[-3,2],[21,8],[7,4],[7,1],[8,1],[3,1],[3,0],[2,0],[4,-3],[13,0],[3,3],[0,5],[-1,4],[2,6],[8,3],[17,3],[4,0]],[[7222,9841],[-26,-3],[-2,2],[-1,1],[4,4],[3,2],[16,1],[13,-2],[4,-1],[-1,-2],[-1,-1],[-9,-1]],[[6698,9846],[-9,-1],[-14,2],[-7,1],[0,1],[2,1],[12,4],[24,1],[4,-3],[-3,-2],[-9,-4]],[[6519,9856],[21,-6],[20,1],[8,-2],[12,-5],[18,-5],[4,-2],[-3,-2],[-21,-5],[-14,-2],[-12,0],[-5,0],[-5,4],[-12,3],[-12,-1],[-1,2],[-3,1],[-4,0],[-9,2],[0,3],[5,2],[4,0],[1,4],[6,8],[2,0]],[[6628,9852],[4,-3],[1,-4],[3,-2],[0,-3],[-2,-3],[-6,-1],[-10,0],[-9,1],[-5,6],[-10,1],[-5,6],[5,2],[7,-1],[11,5],[1,0],[3,-1],[9,-2],[3,-1]],[[6409,9852],[-4,0],[-2,0],[-3,2],[-1,1],[-1,1],[3,1],[1,1],[1,0],[2,1],[3,0],[5,-1],[2,-2],[-5,-3],[-1,-1]],[[6760,9832],[-5,0],[-6,1],[-6,3],[-7,3],[2,2],[6,2],[9,4],[13,1],[7,0],[7,1],[2,2],[1,4],[1,3],[2,1],[7,2],[6,0],[7,-2],[4,-1],[3,-3],[2,-2],[0,-3],[0,-3],[2,-2],[-12,-6],[-13,-4],[-32,-3]],[[7543,9857],[-10,-4],[-34,3],[-2,2],[0,1],[4,3],[29,-1],[10,-1],[3,-3]],[[7681,9854],[1,-3],[3,-2],[2,-2],[18,-7],[8,-1],[4,-1],[1,-2],[-1,-4],[-3,0],[-2,-1],[-12,-2],[-3,-2],[-3,-4],[2,-1],[1,-2],[4,-7],[1,-2],[3,-1],[-3,-3],[-3,-1],[-37,-4],[-25,-2],[-8,-1],[-3,0],[-7,-3],[-12,-4],[-6,0],[-18,6],[-23,4],[-3,3],[-5,1],[-7,1],[-3,5],[4,4],[6,3],[10,1],[9,2],[7,5],[4,5],[8,5],[-14,-1],[-5,1],[1,1],[3,4],[1,1],[5,2],[3,4],[9,2],[3,1],[4,-1],[7,2],[7,1],[7,1],[6,1],[7,1],[6,3],[3,5],[17,0],[3,-1],[2,-3],[3,-1],[3,0],[8,-5],[2,-1]],[[6647,9867],[-6,-1],[-11,1],[-3,2],[1,1],[7,2],[5,0],[6,-2],[3,-2],[-2,-1]],[[6605,9881],[2,-3],[4,-1],[12,-1],[3,-3],[-5,-1],[-14,-2],[1,-3],[3,-3],[-3,-3],[-4,-2],[-9,-2],[-8,3],[-9,3],[-5,-2],[-4,-2],[-4,1],[-5,2],[-13,-2],[-4,2],[-3,5],[9,1],[10,-1],[7,5],[9,2],[7,5],[3,1],[8,0],[2,1],[8,1],[2,-1]],[[6767,9884],[-3,0],[-18,0],[-9,2],[-1,1],[-11,1],[4,2],[15,1],[25,-2],[2,-1],[0,-1],[-4,-3]],[[6619,9890],[-10,-1],[-1,1],[0,1],[1,1],[1,3],[4,2],[32,1],[4,-1],[-2,-3],[0,-1],[-29,-3]],[[5847,5122],[-1,-1],[0,-2],[1,-5],[3,-9],[2,-2],[2,-3],[1,-6],[1,-8],[-1,-9],[1,-7],[1,-4],[0,-6],[0,-7],[-1,-4],[-1,-1],[-1,-1],[-1,1],[-2,-1],[-2,-1],[-1,0]],[[5821,5104],[1,0],[6,3],[1,-1],[0,-6],[1,-1],[1,0],[1,1],[4,5],[1,3],[2,4],[2,4],[1,4],[1,2],[1,1],[2,-1],[1,0]],[[4526,6382],[-1,3],[2,30],[0,3]],[[6166,6147],[2,-1],[-1,2],[0,1],[1,3],[3,-6],[0,-6],[-1,-2],[0,2],[-1,1],[0,1],[-1,2],[-3,-1],[-2,2],[-2,5],[-1,4],[1,1],[1,2],[1,3],[-1,3],[2,0],[1,-4],[0,-7],[0,-2],[0,-1],[1,-2]],[[6024,6646],[-2,4],[-1,3],[-2,2],[-5,3],[-1,3],[1,2],[1,-2],[1,-2],[4,-3],[5,-8],[1,0],[-2,-2]],[[6016,6665],[0,-1],[-1,2],[0,5],[1,2],[0,-3],[0,-4],[0,-1]],[[6345,6828],[2,-6],[0,-5],[3,-13],[4,-10],[1,-3],[1,-6],[-1,-2],[0,-2],[3,-6],[5,-4],[2,-2],[2,-2],[-2,-3],[3,-7],[4,-8],[3,-1],[5,-12],[8,-7],[4,-9],[0,-1],[-1,1],[-2,2],[-1,-2],[1,-4],[0,-4],[2,-4],[2,-3],[1,-6],[-1,-12],[-1,0],[-1,1],[-1,0],[-1,0],[2,-9],[1,-6],[2,-6],[1,-7],[1,-4],[5,-8],[1,-7],[2,-12],[3,-7],[1,-6],[3,-4]],[[6423,6601],[2,-2],[2,0],[1,-2],[-2,-3],[-1,-8],[2,-1],[2,-1],[2,-1],[1,0]],[[6443,6278],[-6,-2],[-7,-2],[-7,-2],[-8,-2],[-7,-2],[-10,-3],[-9,-2],[-8,-2],[-8,-3],[-7,-2],[-4,-2],[-5,-5],[-8,-8],[-8,-7],[-4,-4],[-4,-11],[-2,-5],[-4,-9],[-3,-8],[-3,-8],[-1,-8],[-3,-12],[-2,-3],[-3,-3],[-3,-3],[-5,0],[-2,8],[-3,7],[-2,3],[-1,0],[-5,-1],[-5,-1],[-7,2],[-8,1],[-7,1],[-3,1],[-5,5],[-1,1],[-2,1],[-5,0],[-6,0],[-5,-2],[-6,1],[-5,-1],[-2,-2],[-2,0],[-2,-2],[-1,0],[-1,1],[-2,0],[-2,1],[-2,3],[-2,3],[-1,2],[-2,1],[-2,0],[-2,-2],[-1,-2],[-3,-5],[0,-2],[1,-4],[0,-1],[-2,-2],[0,-6],[-1,-2],[0,-7],[1,-6],[1,-2],[0,-2],[-1,-5],[-1,-1],[-1,-5],[-1,-2],[-2,-2],[-5,-8]],[[6188,6127],[0,4],[-2,7],[0,5],[-1,5],[-1,4],[-3,3],[0,6],[-2,5],[-2,4],[-2,8],[-1,10],[-6,14],[-9,12],[-2,7],[-5,14],[-2,12],[-5,13],[-1,5],[0,6],[-2,7],[0,5],[-6,23],[-2,4],[-2,5],[0,4],[0,3],[-4,4],[-4,9],[-11,16],[-6,2],[-4,5],[-3,8],[-4,12],[-6,14],[-5,19],[2,7],[0,5],[-2,9],[-1,6],[-2,6],[1,9],[1,10],[1,5],[0,6],[-1,11],[-1,6],[0,4],[-2,2],[-2,5],[2,0],[-3,6],[-1,3],[-1,9],[-1,6],[-5,15],[-2,9],[-5,11],[-5,9],[-4,3],[-1,4],[-3,0],[-3,5],[-2,0],[-3,1],[-3,10],[-2,9],[-5,11],[1,3],[2,5],[-1,7],[-1,4],[-2,9],[-6,20],[-2,3],[-2,3],[-2,9],[-1,8],[-4,3],[-8,29],[-4,9],[-2,7],[-5,11],[-2,11],[-5,10],[-5,17],[-6,18],[-3,3],[-7,1],[-3,1],[-3,-4],[0,5],[2,7],[3,14],[0,12],[4,37]],[[6024,6451],[0,-13],[1,-11],[4,-15],[4,-8],[1,-4],[0,-2],[0,-2],[-1,2],[-2,1],[0,-7],[1,-5],[0,-9],[1,-10],[-1,-9],[1,-16],[1,-19],[0,-12],[3,-29],[3,-15],[2,-4],[2,-2],[3,-1],[6,-8],[4,-9],[2,-4],[2,-5],[1,1],[1,1],[1,-4],[7,-8],[1,-4]],[[5946,5729],[-5,0],[-1,1],[0,1],[0,3],[0,4],[1,6],[2,7],[0,1],[0,2],[-1,1],[0,1],[1,4],[0,1],[0,2],[0,1],[-2,6],[0,1],[-12,21],[-2,5],[-1,0],[0,1],[-6,4],[0,1],[0,1],[1,3],[0,1],[0,1],[-3,42],[0,1],[0,1],[1,1],[0,1],[0,2],[1,8],[0,7],[1,11],[1,4],[-14,1],[0,-1],[0,-1],[0,-2],[0,-1],[0,-3],[1,-2],[0,-1],[0,-1],[-19,-1],[8,-16],[0,-1],[0,-1],[0,-6],[0,-10],[0,-6],[0,-3],[2,-8],[0,-1],[0,-2],[-14,-23],[0,-1],[-2,-10],[-1,-5],[-1,-2],[-3,-7],[-12,-25],[-2,-1],[-6,-1],[-3,0],[-1,0],[0,-1],[-1,-1],[-1,1],[-7,14],[-13,17],[-1,-2],[-8,-7],[-1,-2],[-1,-1],[0,-9],[-2,-4],[-2,-5],[-6,-2],[-4,-3],[-3,-4],[-1,-1],[-1,-2],[-2,-5],[-1,-4],[1,-4],[-22,0],[-2,3],[-3,13],[-2,-1],[-21,2],[-2,-2],[-6,-5],[-3,-1],[-3,2],[-11,26],[-2,3],[-1,1],[-1,5],[-3,3],[0,1],[-1,3],[0,6],[0,3],[-2,1],[-14,-6],[-2,1],[-3,-1],[-1,-1],[-1,-4],[-1,-3],[0,-4],[0,-3],[-1,-4],[-4,-8],[-1,-4],[0,-10],[0,-4],[-1,-3],[-2,-3],[0,-2],[0,-3],[-1,-7],[0,-2],[-2,-8],[-1,-2],[0,-6],[0,-1],[-7,-5],[-2,-2],[-1,-4],[-1,-2]],[[5634,5813],[1,6],[2,9],[0,5],[-1,4],[-2,4],[-2,0],[-1,2],[-1,2],[-2,2],[-1,4],[-1,5],[1,18],[-1,3],[-2,1],[0,1],[0,3],[-1,11],[-2,9],[1,4],[-2,7],[-3,3],[-3,-1],[-3,-1],[-2,0],[-2,1],[-1,3],[0,3],[0,4],[2,8],[2,6],[5,6],[1,3],[1,4],[0,4],[0,4],[-1,4],[-1,5],[-1,6],[0,4],[0,3],[1,3],[3,4],[0,1],[2,2],[1,1],[4,5],[1,2],[-1,2],[-1,2],[-1,3],[0,3],[-1,6],[0,3],[-1,3],[1,2],[2,3],[1,1],[3,2],[1,2],[1,4],[-1,3],[1,3],[2,6],[1,2],[2,3],[1,4],[1,4],[0,5],[-1,12],[3,6],[2,4],[4,0],[6,1],[4,2],[3,0],[7,-3],[0,1],[1,4],[0,8],[0,26],[0,26],[0,25],[0,26],[0,26],[0,25],[0,26],[0,26]],[[5943,5427],[-6,-14],[-5,-10],[-1,-1],[-1,-2],[-5,0],[-5,1],[-4,6],[-4,-4],[-3,-2],[-2,0],[-4,-1],[-5,-3],[-3,-3],[-1,-2],[-1,-5],[-1,0],[-1,0],[-1,2],[-3,3],[-2,5],[-1,4],[-1,2],[-5,-6],[-2,-1],[-2,0],[-4,3],[-3,3],[-2,0],[-3,-4],[-3,-5],[-2,-5],[-1,-3]],[[4535,5895],[-1,3],[-1,4],[1,3],[2,2],[4,3],[2,-2],[1,0],[0,2],[-1,1],[-2,2],[-1,3],[-2,-2],[-1,-3],[0,-1],[-2,-1],[0,2],[-1,3],[1,1],[0,11],[0,5],[0,5]],[[4539,5966],[0,6],[-2,5],[-3,4],[0,4],[1,3],[2,3],[1,2],[-1,-1],[-3,-1],[-1,-1],[0,6],[-2,6],[-3,11],[-3,5],[-2,9],[-3,4],[-2,1],[-2,0],[-1,-4],[-3,6],[4,2],[7,7],[9,22],[7,25],[1,6]],[[7887,5260],[-4,-3],[-5,3],[2,6],[3,1],[3,-2],[1,-1],[1,-2],[-1,-2]],[[4270,1818],[0,-3],[-4,3],[-1,1],[1,2],[3,0],[1,-1],[0,-2]],[[3969,2070],[3,-3],[2,2],[2,0],[1,-1],[1,-1],[2,0],[3,-4],[-1,-5],[3,1],[2,-3],[1,0],[1,1],[2,2],[1,-2],[1,-4],[2,-2],[1,-4],[2,-5],[1,-1],[2,0],[2,1],[-1,-5],[0,-4],[3,-3],[-2,-2],[-2,-3],[-4,-1],[-1,0],[-3,5],[-2,5],[-4,7],[-1,2],[0,1],[-4,1],[-3,2],[-2,3],[-1,2],[-1,2],[-3,0],[-2,2],[-3,2],[-9,7],[-4,-1],[-1,2],[0,3],[2,2],[-9,1],[-2,1],[2,1],[11,0],[4,0],[1,-1],[3,-3],[4,0]],[[4841,4262],[-2,0],[0,3],[2,3],[1,-1],[0,-3],[-1,-2]],[[4601,4724],[-1,0],[-1,1],[0,1],[1,2],[0,2],[1,0],[1,-2],[0,-1],[0,-1],[-1,-2]],[[9636,4512],[-2,-1],[-1,0],[-2,5],[1,1],[2,0],[0,-3],[2,-2]],[[9460,4504],[-2,-2],[-2,1],[-2,2],[-1,4],[-2,3],[-3,1],[-2,2],[0,1],[-2,1],[-1,2],[0,3],[1,1],[2,-1],[10,-12],[2,-3],[2,-3]],[[9614,4564],[-2,-1],[-1,0],[-2,0],[-2,-4],[-1,0],[-1,0],[-1,4],[0,1],[2,0],[0,3],[2,2],[3,1],[3,-1],[1,-1],[-1,-3],[0,-1]],[[9491,4586],[4,-4],[2,1],[3,-3],[2,2],[1,-3],[4,-12],[0,-4],[2,-3],[-2,0],[-2,1],[-3,-1],[-2,3],[-4,1],[-3,3],[-7,8],[0,5],[-1,2],[0,5],[-3,2],[-3,0],[0,3],[1,4],[2,0],[2,-2],[5,-6],[2,-2]],[[9486,4629],[1,-6],[0,-2],[-2,5],[-1,-2],[-1,2],[0,5],[0,5],[-1,4],[-1,5],[2,-1],[3,-15]],[[9437,4650],[6,-10],[2,1],[8,0],[5,-6],[3,-4],[1,-5],[2,-2],[2,-3],[0,-5],[0,-1],[-3,-2],[-1,-1],[-5,2],[-5,4],[-8,1],[-5,1],[-1,1],[-1,3],[-2,5],[-2,6],[0,3],[0,7],[0,2],[2,3],[2,0]],[[9448,4666],[2,-1],[1,0],[1,-3],[3,-5],[-1,-2],[-2,1],[-1,0],[0,2],[-3,3],[-2,0],[0,2],[2,3]],[[9421,4658],[-2,1],[-1,0],[-1,2],[1,3],[1,2],[1,-1],[1,-1],[1,0],[0,-4],[-1,-2]],[[9378,4679],[0,-2],[-2,1],[-3,3],[0,1],[2,1],[1,-1],[1,-1],[1,-2]],[[9394,4676],[-1,-1],[-1,3],[2,6],[1,-5],[0,-2],[-1,-1]],[[9391,4684],[-3,-5],[-2,2],[-1,3],[0,5],[0,1],[1,1],[1,1],[1,2],[3,-2],[1,-1],[-2,-3],[0,-1],[1,-1],[0,-2]],[[9371,4682],[0,-1],[-2,2],[-3,7],[1,3],[3,5],[1,1],[1,-3],[-1,-5],[-1,-1],[-1,-4],[2,-4]],[[9435,4694],[-1,-1],[-2,2],[-1,2],[0,3],[1,1],[2,-2],[0,-2],[1,-3]],[[9464,4705],[7,-17],[0,-3],[-1,-2],[0,-6],[1,-2],[1,-1],[4,-6],[1,-8],[0,-2],[1,-4],[0,-7],[4,-10],[0,-5],[-1,-2],[-1,1],[-3,12],[-5,5],[0,2],[-4,6],[-3,11],[-3,20],[1,5],[-3,10],[0,2],[2,0],[1,0],[0,1],[1,0]],[[9381,4709],[2,-5],[2,-10],[0,-4],[-2,0],[0,-2],[-2,5],[-3,1],[-1,3],[-1,7],[0,3],[-2,1],[-4,-1],[-1,-3],[-2,1],[-1,3],[1,3],[2,3],[1,3],[2,7],[2,1],[3,-2],[0,-9],[1,-3],[3,-2]],[[9349,4713],[0,-1],[-2,7],[0,3],[1,3],[1,-8],[0,-4]],[[9365,4717],[-1,-1],[-3,0],[-2,6],[0,5],[2,4],[2,0],[1,-1],[1,-4],[1,-4],[-1,-4],[0,-1]],[[9352,4727],[-1,0],[-1,3],[-1,1],[0,3],[-2,6],[-1,4],[2,4],[2,-3],[2,-4],[3,-2],[-1,-3],[-2,-6],[0,-3]],[[9440,4692],[0,-1],[-4,5],[-2,6],[-8,6],[-2,3],[-2,1],[-4,5],[-4,4],[-2,4],[-1,2],[-1,1],[-3,5],[-2,4],[-1,6],[-3,4],[0,2],[7,-3],[4,-7],[3,-4],[1,-3],[3,-3],[2,-1],[3,-4],[2,-1],[2,-2],[11,-17],[-1,-4],[1,-4],[1,-4]],[[9328,4775],[-3,-1],[-2,1],[1,5],[1,2],[4,-4],[-1,-3]],[[9374,4762],[1,-2],[-3,-4],[-2,2],[-1,2],[0,1],[-2,-1],[-4,2],[-5,8],[-6,16],[-6,8],[-1,3],[0,4],[1,2],[3,-2],[5,-7],[7,-7],[2,-4],[1,-9],[2,-3],[4,-7],[2,-1],[1,0],[1,-1]],[[4652,5612],[-1,-1],[-2,3],[-9,6],[2,3],[7,1],[2,-2],[1,-1],[0,-3],[0,-6]],[[4680,5582],[-1,2],[-5,8],[-6,6],[-11,9],[-4,2],[0,3],[1,6],[-2,7],[1,5],[-1,0],[-2,-3],[-3,1],[-3,5],[-1,1],[-1,2],[-1,12],[-1,5],[-2,3],[-4,1],[-1,7],[-2,5],[0,4],[2,-1],[1,-2],[2,-1],[3,6],[2,3],[0,3],[0,1],[-1,-2],[-4,1],[-1,-3],[-2,0],[-1,7],[0,4],[1,4],[3,1],[1,1],[-3,1],[-3,5],[-1,4]],[[2560,5956],[0,-1],[0,-6],[-1,-3],[-2,-3],[-2,-1],[-5,0],[-6,3],[-5,4],[-3,0],[1,-1],[2,-1],[3,-3],[-1,-1],[-10,6],[-11,11],[-7,2],[-8,3],[-4,7],[-4,3]],[[6359,5832],[0,-16],[0,-15],[0,-16],[0,-27],[0,-9],[0,-14],[0,-7],[-4,-12],[-5,-16],[-5,-16],[-5,-14],[-4,-13],[-4,-13]],[[6201,5846],[5,-9],[5,-18],[7,-14],[8,-13],[3,-5],[3,-2],[16,0],[11,12],[10,9],[3,2],[6,-2],[6,-1],[6,-3],[3,1],[11,10],[7,10],[5,4],[2,0],[7,-3],[8,1],[12,9],[4,2],[2,0],[7,-4],[1,0]],[[6359,5832],[3,1],[9,4],[7,6],[13,5],[10,11],[2,6],[3,7],[4,2],[11,-8],[2,-1],[-1,-5],[0,-5],[-2,-9],[-2,-9],[1,-15],[1,-24],[0,-4],[-1,-3],[0,-3],[-2,-1],[0,-2],[1,0],[3,2],[0,3],[0,2],[3,-3],[2,-2],[1,-3],[0,-2],[-4,1],[-1,2],[-5,-3],[-3,-3],[-1,-5],[0,-19],[-2,-12],[0,-16],[-4,-11],[-1,-8],[-6,-15],[-3,-13],[-1,-6],[-5,-18],[-7,-14],[-2,-17],[-3,-11],[-3,-10],[-6,-18],[-3,-12],[-4,-21],[-1,-14],[-11,-39],[-12,-31],[-7,-26],[-13,-31],[-17,-39],[-23,-47],[-7,-9],[-25,-29],[-16,-24],[-8,-17],[-9,-14],[-7,-13],[-21,-46],[-2,-5],[-2,-4],[-3,-7],[-2,-4],[-5,-13],[-3,-7],[-4,-6],[-1,-5],[-1,-5],[-1,-4],[-3,-13],[-3,-8],[-3,-7]],[[3440,7877],[-1,0],[-2,1],[1,1],[1,1],[1,0],[0,-1],[0,-1],[0,-1]],[[3437,7882],[-3,-3],[-1,2],[1,1],[1,4],[0,1],[-2,8],[1,1],[0,1],[2,-2],[0,-2],[-1,-5],[1,-3],[1,-2],[0,-1]],[[5184,5191],[-2,-4],[-1,1],[-1,3],[-1,6],[0,3],[2,3],[3,4],[1,0],[2,-4],[0,-5],[-3,-7]],[[5206,5274],[-1,-1],[-2,1],[0,2],[2,5],[0,1],[1,-1],[0,-1],[0,-2],[0,-4]],[[3411,5503],[0,-1],[1,7],[1,5],[0,6],[2,6],[2,3],[14,-3],[7,-3],[8,-5],[1,-6],[0,6],[0,5],[2,4],[5,2],[7,-2],[7,2],[8,0],[14,-5],[6,-3],[2,-3],[1,-5],[-1,-6],[-1,-6],[-2,-9]],[[5626,8010],[-1,-2],[-1,-3],[-1,-3],[-2,-3],[-1,-8],[-1,-3],[-4,-7],[-1,-9]],[[5377,7806],[1,1],[3,3]],[[5459,8426],[-2,-3],[-1,0],[-1,4],[0,10],[0,5],[6,18],[3,1],[4,11],[1,5],[2,4],[1,4],[0,2],[2,-1],[1,-1],[-2,-2],[0,-3],[0,-1],[-5,-13],[-1,-8],[-1,-2],[-7,-30]],[[5529,8515],[-2,-1],[-1,-4],[-2,-1],[-2,-1],[-1,-13],[4,-5],[-2,-1],[-2,-1],[-1,-2],[-1,-5],[-5,-3],[-1,-2],[-3,-4],[-1,-6],[-3,-3],[-2,-1],[1,5],[2,5],[-2,3],[-1,4],[-2,4],[2,3],[-1,7],[0,6],[2,3],[2,3],[4,6],[3,4],[6,2],[2,-2],[1,4],[1,1],[2,-1],[3,-4]],[[5532,8520],[-1,-4],[-1,1],[-2,2],[3,4],[4,0],[1,-1],[-4,-2]],[[5511,8584],[-1,-1],[-1,0],[1,3],[0,1],[2,1],[1,0],[-2,-4]],[[5516,8609],[-1,-2],[0,3],[0,2],[2,2],[2,-1],[0,-1],[-2,-2],[-1,-1]],[[5670,8974],[-7,-1],[-5,2],[-3,-1],[-5,0],[-6,-1],[-1,-2],[-2,-1],[-5,3],[-5,5],[-3,-4],[-2,-1],[-3,4],[-1,0],[-1,-1],[-1,-3],[-1,-2],[-1,-2],[0,-6],[0,-1],[-5,1],[0,-2],[1,0],[1,-1],[-2,-2],[-5,0],[0,-1],[1,-2],[-1,-2],[-1,-1],[-5,-1],[-4,0],[0,-1],[-1,-2],[1,-1],[1,-1],[1,-1],[0,-2],[-1,-1],[-4,4],[-1,0],[1,-2],[2,-2],[1,-2],[1,-3],[0,-2],[-4,-7],[-4,-4],[-3,-3],[-1,-4],[1,-2],[3,-3],[1,-6],[2,-5],[3,-4],[0,-3],[-1,-2],[-6,-5],[-7,-7],[-7,-18],[-2,-2],[-6,-3],[-3,-3],[-4,-3],[-8,-3],[-4,-5],[-2,-4],[-2,0],[-1,2],[-3,1],[0,-3],[0,-2],[-4,3],[-2,-3],[-1,-4],[-6,-7],[-6,1],[-1,-1],[2,-1],[0,-1],[-1,0],[-1,0],[-3,-1],[-2,0],[-1,-3],[-1,-4],[-3,-1],[-2,-1],[-1,-2],[5,0],[0,-2],[0,-2],[-1,-1],[-6,-3],[-1,-2],[-1,-2],[-2,0],[0,2],[0,1],[-4,0],[-1,3],[-1,-1],[1,-2],[1,-3],[1,-4],[-1,-2],[-1,-1],[1,-1],[2,-1],[0,-2],[-2,-1],[-3,-4],[-3,0],[-2,-3],[-2,0],[-2,2],[-3,1],[-1,-2],[0,-3],[2,-5],[3,-4],[2,-2],[-2,-1],[-1,-3],[-2,-8],[-1,-3],[-1,-6],[1,-5],[0,-2],[2,-3],[-4,0],[-4,2],[1,-4],[-3,-5],[1,-4],[0,-2],[0,-5],[1,-1],[0,-3],[-1,-2],[1,-1],[0,-6],[1,-10],[-1,-1],[2,-9],[0,-2],[0,-4],[3,-3],[2,0],[3,0],[1,-1],[1,-3],[1,-2],[2,0],[4,2],[2,1],[2,-5],[4,-6],[2,-2],[5,-2],[4,-5],[-1,-5],[2,-2],[5,-3],[2,-3],[1,-2],[1,-3],[2,-6],[-1,-4],[-2,-2],[-5,-4],[-2,-3],[-1,-2],[-5,-5],[-2,0],[-2,-3],[-2,-1],[-1,1],[-6,-4],[1,-2],[4,-1],[2,1],[2,2],[2,1],[1,-1],[2,2],[2,1],[1,-1],[2,-4],[-4,-2],[-2,0],[-1,-7],[-2,-2],[-1,-2],[-5,-2],[-3,-4],[-4,-3],[-2,1],[-3,-3],[-6,-3],[-3,-5],[-6,-4],[-4,-3],[-9,0],[-9,1],[-3,-2],[3,0],[2,-2],[2,1],[6,-1],[3,-1],[4,-5],[-3,-2],[-5,-1],[2,-8],[1,-5],[-2,-3],[0,-14],[-3,-1],[-1,-5],[1,-3],[0,-7],[1,-4],[1,-4],[-1,-4],[-4,-10],[0,-4],[1,-3],[1,-4],[-2,-8],[-2,-7],[-1,-6],[-4,-7],[-2,-5],[-4,-16],[-2,-3],[-3,-2],[-3,2],[-2,1],[-4,0],[-5,-2],[-7,1],[-8,0],[-2,-2],[1,-6],[-2,-1],[-3,2],[-3,-2],[-1,-2],[-4,-5],[-2,-3],[0,-6],[2,-6],[2,-6],[-5,-7],[-2,-1],[-8,2],[-13,-4],[-13,3],[2,4],[0,3],[1,5],[0,5],[0,3],[-1,3],[-3,5],[-7,14],[-2,6],[-1,3],[1,0],[5,-3],[2,0],[1,2],[-2,4],[-1,2],[-1,4],[3,1],[3,-1],[1,4],[-1,6],[-2,2],[-2,0],[-4,10],[-4,5],[-8,18],[-3,13],[-2,-2],[-2,6],[0,5],[-1,4],[-4,2],[0,3],[0,12],[-5,2],[-2,6],[-1,13],[-3,2],[-2,0],[0,3],[1,3],[-2,12],[0,10],[-1,4],[-1,3],[1,4],[0,2],[3,0],[3,-3]],[[5891,3638],[0,1],[-2,1],[-1,-1],[-1,-8],[0,-12],[0,-8],[-6,0],[-7,1],[-6,3],[-6,7],[-3,11],[-2,8],[-2,0],[0,1],[0,9],[0,9],[0,2],[4,12],[2,7],[2,6],[3,8],[4,5],[1,1],[1,0],[6,-7],[7,-7],[1,1],[1,1]],[[3249,6225],[0,-2],[0,-1],[-2,1],[-1,1],[0,1]],[[6542,4913],[0,-5],[-1,2],[-1,3],[-1,3],[-1,2],[2,3],[2,-8]],[[5999,7178],[-2,13],[-1,6],[0,6],[2,10],[-1,4],[0,3],[0,4],[-4,9],[2,16],[1,4]],[[5996,7253],[3,-1],[4,-4],[1,0],[1,6],[1,2],[3,2],[1,9],[1,2],[2,1],[2,0],[2,1],[0,2],[-3,11],[1,3],[1,11],[1,4],[1,2],[3,-1],[5,-2],[1,-3],[2,-3],[3,0],[4,0],[3,-1],[3,2],[5,4],[3,1],[2,2],[8,6],[3,0],[3,-1],[1,-1],[4,-4],[3,-4],[2,-2],[4,0],[6,0],[7,0],[4,1],[5,2],[9,5],[12,10],[7,6],[3,0],[4,0],[4,-1],[5,-1],[2,0],[5,1],[6,2],[4,2],[5,3],[3,5],[1,0],[1,-1],[1,0],[1,-3],[1,-7]],[[2990,6442],[4,-3],[2,1],[0,-1],[-1,-1],[-1,0],[-3,-1],[-1,0],[0,2],[0,3]],[[3009,6437],[-2,2],[-3,0],[0,3],[1,0],[4,-1],[1,-2],[-1,-2]],[[3003,6442],[0,-1],[-2,2],[0,2],[-1,0],[-1,1],[0,2],[3,0],[0,-5],[1,-1]],[[5045,5542],[-9,-4],[-4,-3]],[[7768,5559],[-1,0],[-1,5],[1,7],[2,-9],[-1,-3]],[[7751,5621],[1,-7],[-1,2],[-1,3],[0,4],[0,1],[1,-3]],[[7738,5641],[0,-1],[-2,11],[2,-3],[0,-7]],[[7733,5639],[0,-4],[-2,0],[-1,-3],[-1,8],[1,12],[0,2],[1,-3],[3,-1],[-1,-7],[0,-4]],[[7730,5705],[-2,0],[1,3],[0,2],[1,0],[0,-3],[0,-2]],[[7779,5736],[0,-3],[-1,-4],[-2,-3],[-1,4],[0,4],[1,2],[2,-1],[1,1]],[[7779,5742],[0,-1],[-1,2],[-1,2],[0,3],[1,0],[1,-3],[0,-3]],[[7849,5856],[0,-6],[-2,3],[1,3],[0,1],[1,-1]],[[7844,5874],[0,-1],[-1,1],[-2,0],[-1,8],[0,2],[1,-1],[2,-4],[1,-3],[0,-2]],[[7858,5858],[-1,4],[-2,7],[-1,7],[-3,8],[-2,3],[0,-3],[-1,-3],[-3,4],[-3,5],[-2,8],[-1,-2],[0,-2],[-3,6],[-2,6],[-3,1],[-2,2],[-1,3],[-3,3],[-8,-4],[-10,3],[-4,-3],[-1,2],[-1,3],[1,6],[0,13],[1,8],[0,7],[0,3],[1,4],[-2,2],[-7,4],[-1,2],[-2,-3],[-8,-2],[-4,-2],[-3,-5],[0,-6],[1,-5],[2,-7],[-3,-16],[-1,-4],[1,-20],[0,-10],[-2,-7],[-3,-7],[-1,-10],[-2,-6],[-2,-11],[-2,-14],[-1,-7],[-1,-12],[-6,-18],[-1,-11],[-2,-4],[1,-3],[0,-5],[-1,-14],[0,-12],[1,-6],[2,-12],[0,-3],[-1,-6],[3,-2],[1,-1],[9,6],[3,-1],[2,-6],[0,-4],[2,-26],[1,-4],[2,-5],[2,-5],[0,1],[0,2],[1,2],[1,-5],[2,-9],[5,-48],[1,-6],[1,-6],[-3,3],[-1,11],[0,4],[-1,1],[-2,0],[0,2],[1,3],[0,4],[-2,4],[-3,-3],[0,-7],[2,-6],[4,-13],[2,-5],[2,-2],[2,1],[3,-5],[3,-5],[6,-8],[4,1],[4,2],[3,-1],[3,-2],[3,-6],[5,-16],[8,-14]],[[7780,5555],[-7,18],[-4,7],[0,13],[-1,3],[-2,0],[-1,4],[1,7],[-2,-1],[-3,0],[-2,2],[-1,11],[-1,4],[-3,5],[-3,0],[-1,3],[1,7],[-2,4],[-3,4],[-3,2],[-2,11],[-2,3],[-1,2],[-3,-1],[0,-4],[-2,-4],[-2,0],[-1,3],[-2,11],[0,7],[0,13],[3,11],[1,19],[2,12],[1,4],[2,15],[4,21]],[[6962,7542],[-1,0],[-1,2],[-1,2],[1,1],[1,-2],[1,-2],[0,-1]],[[6882,7325],[1,4],[0,14],[1,5],[5,8],[2,7],[2,5],[2,2],[1,4],[2,5],[0,3],[0,3],[-1,1],[-2,4],[-3,5],[-1,5],[-1,6],[0,5],[2,13],[0,2],[-1,2],[-2,1],[-2,1],[-2,-1],[-3,0],[-2,1],[-1,1],[0,5],[-1,2],[0,1],[-6,2],[-2,2],[0,1],[2,13],[1,1],[1,2],[1,2],[5,4],[6,-2],[4,-1],[5,-1],[2,-1],[2,0],[2,0],[1,2],[2,4],[1,6],[1,5],[1,1],[2,-1],[0,1],[1,2],[0,1],[0,1],[1,-2],[1,0],[0,1],[0,2],[-1,1],[-1,4],[0,1],[1,1],[2,1],[2,0],[0,1],[0,2],[-1,1],[-4,-1],[-4,0],[-1,1],[1,1],[0,1],[9,3],[4,-1],[3,-1],[2,0],[-2,5],[2,1],[0,2],[-2,13],[1,2],[2,2],[0,5],[1,3],[1,2],[3,-2],[3,-5],[2,-1],[1,0],[1,1],[7,5],[4,3],[4,4],[1,2],[1,6],[1,0],[1,0],[4,-7],[2,-4],[0,-1],[-1,-1],[1,-1],[3,-3],[0,-1],[-1,-2],[0,-1],[-1,0],[-4,-6],[-5,-6],[0,-1],[0,-2],[0,-1],[1,-1],[2,-1],[2,-2],[0,-3],[1,-3],[2,-1],[7,2],[1,0]],[[6475,7419],[-1,-3],[-1,8],[-1,9],[1,3],[1,0],[-1,-4],[2,-13]],[[6497,7335],[0,4],[-2,15],[-1,14],[0,7],[1,14],[0,7],[0,6],[0,6],[1,7],[0,7],[0,5],[-2,4],[-2,5],[-1,3],[0,3],[-2,1],[-2,3],[-2,2],[-4,2],[-2,0],[-2,-2],[-1,-3],[-1,5],[0,5],[3,10],[2,-3],[2,-1],[3,0],[3,1],[0,3],[-2,2],[-1,2],[-1,4],[0,5],[1,5],[-1,1],[-1,1],[-3,0],[-5,2],[-4,0],[-1,-5],[3,-7],[-2,3],[-2,5],[-3,8],[-2,9],[0,11],[2,8],[1,8],[2,10],[1,11],[2,-5],[1,-4],[3,-4],[1,-1],[4,-1],[2,0],[3,3],[3,-1],[2,-4],[2,-5],[3,-1],[6,3],[3,1],[2,-1],[2,-1],[1,1],[-1,4],[-1,4],[2,2],[5,-2],[3,1],[0,1],[1,1],[0,4],[0,3],[0,3],[-1,3],[-2,4],[-9,10],[-3,4],[-2,5],[-2,7],[-1,8],[-1,5],[-3,13],[-1,2],[-2,0],[-3,1],[-4,-1],[-6,-2],[-3,0],[-1,-1],[-4,-5],[-2,-5],[-3,-11],[2,-3],[0,-2],[-1,-16],[1,-8],[-1,0],[0,2],[-2,7],[-4,10],[-3,14]],[[6554,7564],[8,-1],[6,0],[8,-1],[3,-1],[3,0],[1,0],[1,2],[1,1],[1,2],[0,1],[-1,1],[-2,3],[-1,13],[0,11],[2,3],[2,2],[3,8],[2,2],[2,2],[9,0],[3,2],[1,2],[2,6],[1,5],[1,2],[1,2],[2,0],[2,-1],[2,-1],[1,-1],[2,-2],[1,-3],[0,-2],[0,-1],[1,0],[1,0],[1,0],[0,1],[0,2],[-2,3],[-4,7],[-2,3],[-1,2],[0,1],[1,2],[2,2],[2,-1],[4,-1],[1,1],[2,6],[4,-6],[4,-7],[1,-1],[3,-1],[3,0],[1,-1],[1,-1],[2,-8],[2,-1],[3,-2],[8,0],[3,0],[2,-3],[2,-2],[0,-1],[0,-2],[-1,-1],[0,-4],[0,-3],[0,-1],[-1,-2],[1,-1],[4,-2],[1,-3],[1,-2],[1,-1],[-1,-2],[-2,1],[-1,-2],[0,-3],[1,-4],[1,-2],[-1,-3],[-1,-4],[0,-3],[0,-2],[4,-3],[7,-7],[1,0],[7,1],[3,1],[2,-1],[5,-2],[2,-1],[2,0],[2,1],[2,3],[0,1],[1,0],[2,0],[4,-2],[4,-4],[3,-4],[1,-4],[2,-8],[2,-12],[3,-8],[3,-4],[2,-8],[2,-17],[1,-4],[1,-1],[4,-5],[7,-9],[4,-4],[6,-8],[6,-7],[6,-11],[2,-2],[5,-6],[6,-6],[4,2],[6,-9],[2,-4],[1,-1],[5,-4],[7,-7],[9,-11],[6,-7],[2,0],[1,0],[2,1],[2,1],[3,-1],[3,-3],[2,-2],[3,-3],[2,-2],[1,-2],[6,-2],[0,-1],[1,-2],[0,-1],[-3,-9],[0,-11],[0,-8],[0,-6]],[[8445,4646],[4,5],[7,3]],[[8469,4669],[3,5],[3,8],[1,4],[4,3],[2,1],[12,5],[3,0],[7,0],[10,1],[2,1],[4,2],[3,2],[1,2],[2,2],[3,-2],[4,-1],[1,-2],[1,-1],[-5,-10],[-5,-7],[-4,-2],[-3,-2],[-3,-3],[-2,-5],[-3,-2],[-3,-1],[-3,-1],[-3,-3],[-3,-5],[-2,0],[-1,0],[-3,-2],[-9,-6],[-6,-8],[-4,-6]],[[8489,4715],[-2,-10],[-2,2],[3,6],[1,1],[0,1]],[[141,3957],[0,-9],[-1,4],[0,2],[1,3]],[[134,3964],[1,0],[0,2],[2,1],[0,-2],[-2,-6],[-2,2],[-3,4],[-1,3],[1,2],[0,-1],[1,-1],[2,-1],[1,-1],[-1,-1],[1,-1]],[[168,4110],[-1,-3],[-1,0],[-1,2],[0,1],[2,4],[1,0],[1,-1],[0,-1],[-1,-2]],[[3305,5768],[-5,-4],[-11,0],[-5,1],[-4,-1],[7,7],[1,3],[3,0],[0,1],[1,16],[0,4],[-1,2],[-1,1],[-2,2],[-1,1],[2,2],[3,1],[3,2],[5,0],[3,2],[5,0],[-3,-7],[-1,-3],[1,-6],[-1,-4],[1,-6],[1,-4],[-1,-3],[0,-6],[0,-1]],[[3312,5828],[-2,-1],[1,2],[2,4],[4,3],[1,0],[0,-3],[-6,-5]],[[5304,7126],[-1,0],[-1,-2],[-1,0],[-2,2],[-1,0],[-1,1],[1,7],[0,2],[5,0],[3,-4],[0,-1],[0,-1],[-1,-2],[-1,-2]],[[5313,7186],[-5,-5],[1,4],[3,4],[1,-1],[0,-2]],[[5238,7311],[7,4],[6,9],[2,2],[16,9],[2,-1],[2,-1],[-1,-3],[-1,-3],[2,-4],[1,2],[0,2],[0,3],[3,0],[3,-1],[3,-2],[-1,-10],[5,-10],[-2,-5],[4,-3],[3,4],[1,5],[6,3],[5,7],[3,1],[0,-6],[2,-5],[-2,-2],[-3,-6],[-5,-14],[-4,-4],[-3,-6],[-1,-4],[-1,-5],[1,-8],[3,-8],[2,-5],[3,-2],[6,-8],[0,-4],[1,-6],[0,-7],[2,-5],[-4,-12],[-3,-9],[-5,-12],[-4,-7],[-9,-12],[-2,-4],[-2,-4],[-1,-4],[1,-5],[3,-11],[4,-8],[4,-3],[7,1],[0,-4],[0,-6],[3,0],[2,1],[2,6],[3,-4],[2,-11],[3,-4],[1,-1],[-2,-1],[0,-1],[1,-1],[2,-1],[2,1],[3,-3]],[[5721,7496],[-7,-2],[-2,2],[2,3],[4,2],[1,0],[2,-3],[0,-2]],[[5996,7253],[2,4],[-2,10],[-2,8],[2,6],[4,6],[5,8],[0,5],[-1,4],[-1,2],[-2,4],[-4,-4],[-3,-4],[-2,-1],[-2,-2],[-1,-4],[-2,-3],[-4,-2],[-6,4],[-7,5],[-4,4],[-3,1],[-2,-1],[-9,-11],[-7,-15],[-2,-3],[-8,-6],[-4,-2],[-3,0],[-9,-3],[-5,0],[-4,-4],[-7,4],[-4,5],[-3,5],[-4,10],[-3,5],[-7,5],[-12,10],[-3,2],[-8,1],[-8,1],[-2,-4],[-1,-15],[-1,-5],[-1,-8],[-1,-2],[-1,-2],[-3,3],[-2,1],[-4,-3],[-8,-5],[-3,-1],[-9,6],[-4,4],[-2,4],[-1,7],[-1,4],[0,3],[-1,3],[-2,2],[-2,-3],[-2,0],[-3,2],[-6,6],[-5,0],[-3,-7],[-3,-2],[-2,-1],[0,2],[2,5],[-8,-1],[-4,-4],[-4,1],[-2,1],[0,2],[3,1],[2,2],[8,1],[2,1],[3,5],[3,5],[1,2],[-3,0],[-13,-2],[-9,1],[-1,-2],[-1,0],[-1,6],[2,2],[2,0],[4,2],[0,5],[-3,4],[-1,2],[-3,0],[-1,2],[-1,6],[-1,7],[-3,3],[1,2],[4,2],[1,9],[-1,5],[-2,1],[-6,4],[-2,0],[-2,5],[-3,3],[-2,-1],[-1,-2],[-2,1],[-2,3],[-3,2],[-1,2],[1,5],[2,0],[1,4],[-2,7],[0,3],[2,1],[2,0],[2,-4],[1,-4],[-1,-4],[1,-4],[1,-1],[1,4],[1,1],[1,-2],[3,-1],[6,2],[1,3],[-4,-1],[-2,2],[-2,5],[-1,4],[0,2],[-1,2],[1,2],[3,2],[3,7],[-1,1],[-2,1],[-1,0],[-2,2],[0,3],[1,2],[0,4],[-3,8],[-1,2],[0,3],[3,4],[3,6],[0,2],[-2,1],[-10,-3],[-4,-2],[-6,-1],[-1,3],[0,3],[2,5],[0,12],[1,7],[3,2],[5,10],[7,12],[8,0],[3,3],[4,0],[1,-2],[1,-3],[4,-3],[7,1],[1,1],[2,2],[-3,5],[1,2],[3,0],[3,-1],[0,-1],[-1,-2],[-1,-3],[1,-1],[9,2],[10,-2],[3,1],[7,0],[2,2],[-3,3],[-2,1],[-1,1],[-2,1],[5,6],[2,1],[13,4],[9,1],[1,2],[-2,0],[-12,2],[-3,3],[-4,5],[-1,1],[-1,3],[1,5],[1,5],[1,2],[5,0],[17,-4],[11,3],[13,-7],[13,2],[2,2],[3,10],[18,15],[6,8],[6,5],[12,5],[9,6],[3,1],[22,-3],[16,-1],[7,7],[4,-2],[0,-3],[-1,-2],[0,-3],[2,-6],[3,-4],[7,-5],[10,4],[2,0],[2,-1],[3,-15],[3,-5],[4,-4],[3,-1],[2,4],[1,2],[4,0],[6,-5],[2,-5],[10,-4],[9,-2],[4,-5],[14,-4],[4,1],[9,4],[16,5],[10,-7],[3,-1],[3,1],[3,-2],[4,1],[12,9],[3,4],[4,2],[4,2],[9,10],[2,5]],[[5778,7601],[-1,-6],[2,-8],[4,-10],[4,-5],[17,-12],[3,-1],[-1,-6],[-1,-4],[-1,-3],[-5,-2],[-14,5],[-3,1],[-2,-1],[-5,-4],[-5,1],[-7,-2],[-2,-8],[-4,-9],[-8,-7],[-6,-4],[-8,-13],[-4,-8],[-2,-2],[-2,-1],[1,4],[1,3],[0,3],[0,4],[3,4],[2,3],[8,6],[2,5],[-6,0],[-6,-1],[-4,0],[-3,0],[-1,4],[-1,3]],[[8288,6596],[1,-4],[0,-2],[-4,1],[0,3],[1,-1],[2,3]],[[8361,6487],[-2,-7],[-2,-7],[0,-7],[0,-7],[0,-6],[-1,-6],[-3,1],[-1,5],[-1,7],[-2,9],[0,2],[-3,5],[-3,3],[-2,4],[1,-1],[-2,5],[-1,5],[-2,15],[-1,4],[-1,3],[0,3],[0,4],[1,5],[0,6],[0,7],[0,7],[1,3],[13,45],[4,9],[2,5],[2,5],[1,7],[2,6],[2,2],[7,5],[3,5],[2,2],[2,0],[1,-3],[1,-3],[2,-1],[3,-3],[1,-3],[1,-5],[-2,-4],[-1,-4],[0,-5],[0,-6],[0,-6],[-2,-14],[-3,-9],[-1,-5],[-1,-11],[-1,-11],[-1,-14],[-3,-14],[-1,-7],[-2,-5],[-3,-11],[-4,-9]],[[6102,4724],[-1,0],[-1,0],[-1,3],[2,2],[2,4],[3,6],[1,3],[1,1],[0,-4],[-2,-10],[-2,-1],[-2,-4]],[[6097,4828],[2,-12],[-1,-2],[-1,-2],[-1,0],[-1,2],[-1,4],[-1,-1],[-2,5],[-2,0],[-1,6],[0,5],[0,9],[2,5],[1,7],[2,-5],[0,-8],[2,-9],[1,-3],[1,-1]],[[6107,4901],[0,-3],[-1,-2],[1,-9],[-1,-6],[-1,-8],[-1,-3],[-2,1],[-1,1],[0,3],[1,14],[-1,11],[3,-1],[3,2]],[[6089,4914],[-1,-5],[-2,-12],[0,-5],[-1,-6],[-1,-4],[-2,-16],[-2,-6],[-2,-15],[-1,-11],[2,-8],[0,-7],[3,-7],[3,-3],[1,-3],[3,-7],[2,-8],[5,-3],[2,-9],[-1,-6],[-2,-4],[-2,-8],[-2,-10],[0,-16],[1,3],[3,-4],[0,-12],[-3,-13],[-1,-6],[0,-6],[2,-16],[3,-8],[0,-2],[-1,-2],[6,-15],[-1,-12],[2,-10],[1,-8],[1,-7],[0,-4],[-1,-5],[4,-1],[2,-4],[1,-4],[3,0],[1,-3],[3,-2],[4,-7],[2,-3],[0,-2],[0,-1]],[[5914,4642],[-2,1],[-3,4],[-4,3],[-3,3],[-2,3],[-3,2],[-3,0],[-2,3],[-3,1],[-2,0],[-1,2],[0,5],[-1,1],[-2,1],[-2,0],[-1,-1],[-1,1],[-1,2],[-2,4],[-1,5],[-2,3],[-3,3],[-7,0],[-2,1],[-1,2],[-2,5],[-2,5],[-2,7],[0,4]],[[5847,5122],[0,1],[2,-1],[2,1],[2,3],[2,0],[1,0],[3,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[4,0],[5,0],[5,0],[5,0],[5,0],[5,0],[3,0]],[[5889,7845],[3,-3],[-3,1],[-9,3],[-4,2],[-1,3],[0,4],[2,-4],[1,-2],[11,-4]],[[6061,7896],[-1,0],[-10,0],[-8,-1],[-5,-9],[-4,0],[-4,-2],[-4,-3],[-4,-7],[-2,3],[-4,0],[-4,-1],[-4,-5],[-2,0],[-5,1],[-5,-3],[-12,-14],[-4,-10],[-2,-2],[-2,-2],[-2,-2],[-1,0],[6,8],[1,2],[1,2],[0,4],[-2,4],[-5,-10],[-2,-2],[-4,-3],[0,-6],[1,-5],[1,-7],[3,-10],[7,-15],[3,-5],[2,-2],[3,0],[5,4],[3,1],[5,-2],[2,3],[2,2],[3,0],[4,-1],[4,-3],[-1,-5],[-2,-4],[-1,-4],[-1,-6],[-4,-2],[-5,1],[-5,-2],[-2,2],[-1,2],[-3,2],[-3,1],[-2,-2],[-3,-7],[-6,-4],[-2,-6],[-5,2],[-5,-1],[-7,-5],[-5,-11],[-6,-6],[-5,-3],[-4,1],[-3,2],[-5,7],[0,3],[1,1],[1,3],[2,13],[0,5],[-1,6],[-5,6],[-4,-1],[-2,1],[-7,9],[-4,0],[-5,-1],[-1,1],[-2,3],[9,11],[9,9],[4,1],[5,4],[6,6],[-1,5],[-1,4],[-3,-1],[-2,-1],[-5,4],[-1,2],[-8,-3],[-4,1],[-8,-3],[-5,3],[-8,7],[-3,2],[-2,0],[-2,2],[2,1],[2,0],[2,1],[1,2],[0,2],[-5,2],[-4,1],[-2,2],[-2,2],[4,0],[5,-2],[7,0],[6,-2],[2,2],[4,4],[0,2],[-6,-3],[-6,2],[-2,2],[-2,4],[-1,5],[0,4],[0,7],[-2,6],[-1,4],[-2,3],[2,-7],[1,-5],[1,-4],[0,-12],[-1,-4],[-3,-1],[-3,0],[-4,2],[1,6],[-2,-2],[-2,-6],[-3,-1],[-5,0],[-9,-4],[-1,-4],[-1,-7],[-2,-3],[0,-2],[-4,-10],[-1,0],[-7,-13],[-1,-1],[-5,-3],[-3,-3],[-2,-1],[-4,1],[-2,-2],[0,-2],[0,-5],[2,-3],[1,-11],[0,-5]],[[3517,3240],[-1,-2],[-2,-4],[-1,-10],[-6,-13],[-1,-7],[-7,-8],[-4,-9],[-3,0],[-2,-4],[-15,-11],[-6,2],[-4,0],[-3,5],[-9,2],[-5,-2],[-7,-6],[-2,0],[-2,1],[-4,2],[-2,5],[-11,5],[-8,13],[-11,1],[-8,-2],[-1,2],[-1,3],[-1,5],[-7,11],[-6,11],[-1,12],[1,12],[2,14],[-1,5],[2,2],[2,1],[2,3],[2,6],[0,4],[-1,8],[-1,11],[-1,5]],[[678,6279],[-1,-3],[-2,0],[-5,6],[-1,3],[1,15],[-2,12],[-3,9],[2,5],[2,4],[3,7],[-2,8],[0,6],[1,1],[6,-7],[12,-10],[3,-6],[1,-8],[2,-1],[1,-5],[3,-4],[1,-3],[-1,-4],[-6,-7],[-7,-4],[-6,-9],[-2,-5]],[[643,6380],[-2,-1],[-1,0],[-1,4],[-2,5],[3,1],[2,-1],[1,-2],[1,-2],[-1,-4]],[[653,6389],[1,-1],[3,2],[2,1],[3,-4],[2,-3],[2,-3],[1,-2],[-1,-2],[-2,-4],[-4,-1],[-2,-2],[-3,1],[-1,0],[0,5],[-1,6],[-2,-1],[-1,2],[-3,5],[0,2],[1,5],[2,0],[2,-2],[1,-4]],[[633,6406],[6,-2],[1,1],[1,-1],[5,-1],[1,-1],[-1,-3],[-3,-2],[-5,2],[-7,1],[0,2],[1,2],[0,3],[1,-1]],[[617,6420],[1,-1],[1,1],[0,-5],[2,-2],[0,-2],[-1,-2],[-3,0],[-2,1],[-1,3],[-2,-1],[0,2],[0,1],[-1,0],[1,-3],[-3,-1],[-1,1],[-1,3],[-3,7],[0,2],[-1,3],[5,1],[2,5],[2,1],[3,-9],[0,-2],[1,-2],[1,-1]],[[551,6442],[-1,-3],[-1,1],[0,2],[0,3],[2,3],[2,4],[1,-1],[-1,-2],[0,-3],[-2,-2],[0,-2]],[[573,6447],[-3,-3],[-1,1],[-3,1],[-1,2],[-2,2],[-2,3],[2,6],[4,5],[7,0],[1,-4],[0,-3],[-1,-3],[0,-5],[-1,-2]],[[2728,6598],[-1,-1],[0,1],[1,1],[1,0],[0,-1],[-1,0]],[[2734,6601],[-2,-1],[2,2],[0,4],[1,-3],[0,-1],[-1,-1]],[[2740,6604],[0,-2],[-1,1],[0,2],[-1,3],[0,1],[3,-3],[0,-1],[-1,-1]],[[2749,6607],[-2,-1],[-1,1],[1,1],[5,2],[-2,-2],[-1,-1]],[[2754,6612],[0,1],[1,2],[1,-1],[0,-1],[-2,-1]],[[2760,6618],[-1,0],[1,2],[0,-2]],[[2767,6632],[-6,-11],[1,3],[2,6],[1,2],[1,2],[2,3],[0,4],[2,2],[0,1],[-3,-12]],[[2721,6707],[-1,-1],[-2,1],[-1,2],[-1,4],[2,-4],[1,-1],[2,-1]],[[2720,6713],[0,-3],[-2,5],[-1,7],[2,-2],[1,-7]],[[2301,6691],[-1,-3],[-2,12],[-4,29],[0,16],[1,5],[1,-22],[4,-29],[1,-8]],[[2296,6756],[-1,-3],[0,5],[2,11],[5,15],[2,2],[-6,-16],[-2,-14]],[[2772,6755],[1,-4],[-3,10],[-3,15],[-2,12],[2,-3],[1,-7],[4,-23]],[[2305,6791],[-1,0],[2,4],[0,2],[2,6],[1,1],[1,-2],[-2,-5],[-3,-6]],[[2312,6805],[-1,0],[1,3],[2,2],[5,6],[2,0],[0,2],[1,1],[0,-3],[-4,-4],[-6,-7]],[[2360,6863],[-2,-1],[6,9],[2,3],[1,0],[-2,-5],[-5,-6]],[[2450,6883],[-1,-1],[-5,5],[0,2],[2,2],[2,0],[2,-2],[1,-1],[0,-1],[0,-2],[-1,-2]],[[2641,6891],[-3,-2],[-3,2],[2,0],[2,-1],[3,3],[2,2],[2,1],[-5,-5]],[[2531,6895],[-2,-3],[0,1],[1,3],[1,2],[0,-3]],[[2532,6901],[0,-2],[0,9],[-1,7],[1,-3],[1,-4],[-1,-7]],[[2521,6917],[0,-3],[-1,1],[-2,0],[1,1],[1,1],[0,1],[2,3],[0,-2],[-1,-2]],[[2540,6924],[-1,0],[-2,1],[-2,1],[0,1],[4,-2],[1,-1]],[[2553,6926],[-2,-1],[-4,0],[0,1],[1,0],[4,2],[1,-2]],[[2738,6968],[-1,-14],[-1,5],[0,4],[1,3],[1,2]],[[1712,7075],[-1,-1],[-2,1],[-2,6],[-1,4],[1,1],[1,-4],[3,-6],[1,-1]],[[1682,7097],[-1,0],[-2,0],[-1,4],[2,0],[1,-1],[1,-2],[0,-1]],[[1712,7107],[2,-4],[-2,0],[-2,0],[-1,2],[-1,3],[0,1],[-1,0],[-1,1],[0,1],[1,1],[4,-4],[1,-1]],[[1665,7137],[-2,0],[-1,0],[-2,6],[5,1],[2,-3],[-2,-4]],[[1658,7144],[-1,-1],[-3,1],[1,1],[1,1],[1,0],[1,-2]],[[1670,7147],[5,-3],[3,1],[1,-1],[0,-1],[-7,-3],[-2,2],[-1,2],[0,2],[1,1]],[[2873,7180],[-1,0],[-2,2],[1,0],[2,-2]],[[2875,7179],[-1,0],[2,7],[5,9],[2,1],[-4,-8],[-4,-9]],[[2895,7211],[-5,-4],[-1,0],[3,3],[3,1]],[[2901,7214],[-3,-2],[-1,1],[4,3],[2,11],[0,6],[-1,9],[0,2],[1,-3],[1,-9],[-1,-6],[-1,-10],[-1,-2]],[[2899,7249],[-1,-1],[-2,6],[2,-2],[1,-2],[0,-1]],[[2907,7366],[-1,-1],[4,12],[3,9],[1,4],[-1,-7],[-2,-6],[-4,-11]],[[2940,7469],[-3,-8],[0,1],[4,11],[-1,-4]],[[2939,7518],[-1,0],[1,5],[2,3],[1,-1],[0,-2],[0,-1],[-2,-3],[-1,-1]],[[2986,7545],[-2,-4],[1,-1],[2,2],[1,2],[4,3],[3,1],[1,0],[1,-2],[3,2],[2,1],[-12,-10],[-2,-1],[-4,-3],[-3,-2],[-2,0],[-12,-8],[-1,0],[-1,1],[-10,-4],[-4,0],[-4,-1],[3,3],[0,1],[-1,1],[-1,-1],[-2,-3],[-2,-1],[-1,4],[1,2],[1,3],[3,3],[3,3],[2,2],[1,-2],[0,2],[1,2],[1,1],[2,0],[2,0],[1,1],[1,0],[2,-1],[3,0],[2,2],[2,0],[6,1],[5,1],[3,2],[4,6],[3,1],[-4,-6],[-2,-3]],[[3056,7561],[-2,-1],[-5,2],[4,2],[1,0],[0,3],[0,1],[2,-5],[0,-2]],[[3041,7567],[-8,-3],[-1,2],[2,1],[3,4],[1,1],[3,-3],[0,-2]],[[3017,7573],[0,-1],[-1,3],[1,3],[1,-1],[-1,-4]],[[3021,7574],[-2,-2],[-1,0],[1,2],[0,4],[1,3],[0,1],[1,1],[0,-9]],[[3093,7729],[-1,-1],[-1,1],[0,2],[1,1],[0,1],[1,-1],[0,-3]],[[3106,7737],[-2,-1],[-2,1],[0,-3],[0,-1],[-2,1],[-1,1],[0,4],[2,4],[1,1],[2,-1],[2,-4],[0,-2]],[[1587,7903],[0,-1],[-1,2],[0,2],[0,1],[1,-4]],[[1600,7914],[0,-2],[-1,-1],[-1,1],[0,1],[-1,-1],[0,3],[0,4],[1,0],[1,-2],[1,-3]],[[1597,7925],[0,-1],[-2,1],[0,2],[0,2],[0,2],[1,0],[1,0],[0,-1],[0,-5]],[[1595,7958],[1,-8],[1,3],[4,-5],[0,-3],[-1,-1],[-1,1],[-1,1],[-1,1],[-2,1],[0,2],[-1,2],[0,4],[0,1],[-1,1],[-1,1],[-2,3],[1,3],[1,4],[1,2],[1,-1],[1,-1],[1,-2],[0,-2],[-4,-3],[2,-1],[0,-1],[1,-2]],[[1588,7973],[-2,1],[-1,1],[0,1],[1,4],[1,0],[0,-3],[1,-2],[0,-2]],[[1583,7977],[1,-2],[-3,2],[-2,1],[0,1],[-1,3],[1,1],[1,1],[3,-4],[0,-3]],[[1589,7987],[1,-1],[-2,-1],[-2,2],[0,-3],[0,-1],[-2,2],[-1,1],[1,2],[1,1],[1,0],[3,-2]],[[3135,7785],[0,-1],[1,-3],[0,-6],[-1,-2],[1,-4],[2,-1],[1,-1],[0,-1],[-6,-9],[-5,1],[-2,-2],[-3,-1],[-1,-4],[-2,0],[-2,0],[-1,1],[-2,-1],[-2,-7],[-1,1],[-1,-3],[-1,-1],[-1,-1],[-1,3],[0,3],[-1,1],[-2,1],[-1,0],[-1,-1],[-1,-2],[-2,-1],[-1,1],[-1,2],[-1,-3],[-1,-4],[1,-4],[-1,-3],[-1,1],[-1,2],[-3,2],[-3,0],[1,2],[2,4],[-1,0],[-1,0],[1,3],[0,4],[-1,-1],[-2,-4],[-3,-3],[0,-5],[-3,-10],[0,-4],[-2,-4],[-2,-3],[-4,1],[-2,-2],[-1,-3],[-1,-1],[-1,4],[0,1],[-1,-5],[-1,-1],[-1,4],[0,3],[-1,-2],[-1,-6],[-1,0],[0,2],[-1,1],[0,-3],[0,-3],[0,-2],[-1,1],[-1,2],[-2,-2],[-1,0],[0,2],[0,2],[-2,-1],[-4,-4],[-2,-6],[1,-1],[1,-1],[-5,-9],[-4,-7],[-4,-13],[-1,-1],[-1,-2],[-1,-8],[-2,-7],[1,-2],[1,-4],[1,-3],[1,0],[1,1],[1,0],[0,-2],[0,-1],[-1,-1],[-3,-2],[-2,-1],[-1,-3],[-2,-4],[-3,-6],[2,-2],[5,-2],[2,-2],[3,-11],[-1,-1],[0,-2],[3,-3],[1,-7],[2,-3],[4,-2],[5,3],[3,3],[0,3],[-2,6],[-1,3],[-2,2],[0,-2],[-1,2],[0,1],[1,1],[1,0],[1,-2],[4,-6],[1,-9],[0,-6],[0,-2],[-1,1],[-2,-1],[-10,-3],[-2,-2],[-5,-3],[0,1],[0,3],[0,6],[-1,1],[-8,-10],[-3,-1],[-2,-2],[-1,1],[0,7],[1,6],[-3,-3],[-1,2],[-1,2],[0,2],[-1,0],[0,-5],[-1,-4],[-1,-11],[-2,-4],[-7,-3],[-4,1],[-4,-1],[-6,-2],[-3,1],[-3,-2],[-10,0],[-2,1],[-3,-4],[-4,-3],[-11,-8],[-3,-4],[-3,-5],[-2,-2],[-1,-1],[-1,-3],[-1,-1],[1,5],[1,4],[1,9],[-1,6],[-1,3],[-1,2],[1,-7],[1,-8],[-1,-5],[-3,-9],[-1,-2],[-1,-2],[-1,0],[-1,-2],[-1,-2],[-1,-5],[0,-4],[6,-2],[1,2],[1,-3],[0,-4],[0,-5],[-1,-4],[-1,-6],[0,-9],[-1,-7],[0,2],[0,9],[-1,-1],[0,-2],[-2,-12],[-2,-7],[-2,-4],[-2,1],[0,-4],[0,-2],[-1,-4],[-1,-2],[-1,0],[-2,-2],[-1,-1],[0,-3],[-1,-2],[-4,-12],[-3,-3],[-1,0],[1,6],[0,6],[-2,2],[-2,1],[-2,0],[-3,5],[-3,3],[-5,8],[0,3],[0,4],[1,6],[2,5],[2,2],[5,2],[1,4],[1,3],[-2,-5],[-5,-2],[-2,-2],[-2,-3],[-1,-4],[-2,-4],[0,-3],[1,-2],[-1,-4],[2,-5],[3,-7],[0,-11],[3,-7],[3,-8],[3,-3],[0,-3],[-1,-5],[-2,-2],[2,0],[1,-1],[1,-4],[0,-5],[0,-2],[-1,-1],[0,2],[0,1],[-1,-1],[0,-1],[-1,-5],[0,-3],[-2,-1],[-2,-6],[-1,-4],[-7,-25],[0,-4],[-1,-1],[-2,-1],[-2,-3],[-1,-3],[-1,-7],[-3,-8],[-1,3],[0,3],[0,8],[3,13],[2,8],[2,3],[2,8],[-2,1],[-3,0],[0,3],[1,4],[-1,3],[-1,0],[-1,1],[1,3],[0,3],[0,3],[1,2],[-1,0],[-2,-3],[0,-1],[-1,3],[-1,-1],[0,-1],[-1,-1],[-2,2],[-2,2],[-2,5],[-1,3],[1,6],[2,1],[2,-1],[4,0],[-1,2],[-1,-1],[-3,5],[-1,3],[-2,1],[-1,-3],[-1,-1],[1,7],[2,0],[2,2],[-1,3],[-1,2],[-3,-2],[0,2],[1,4],[2,0],[1,-1],[2,5],[0,2],[-2,-3],[-1,7],[2,7],[3,3],[2,0],[3,1],[-2,1],[-1,1],[1,3],[1,0],[1,3],[-3,-1],[1,5],[-2,-1],[-1,-1],[-1,-2],[0,-3],[0,-2],[-1,-2],[-2,-1],[-1,2],[0,1],[-1,-5],[0,-1],[-2,4],[0,-1],[0,-1],[0,-2],[-2,-1],[0,-3],[0,-2],[-4,3],[0,-1],[2,-6],[2,-2],[0,-3],[-2,-2],[-2,2],[1,-4],[1,-3],[-1,-3],[0,-3],[0,-3],[0,-3],[1,-12],[1,-3],[1,-3],[1,-3],[-2,-1],[-2,3],[-1,2],[-2,6],[-1,2],[0,2],[0,-5],[1,-4],[6,-11],[1,-4],[1,-3],[0,-3],[-2,2],[-1,3],[-4,3],[-5,2],[-3,7],[1,-3],[-1,-3],[-2,4],[-1,2],[0,3],[-2,0],[-3,-3],[-2,1],[0,5],[1,3],[2,6],[2,3],[1,4],[0,7],[0,-7],[-2,-3],[-2,-2],[-2,-5],[-1,-4],[-1,-8],[1,-2],[1,-1],[4,2],[2,-1],[3,-9],[8,-4],[2,-2],[3,-5],[3,-3],[2,-4],[0,-2],[-1,-3],[0,-4],[-1,-3],[-3,0],[-1,0],[-8,15],[-1,1],[-4,8],[-3,4],[-1,0],[5,-8],[2,-5],[4,-7],[2,-4],[2,-5],[2,-2],[5,-3],[-2,-3],[3,-2],[1,-3],[-1,-4],[-4,1],[0,-3],[1,-2],[-2,-1],[-2,2],[-6,11],[0,-1],[0,-2],[4,-7],[3,-5],[2,-2],[3,-3],[0,-3],[1,-3],[-2,-2],[-2,-2],[-1,3],[-1,2],[-3,4],[-1,5],[-2,-1],[-8,6],[-7,1],[1,-1],[0,-1],[6,-1],[2,-3],[4,-2],[3,-1],[1,-7],[4,-5],[0,-4],[3,0],[4,3],[3,-1],[4,-1],[1,-3],[0,-6],[2,-6],[3,-24],[6,-21],[1,-3],[-2,3],[-4,13],[-2,10],[-2,17],[-1,4],[-1,1],[0,-1],[-1,-2],[1,-2],[-1,-5],[0,-3],[2,-3],[1,-6],[2,-9],[-2,3],[-2,2],[-3,2],[-3,2],[1,-3],[-1,-4],[-2,1],[-1,1],[1,-4],[-2,1],[-2,0],[-1,-4],[-2,-2],[-2,-1],[-3,4],[-1,4],[-1,5],[0,-6],[1,-6],[-1,-4],[4,-1],[3,1],[4,0],[2,0],[2,2],[4,-1],[0,-6],[0,-5],[-1,-5],[1,0],[2,1],[0,10],[4,4],[1,0],[1,-3],[0,-4],[1,-4],[-1,-7],[-5,-8],[-4,-7],[-2,-2],[-3,1],[-3,2],[-2,0],[-1,0],[-1,2],[0,4],[-1,1],[-1,0],[-1,-4],[-3,-1],[-4,1],[-4,4],[2,-4],[10,-7],[1,-2],[1,-2],[-1,-3],[-1,-3],[0,-3],[-1,-2],[-4,-5],[-2,1],[-6,9],[3,-8],[2,-3],[4,-2],[8,3],[3,-3],[-3,-5],[-2,-4],[-3,-1],[-2,-1],[-1,-2],[-2,0],[-2,0],[-5,-1],[-2,1],[-3,-5],[-1,-1],[-2,1],[-1,4],[-1,2],[0,-8],[1,-2],[0,-2],[-4,-4],[-3,-5],[-2,-2],[-1,-2],[-3,-8],[-1,-6],[-1,-6],[0,3],[0,4],[-1,6],[0,-10],[-1,-5],[-11,0],[-5,-2],[-7,-9],[-3,-4],[-6,-14],[-1,-9],[-1,4],[0,2],[0,3],[-2,-5],[2,-8],[-1,-3],[-4,-5],[-3,-1],[-2,-1],[-1,-6],[-3,-5],[-2,-2],[-4,2],[1,-5],[-1,-4],[-2,-2],[-3,-2],[-2,0],[-1,-1],[-1,-2],[-3,-2],[-2,1],[-3,1],[-2,-2],[3,-2],[1,-3],[0,-4],[-1,-1],[-2,-3],[0,1],[-1,2],[0,4],[-1,-1],[0,-2],[-1,-1],[-3,7],[0,-5],[1,-4],[1,-2],[1,-1],[0,-2],[-2,-4],[0,-1],[-2,0],[-1,-3],[0,-2],[-1,-5],[-4,-3],[-1,0],[0,-1],[0,-2],[1,-2],[0,-1],[-1,-2],[-2,-1],[-1,-2],[1,-2],[0,-1],[0,-2],[-2,-3],[0,-2],[1,0],[1,0],[-1,-3],[-1,-3],[-1,-3],[-3,-1],[0,-2],[2,-1],[1,-2],[-2,-6],[-2,1],[-1,1],[0,-4],[0,-3],[0,-4],[-1,-6],[-1,-2],[0,-4],[1,-4],[1,-5],[2,-22],[1,-7],[3,-20],[4,-20],[6,-23],[9,-28],[1,-4],[-1,-4],[-1,-3],[0,-6],[1,-5],[1,-6],[2,-10],[-1,2],[-3,14],[-1,8],[1,12],[-1,-1],[-1,-3],[0,-5],[-1,-2],[-1,7],[0,3],[1,4],[0,1],[-2,2],[0,3],[0,3],[-1,1],[-1,0],[1,-7],[1,-4],[1,-10],[1,-7],[1,-5],[12,-56],[3,-7],[1,-5],[1,-11],[0,-14],[-2,-25],[0,-17],[0,2],[-1,0],[-2,-8],[-2,-7],[-1,-11],[-1,-5],[-3,-6],[-2,0],[-5,-4],[-3,1],[-5,-3],[-2,1],[-2,5],[0,2],[1,3],[1,0],[4,-5],[0,2],[-1,3],[-2,1],[-1,2],[-4,12],[-3,9],[0,6],[-6,3],[-4,5],[-3,10],[-1,16],[-2,2],[-1,2],[2,6],[2,5],[-2,-1],[-1,-2],[-1,-5],[-1,-1],[-1,1],[-1,9],[0,11],[2,4],[-3,0],[-2,-2],[0,-3],[0,-2],[-2,0],[-1,2],[-2,3],[-2,7],[-5,20],[-1,3],[-2,3],[1,1],[1,0],[3,9],[3,5],[1,4],[0,2],[-1,2],[-2,-2],[-1,1],[-1,4],[-2,1],[-1,-1],[1,-3],[1,-2],[0,-5],[0,-2],[-1,-2],[-2,1],[-1,-1],[-1,1],[0,3],[-1,4],[2,22],[3,15],[0,16],[0,2],[0,5],[-3,9],[-15,23],[-11,27],[-10,11],[-7,-3],[-1,-2],[-1,-2],[0,-3],[0,-2],[-2,1],[-3,-1],[-7,-7],[-2,0],[-3,-2],[-1,-1],[-5,-1],[-3,-2],[-2,1],[-1,4],[0,5],[1,-4],[1,-2],[1,1],[0,2],[-1,5],[-4,5],[-5,9],[1,-1],[1,2],[-2,3],[1,2],[1,3],[-2,0],[-2,-2],[0,-3],[0,-2],[-1,1],[-2,2],[-9,7],[-8,4],[6,1],[3,-1],[0,2],[-1,1],[-2,2],[-4,0],[-2,0],[-2,-1],[-2,-3],[-2,-1],[-8,-2],[-7,-2],[2,2],[1,2],[3,2],[1,4],[-1,4],[-1,-1],[-1,-3],[-1,2],[-2,0],[0,-5],[-2,-3],[-1,-4],[-5,-2],[-1,1],[2,3],[0,1],[-2,-1],[-3,-6],[-11,-2],[1,1],[2,1],[3,2],[-1,3],[-1,3],[-1,1],[-1,2],[0,6],[0,4],[-2,4],[-1,-1],[-1,-7],[-1,-8],[0,-3],[-4,0],[-2,0],[-10,-1],[-3,3],[-2,1],[-1,0],[-4,-3],[-5,-2],[-1,1],[-1,0],[-4,-7],[-4,-4],[-10,6],[-3,5],[-2,1],[-3,1],[-2,-6],[-3,-8],[4,-4],[3,-3],[5,2],[3,4],[2,0],[1,1],[1,2],[2,-2],[0,-2],[-1,-2],[-2,-2],[-1,-2],[2,-4],[3,-2],[1,1],[1,5],[2,3],[2,-1],[0,-2],[0,-2],[2,-3],[-1,-4],[1,-2],[-3,-2],[-2,0],[-2,-3],[1,-2],[-2,-1],[-1,1],[0,-1],[-1,-2],[0,-1],[1,-5],[2,-3],[2,-4],[8,-5],[2,0],[1,-5],[2,-1],[1,-1],[0,-4],[-3,-2],[0,-3],[-1,-2],[-1,2],[-1,2],[-3,-5],[-1,-1],[1,5],[-1,2],[-2,5],[-2,4],[-2,1],[-1,2],[-1,0],[-1,0],[-2,1],[-1,3],[0,2],[-2,3],[-8,4],[0,-2],[1,-1],[1,-1],[1,-2],[0,-5],[0,-3],[-1,-3],[0,-3],[-1,-3],[-2,-2],[-1,2],[-2,7],[-2,2],[-3,0],[-3,-1],[-2,-7],[-2,-1],[-7,3],[-8,6],[0,2],[1,0],[3,-1],[0,2],[-3,6],[0,3],[0,4],[-1,0],[-1,-3],[-5,2],[-2,3],[-3,8],[-4,0],[-2,5],[-3,-2],[-2,-2],[-2,-4],[1,-1],[2,-3],[-1,-2],[-5,-2],[-11,3],[-4,2],[-4,4],[-6,4],[-3,1],[-3,-1],[-9,0],[-2,-1],[-2,-2],[-1,2],[0,3],[1,0],[1,2],[1,4],[0,2],[-1,1],[-1,1],[-3,-10],[2,-5],[0,-2],[-6,-1],[-13,-11],[-5,-6],[0,2],[6,8],[-2,1],[-4,-2],[-1,1],[2,6],[-1,5],[-2,1],[-2,-5],[-1,0],[-2,2],[-1,0],[1,-10],[2,-4],[1,-6],[-4,-6],[-3,-5],[0,-5],[-4,-7],[-3,-4],[-7,-9],[-2,-1],[-4,-5],[-4,-3],[-5,-5],[-1,0],[2,4],[4,4],[-3,-1],[-5,2],[-2,0],[0,-1],[-2,-2],[-3,3],[0,2],[-1,2],[-1,0],[-1,-1],[4,-12],[1,-1],[1,-1],[-1,-3],[-2,-2],[-4,-2],[-2,5],[-1,-6],[0,-6],[-1,-1],[-2,-2],[0,1],[-1,2],[-1,-2],[-1,-1],[-2,0],[-2,-1],[0,-3],[0,-2],[3,2],[-1,-6],[-2,-6],[-3,-2],[-3,1],[-1,-1],[-1,-1],[4,-9],[-2,-15],[-2,-5],[-1,-1],[-1,0],[-5,5],[-2,3],[2,-10],[6,-2],[0,-4],[0,-3],[-1,-4],[-1,-5],[1,-3],[1,-9],[0,-4],[1,-12],[1,-5],[5,-19],[2,0],[0,-2],[0,-4]],[[1746,7058],[0,6],[-1,3],[-2,-2],[-1,8],[1,4],[0,4],[-2,9],[-4,12],[-9,14],[-5,4],[-3,6],[-2,2],[-3,0],[-1,-2],[-3,1],[0,7],[-3,9],[-3,1],[-6,0],[-9,5],[-2,3],[-1,5],[-4,5],[-6,4],[-3,-1],[-3,1],[-6,3],[-3,1],[-7,-1],[-2,0],[-2,4],[-2,3],[0,5],[0,4],[0,4],[-1,8],[1,7],[-1,3],[-1,2],[-4,3],[-1,4],[1,5],[-1,3],[-4,3],[-3,8],[-4,4],[-2,6],[-2,5],[-1,3],[-6,13],[-6,10],[-1,6],[0,8],[3,5],[1,5],[0,3],[-1,3],[-2,5],[-8,3],[-6,13],[0,9],[-3,10],[0,7],[0,6],[2,2],[1,-1],[0,-2],[1,-5],[2,-4],[2,-2],[1,-3],[2,-1],[1,-1],[-1,3],[0,1],[-1,5],[-2,6],[-2,3],[-1,7],[-1,1],[-1,2],[2,3],[3,2],[4,0],[10,0],[2,1],[2,0],[1,0],[-3,1],[-1,0],[-2,0],[-4,0],[-1,1],[-2,1],[-1,1],[-3,-4],[-2,1],[-3,3],[-2,1],[-2,-2],[-1,-9],[1,-7],[-2,0],[-1,2],[-3,2],[-2,2],[-3,5],[-2,2],[-2,-4],[0,2],[1,4],[0,8],[3,-6],[-1,4],[-2,5],[-2,1],[-2,8],[-5,5],[-4,8],[-7,14],[-1,12],[-3,14],[2,9],[-1,6],[-1,9],[-1,5],[-7,13],[-6,9],[0,7],[-1,7],[1,6],[2,7],[0,1],[1,0],[-1,-2],[1,0],[1,3],[0,1],[-1,0],[0,1],[1,2],[2,9],[0,10],[2,13],[-1,5],[-1,9],[-1,6],[-2,4],[1,6],[0,5],[-4,8],[-2,10],[0,5],[0,12],[-1,5],[-3,8],[2,7],[1,4],[3,19],[1,2],[1,0],[2,3],[-1,1],[-2,-2],[2,8],[1,6],[1,2],[1,21],[1,16],[1,6],[0,5],[0,7],[0,8],[3,36],[-1,4],[1,6],[-1,15],[1,17],[-1,3],[0,2],[2,-2],[6,0],[5,2],[1,-1],[2,-3],[2,0],[3,0],[-1,1],[-1,0],[-3,3],[-2,3],[-5,0],[-1,2],[-6,-2],[-1,2],[-4,-2],[1,6],[0,7],[0,6],[1,-5],[2,-5],[1,6],[0,7],[-1,3],[-4,2],[-1,7],[8,6],[-4,1],[-2,3],[-2,0],[0,-2],[0,-3],[-1,4],[0,4],[-1,7],[-3,11],[-2,15],[-2,7],[-5,7],[-1,4],[-1,10],[1,8],[-1,5],[2,0],[5,-4],[8,-4],[2,-2],[3,-2],[19,-3],[1,1],[3,1],[1,0],[3,-4],[1,0],[2,0],[1,1],[2,2],[1,-1],[0,-2],[0,-4],[2,-4],[1,-3],[-4,-9],[0,3],[-1,1],[-6,-14],[-2,-7],[-1,-3],[0,-2],[1,0],[2,1],[3,2],[0,1],[-2,-1],[-2,0],[1,3],[0,2],[2,4],[2,3],[2,3],[2,2],[1,4],[3,4],[1,1],[-1,4],[1,0],[1,0],[1,-6],[-1,-3],[-2,-3],[-1,-1],[1,-5],[-1,0],[-1,0],[3,-5],[0,-3],[1,-4],[-1,-6],[-1,-1],[-1,0],[-2,2],[-1,-5],[-1,0],[-1,6],[-3,-2],[-1,-3],[0,-4],[-2,-2],[4,-1],[2,1],[3,-2],[3,2],[0,2],[2,6],[1,1],[1,0],[1,1],[2,3],[0,2],[0,7],[0,5],[-1,1],[0,2],[0,1],[0,2],[0,2],[0,2],[0,2],[2,5],[0,2],[2,4],[0,2],[-2,2],[-1,2],[-1,3],[-1,1],[1,-5],[0,-1],[-3,3],[0,2],[-1,2],[1,2],[1,1],[2,1],[0,1],[-3,5],[-1,2],[-1,1],[-2,0],[0,1],[-1,1],[1,2],[1,0],[2,0],[1,1],[0,1],[0,2],[0,6],[-1,5],[-1,1],[-1,0],[-1,0],[-1,1],[-1,4],[-2,8]],[[9984,8143],[-5,0],[-10,9],[-5,3],[-3,3],[2,1],[6,-2],[5,-5],[2,-4],[3,-2],[4,-2],[1,-1]],[[103,8167],[-2,-3],[-1,1],[0,5],[1,1],[2,-3],[0,-1]],[[111,8168],[-2,-1],[-4,2],[1,3],[3,-2],[2,-2]],[[59,8159],[-1,-2],[-4,3],[-1,1],[3,2],[0,1],[0,1],[-2,2],[-3,3],[-1,2],[1,1],[1,1],[5,0],[2,-3],[2,-1],[4,-1],[-2,-2],[-1,-1],[-2,-5],[-1,-2]],[[79,8163],[-1,-1],[-1,-1],[-4,1],[-3,0],[-3,-1],[-2,-1],[0,2],[0,1],[9,3],[2,2],[2,2],[1,4],[1,1],[2,-2],[-1,-2],[-1,-2],[0,-1],[-1,-5]],[[95,8171],[0,-2],[3,1],[1,-1],[0,-4],[0,-1],[-1,-1],[-1,1],[-1,-2],[-6,-4],[-2,2],[-4,-4],[3,11],[3,1],[1,2],[-1,3],[2,5],[3,0],[1,-2],[0,-2],[-1,-3]],[[9959,8174],[-1,-1],[-1,3],[0,1],[1,2],[1,-1],[1,-2],[-1,-2]],[[9991,8173],[-2,-1],[-3,1],[-1,2],[0,3],[4,3],[4,-4],[-2,-4]],[[111,8179],[-1,-2],[-3,2],[-1,2],[0,1],[1,3],[2,0],[1,-1],[1,-2],[1,-1],[-1,-2]],[[9927,8172],[-2,-2],[-2,2],[0,1],[3,5],[3,0],[1,2],[1,5],[2,0],[1,0],[0,-3],[-2,-3],[0,-3],[-5,-4]],[[179,8187],[6,-3],[6,1],[3,-1],[0,-1],[-5,0],[-1,0],[-4,-1],[-2,-1],[-6,2],[-5,-1],[-1,0],[-1,1],[-2,2],[0,1],[1,0],[4,-1],[1,1],[3,1],[3,0]],[[209,8195],[-2,-1],[-2,1],[1,3],[1,1],[2,2],[3,-1],[1,-2],[-4,-3]],[[148,8181],[-15,-2],[-2,1],[2,1],[3,1],[5,2],[7,3],[5,3],[5,1],[1,3],[-4,2],[0,1],[2,2],[1,2],[4,2],[3,-3],[1,-2],[0,-2],[-1,-3],[-3,-1],[0,-2],[1,-3],[-6,-4],[-9,-2]],[[9825,8200],[-2,-1],[-1,2],[-6,1],[0,2],[3,1],[4,3],[3,-1],[-1,-2],[0,-5]],[[257,8212],[-1,-1],[-1,0],[0,3],[1,1],[3,4],[2,-1],[1,-1],[-1,-1],[0,-2],[-1,-1],[-1,0],[-2,-1]],[[286,8228],[0,-3],[-1,0],[-4,1],[-3,-1],[0,2],[0,1],[5,2],[2,0],[1,-1],[0,-1]],[[9799,8237],[5,-2],[3,1],[5,-3],[5,-5],[-1,-1],[-2,-1],[-1,0],[-4,0],[-2,0],[-4,-4],[-5,3],[-1,5],[-4,1],[-2,2],[5,4],[3,0]],[[334,8256],[-8,-6],[-3,-4],[-2,-5],[-2,-2],[-1,0],[-1,-2],[-3,-3],[-1,0],[-9,-7],[-1,0],[0,2],[3,2],[2,3],[2,4],[1,1],[1,2],[0,4],[0,2],[2,3],[2,1],[1,1],[4,-1],[2,2],[0,1],[-1,1],[0,2],[0,3],[1,3],[2,2],[3,2],[3,2],[3,0],[4,-3],[1,-2],[-1,-2],[-1,-3],[-3,-3]],[[383,8278],[-1,1],[0,2],[0,1],[2,2],[1,1],[1,0],[0,-1],[-1,-2],[-1,-2],[-1,-2]],[[372,8288],[1,-2],[2,1],[2,3],[1,3],[1,1],[1,-2],[2,-2],[-2,-3],[-5,-5],[-1,-4],[0,-1],[4,1],[1,0],[1,-1],[-1,-2],[-2,-1],[-3,-2],[-5,-5],[-2,-3],[-2,-1],[-3,-1],[-5,-2],[-3,-2],[-1,-1],[-1,-1],[-2,0],[-1,-1],[-1,-2],[-1,-1],[-2,0],[-1,-1],[-2,0],[-3,3],[0,1],[2,3],[2,1],[3,0],[3,3],[6,3],[2,2],[2,6],[1,1],[1,3],[3,0],[2,-3],[0,-1],[0,1],[1,2],[1,2],[-1,1],[-3,1],[-2,1],[-2,0],[-1,1],[-1,1],[0,2],[0,2],[1,2],[1,2],[2,1],[3,1],[3,1],[2,0],[1,0],[1,-6]],[[393,8298],[-1,-1],[-1,0],[0,1],[-3,-1],[-1,0],[-1,4],[0,1],[0,2],[2,1],[2,1],[2,0],[3,-3],[2,-2],[0,-1],[-1,-1],[-3,-1]],[[401,8302],[-1,0],[-1,3],[-1,4],[2,1],[1,1],[1,-1],[1,-3],[1,-1],[1,-1],[-1,0],[-3,-3]],[[485,8317],[-3,-1],[-2,1],[-3,3],[0,3],[5,-2],[1,-1],[2,-3]],[[492,8343],[-1,0],[-2,1],[-1,2],[0,2],[4,3],[1,0],[0,-2],[0,-1],[-1,-4],[0,-1]],[[459,8351],[3,-10],[1,-2],[2,-1],[2,-1],[1,-1],[2,-2],[0,-1],[-8,3],[-5,-5],[-1,-1],[-14,0],[-2,-1],[-2,-2],[-3,-5],[-2,-2],[-1,-1],[-4,-2],[-4,1],[-2,0],[-2,3],[-1,4],[0,2],[1,2],[4,3],[1,2],[5,11],[1,1],[2,1],[4,-1],[3,3],[8,5],[2,1],[5,0],[2,-1],[1,-1],[1,-2]],[[573,8350],[-1,0],[-1,4],[-1,1],[2,-1],[1,-2],[0,-2]],[[569,8360],[0,-4],[-1,-1],[0,1],[-2,-1],[-1,1],[1,2],[0,1],[1,0],[0,2],[0,1],[0,2],[1,1],[1,-5]],[[1352,8356],[2,-7],[1,-3],[-3,-1],[-2,1],[-1,0],[-1,2],[1,4],[-1,2],[-2,1],[-1,-2],[-1,4],[2,3],[-1,3],[0,3],[0,1],[2,0],[3,-3],[2,-8]],[[559,8359],[-2,-1],[0,-2],[-1,0],[-2,-2],[-3,-6],[-2,-1],[2,5],[0,2],[0,1],[0,4],[1,0],[1,0],[1,4],[2,0],[2,4],[1,0],[-1,-3],[2,-2],[0,-2],[-1,-1]],[[1309,8346],[1,-1],[1,0],[1,2],[2,0],[1,-1],[1,0],[0,-3],[-1,-5],[-1,-2],[0,-2],[-3,1],[-3,3],[-3,5],[-2,4],[0,2],[-1,1],[-2,7],[-2,5],[-2,0],[-2,2],[-1,3],[1,2],[3,1],[6,-6],[1,-3],[2,-3],[0,-4],[1,-2],[2,-6]],[[546,8371],[0,-4],[-4,3],[-1,1],[1,1],[3,0],[1,-1]],[[536,8370],[1,0],[1,0],[2,4],[0,-1],[-1,-4],[2,-4],[1,-2],[0,-1],[-3,-1],[-3,1],[-1,0],[-2,-2],[0,2],[-1,8],[0,1],[2,3],[1,1],[1,0],[1,-1],[0,-2],[-1,-2]],[[1297,8383],[1,-2],[0,-1],[-4,-3],[0,-1],[-1,-3],[-1,0],[-2,-3],[-3,-3],[1,9],[-3,4],[3,3],[2,-1],[3,0],[3,2],[1,-1]],[[679,8399],[-1,-2],[-3,0],[-1,1],[0,2],[3,4],[1,1],[1,-2],[0,-4]],[[1362,8380],[-1,-6],[-2,-7],[-3,-3],[-2,0],[-2,3],[-1,0],[-2,1],[-1,2],[1,3],[0,2],[-1,-2],[-2,-2],[-3,-2],[-2,-5],[-1,-3],[-2,4],[0,7],[-1,4],[3,5],[3,4],[1,15],[10,7],[0,-1],[4,-5],[3,-7],[1,-4],[0,-6],[0,-4]],[[1290,8429],[5,-1],[5,0],[1,-3],[2,-2],[0,-3],[0,-2],[0,-1],[0,-2],[0,-1],[9,-5],[5,-6],[1,-3],[1,-2],[2,-7],[4,-7],[2,-2],[1,-3],[-3,2],[-6,5],[-1,-3],[-1,-2],[-1,-2],[1,-1],[5,2],[4,-5],[1,-1],[2,-4],[0,-1],[-1,-3],[-1,-1],[2,-1],[4,1],[1,-1],[-1,-10],[1,-4],[0,-2],[-1,-2],[0,-2],[1,-2],[0,-2],[-1,-4],[-2,-1],[-2,0],[-1,1],[-2,4],[-2,6],[-1,1],[-3,1],[0,1],[-2,0],[-1,2],[0,4],[-1,3],[0,2],[-1,0],[-1,-1],[0,-3],[0,-3],[-3,2],[-3,8],[-4,6],[-2,2],[1,1],[2,1],[1,0],[1,1],[-4,7],[0,2],[2,3],[-2,1],[-4,-1],[-2,1],[-1,2],[-1,2],[-4,1],[-1,0],[-2,3],[-1,2],[0,1],[2,2],[2,0],[2,-2],[1,0],[2,2],[1,3],[2,2],[-1,2],[-1,3],[-2,1],[-5,-2],[-4,-3],[-1,1],[-1,2],[5,6],[2,3],[-1,1],[-1,3],[0,6],[1,1]],[[1312,8424],[-2,-1],[-2,1],[-4,5],[0,1],[1,2],[2,3],[1,0],[6,0],[1,-1],[1,-1],[0,-1],[-1,-2],[0,-1],[0,-2],[0,-1],[-3,-2]],[[1330,8416],[0,-10],[-2,1],[-1,0],[-2,-2],[-2,1],[-1,1],[0,1],[0,3],[-1,2],[-5,0],[-1,1],[-1,3],[0,4],[0,1],[3,1],[1,5],[1,1],[4,9],[1,-1],[3,-5],[4,-9],[-1,-7]],[[703,8434],[-2,-1],[0,1],[0,1],[0,1],[1,2],[3,4],[3,2],[1,0],[1,-2],[-2,-3],[-5,-5]],[[716,8439],[-1,0],[-2,1],[0,2],[3,2],[3,0],[0,-1],[0,-2],[-1,-1],[-2,-1]],[[285,8446],[3,-1],[2,0],[2,0],[0,-1],[-3,-3],[-1,0],[-4,3],[1,2]],[[1312,8440],[0,-1],[-3,0],[-2,1],[0,2],[0,2],[1,2],[1,3],[1,6],[5,-6],[2,-3],[0,-4],[-1,-1],[-3,0],[-1,-1]],[[1278,8458],[2,-4],[2,0],[2,-3],[1,-4],[-1,-3],[-1,1],[-1,-2],[-1,-6],[0,-5],[0,-6],[-2,-6],[0,-3],[-1,-1],[0,-1],[-1,1],[-1,1],[-2,-3],[-2,0],[-1,7],[1,12],[3,3],[-2,3],[-3,4],[0,2],[-3,6],[0,1],[0,6],[3,4],[4,1],[2,-2],[2,-2],[0,-1]],[[1295,8467],[2,-2],[1,2],[2,0],[3,-2],[3,-2],[1,-3],[0,-2],[-1,-4],[1,-4],[0,-2],[-1,-1],[-1,-2],[-1,0],[-2,4],[-3,6],[-3,2],[0,-1],[1,-1],[2,-4],[0,-2],[1,-3],[1,-1],[0,-3],[0,-2],[0,-2],[-1,-1],[0,-1],[-5,1],[-3,-2],[-3,1],[-1,1],[-1,2],[0,5],[-1,6],[1,5],[-3,5],[-1,3],[-3,2],[-2,2],[1,2],[2,2],[5,0],[9,-4]],[[750,8474],[-4,-2],[-3,-3],[-1,-2],[-2,3],[0,5],[2,3],[10,-1],[0,-1],[0,-1],[0,-1],[-2,0]],[[273,8478],[-3,-3],[-2,1],[-1,2],[0,1],[8,2],[-2,-3]],[[1251,8487],[2,-6],[2,-5],[1,-6],[3,-12],[1,-5],[0,-2],[1,-7],[-1,-1],[0,-2],[-1,-2],[1,-5],[0,-7],[-1,-5],[-2,1],[-2,3],[-1,2],[-3,8],[-1,3],[0,3],[1,2],[1,1],[1,3],[-1,0],[-3,-1],[-2,3],[-2,1],[1,5],[-1,1],[-3,-2],[-1,2],[-1,1],[0,3],[1,2],[3,5],[0,1],[-2,1],[-2,2],[-1,6],[-2,3],[-1,0],[-3,-10],[-2,-2],[-4,-2],[1,3],[1,3],[-2,7],[0,3],[1,2],[3,1],[2,1],[1,2],[0,2],[2,6],[1,1],[3,0],[6,-6],[2,-1],[3,-4]],[[743,8516],[-1,-2],[0,1],[-2,2],[-3,2],[-1,2],[-1,1],[2,1],[3,-2],[2,-2],[1,-3]],[[753,8514],[0,-3],[1,1],[4,3],[3,1],[2,0],[3,-2],[0,-1],[0,-1],[-2,-3],[0,-2],[2,-3],[5,-2],[1,-1],[0,-1],[-4,-5],[-1,-2],[-1,0],[-6,1],[-5,2],[-3,0],[-2,-2],[1,-1],[5,0],[2,-2],[0,-2],[1,-2],[-1,-1],[-2,-1],[-3,0],[-3,-2],[-2,-2],[-6,-1],[-4,-3],[-2,-2],[-1,-2],[-1,-2],[-4,-1],[2,-1],[0,-1],[0,-2],[0,-1],[-3,-6],[-6,-5],[-2,0],[0,1],[-1,1],[0,1],[8,9],[0,1],[-3,0],[-3,3],[-2,-2],[-1,0],[1,2],[1,3],[0,1],[-1,1],[-2,0],[-3,0],[-2,0],[-1,-2],[0,-1],[3,1],[1,-1],[0,-1],[1,-2],[0,-2],[-1,-2],[-1,-3],[-2,0],[-5,7],[-2,10],[-3,7],[-1,2],[1,5],[4,6],[4,2],[3,3],[3,0],[2,0],[2,-1],[1,-2],[0,-1],[0,-1],[2,-2],[1,-5],[3,-4],[1,-2],[2,-2],[-2,4],[-1,4],[-1,9],[0,3],[1,0],[3,0],[0,1],[-4,3],[-1,3],[-1,1],[0,2],[2,3],[1,0],[1,1],[2,-1],[1,-1],[2,-5],[1,-2],[1,0],[1,1],[1,2],[1,1],[1,0],[3,-1],[1,1],[0,1],[0,3],[1,1],[0,1],[-1,3],[1,1],[7,-2],[2,-2],[-1,-5]],[[1230,8539],[4,-6],[0,-1],[-1,-4],[-2,-1],[0,-2],[2,-1],[1,1],[4,5],[1,2],[1,0],[5,-2],[5,-3],[1,-2],[1,-3],[-1,-8],[-4,-1],[-2,0],[-2,1],[-3,-3],[3,-2],[7,0],[3,-5],[0,-3],[-1,-6],[-4,1],[-4,4],[-8,5],[-2,0],[-1,-1],[0,-3],[0,-6],[-2,-4],[-6,2],[-3,5],[-2,8],[-8,9],[-3,2],[-3,6],[2,4],[0,3],[1,1],[3,2],[1,4],[2,-3],[3,-4],[0,3],[1,3],[3,0],[2,0],[1,3],[3,1],[2,-1]],[[1269,8538],[0,-2],[-4,0],[-4,3],[-2,2],[1,2],[3,1],[4,-3],[2,-3]],[[1259,8534],[7,-1],[5,0],[5,-9],[3,-7],[1,-5],[1,-4],[2,-5],[-1,-1],[-2,4],[-2,6],[-1,2],[-1,1],[-1,3],[-2,5],[0,2],[-1,2],[-1,0],[-1,0],[-1,-1],[0,-4],[1,-4],[5,-10],[4,-6],[0,-2],[1,-5],[-2,-2],[2,-5],[0,-1],[0,-1],[-5,-2],[-5,-9],[-4,-5],[-3,-1],[-1,1],[-1,2],[0,3],[-1,3],[2,2],[2,11],[0,4],[-3,5],[-2,4],[-1,5],[-1,15],[-1,5],[-1,4],[-2,3],[-1,4],[0,3],[0,2],[2,-2],[3,-6],[2,-3]],[[766,8545],[1,0],[1,3],[1,0],[3,-3],[2,1],[2,-4],[1,0],[1,1],[0,-1],[0,-3],[-2,-4],[-1,-1],[-2,1],[-2,2],[0,2],[-1,0],[-2,-3],[0,-1],[1,-2],[0,-1],[-2,0],[-2,0],[-2,-2],[-1,1],[0,3],[-1,0],[-1,-4],[-1,-2],[-3,-2],[0,-1],[-2,0],[-2,-1],[-2,0],[-9,4],[-2,2],[8,8],[4,4],[2,-1],[2,-1],[1,1],[0,3],[-2,3],[0,1],[5,2],[2,0],[2,-1],[1,-1],[2,-3]],[[764,8552],[-1,0],[-2,2],[-1,2],[1,1],[4,3],[2,0],[1,-1],[0,-2],[-1,-1],[-3,-4]],[[530,8558],[-2,-1],[-2,0],[-2,6],[1,0],[3,4],[6,3],[2,0],[-6,-12]],[[984,8629],[-1,0],[2,4],[3,4],[2,2],[3,2],[0,-2],[-4,-4],[-5,-6]],[[888,8643],[-1,-1],[-6,1],[1,3],[5,2],[4,-3],[-3,-2]],[[896,8629],[-3,-1],[-1,2],[2,4],[1,2],[1,1],[4,5],[4,3],[3,5],[4,8],[1,2],[1,1],[3,-2],[2,-3],[-1,-2],[-9,-10],[-1,-1],[-1,-4],[-1,-1],[-1,-1],[-1,-1],[0,-3],[-1,-1],[-2,0],[-1,-1],[-1,-1],[-2,-1]],[[385,8662],[3,-3],[1,0],[4,1],[2,-1],[1,-1],[1,-2],[0,-3],[0,-3],[0,-5],[0,-1],[2,-3],[1,-3],[0,-3],[-5,-1],[-5,-1],[-4,-2],[-1,-2],[1,-2],[-1,-1],[-1,1],[-2,2],[-3,1],[-8,2],[-10,7],[-4,1],[-4,5],[-4,7],[3,1],[2,0],[12,-1],[1,5],[2,1],[3,1],[4,3],[1,0],[2,-1],[3,1],[2,1],[1,-1]],[[969,8659],[-1,-1],[-2,0],[-2,1],[5,4],[0,-1],[0,-3]],[[933,8666],[1,-2],[5,0],[2,0],[1,-1],[-1,-1],[-2,-1],[-6,-3],[-5,-3],[-1,0],[-1,4],[-1,1],[0,2],[0,1],[1,2],[2,2],[1,0],[4,-1]],[[898,8666],[0,-2],[-1,-1],[1,-3],[-1,-5],[-1,-3],[-1,-1],[0,-1],[-1,0],[0,1],[0,2],[-2,0],[0,4],[1,1],[0,2],[0,1],[2,5],[0,1],[0,-2],[1,0],[1,3],[1,-2]],[[777,8661],[-1,-1],[2,3],[1,6],[1,-1],[1,-1],[-3,-6],[-1,0]],[[202,8666],[6,-4],[3,1],[3,-4],[2,-2],[-5,2],[-6,0],[-9,7],[-4,2],[1,4],[4,3],[1,-6],[4,-3]],[[891,8687],[-4,0],[-1,1],[-1,0],[1,3],[0,1],[2,1],[2,-1],[0,-2],[1,-3]],[[237,8849],[1,-1],[2,0],[5,0],[4,-2],[4,1],[6,4],[3,1],[4,1],[3,-1],[4,-3],[1,-1],[1,-2],[1,-3],[1,-2],[7,-3],[4,-1],[1,-1],[1,-2],[4,-1],[3,0],[2,0],[7,0],[7,-3],[-1,-5],[-2,-3],[-7,1],[-8,-1],[-3,-3],[-2,-3],[0,-4],[-2,-1],[-1,-1],[-1,2],[-2,6],[-1,2],[-1,1],[-4,1],[-3,2],[-3,0],[-1,2],[-1,3],[-1,1],[-3,3],[-3,1],[-9,4],[-3,1],[-3,-1],[-3,-2],[-3,-2],[-3,-2],[-3,0],[-4,1],[-3,2],[-1,2],[-1,3],[0,3],[1,3],[1,7],[3,1],[5,-5]],[[386,8998],[-1,0],[0,1],[3,2],[6,3],[-4,-3],[-4,-3]],[[1388,8403],[-1,-3],[-1,-3],[-1,-4],[0,-4],[0,-4],[0,-3],[2,-7],[1,-3],[0,-3],[-4,-9],[-1,-5],[0,-2]],[[1373,8338],[-1,2],[-7,1],[-2,8],[-1,6],[-2,6],[0,1],[1,4],[7,3],[0,1],[-2,1],[-1,1],[-1,6],[0,5],[0,4],[-1,7],[-1,4],[-5,9],[0,2],[2,3],[1,2],[-7,-4],[-10,-5],[-4,-3],[-1,-1],[0,-1],[1,-3],[0,-1],[-1,-2],[-1,-5],[-2,-5],[-1,-1],[-4,2],[-1,1],[-2,7],[0,2],[2,2],[2,3],[2,5],[5,14],[2,0],[6,2],[-8,2],[-2,0],[-1,2],[-1,3],[-1,3],[-3,1],[-2,2],[-2,3],[-1,2],[-1,2],[0,3],[-1,1],[-2,1],[-1,1],[0,6],[-5,2],[-1,2],[-3,4],[-1,2],[0,2],[1,4],[-1,1],[-2,0],[-16,7],[1,9],[-3,13],[-3,5],[1,2],[1,1],[1,0],[6,-4],[5,-4],[1,1],[-9,9],[-2,3],[0,3],[0,2],[0,1],[9,-1],[-8,3],[-2,0],[-2,-4],[-1,-1],[-2,1],[-2,5],[-2,3],[-4,5],[-1,3],[0,5],[0,4],[3,10],[2,2],[0,1],[-1,0],[-1,-1],[-2,-5],[-3,-7],[-2,-3],[-2,1],[-2,3],[-4,4],[-5,1],[-3,4],[-5,11],[0,5],[-1,2],[-2,1],[-2,3],[-2,14],[-3,9],[-1,5],[0,5],[-1,-4],[-1,-2],[-2,0],[2,-4],[1,-2],[-1,0],[-2,0],[3,-7],[2,-10],[2,-8],[1,-6],[1,-5],[1,-4],[2,-10],[0,-2],[0,-1],[-1,-2],[-1,-1],[-5,1],[-1,3],[-3,4],[-3,2],[-8,-1],[-1,1],[0,3],[1,7],[-1,2],[-4,10],[0,2],[6,4],[-3,1],[-2,-2],[-1,1],[-2,6],[-1,2],[0,1],[0,-6],[1,-3],[0,-2],[0,-2],[-1,-2],[-1,-1],[-1,0],[-2,1],[-2,2],[-2,1],[-1,1],[-1,3],[-2,2],[-7,2],[-4,3],[-1,-1],[2,-3],[0,-2],[-1,0],[-2,-3],[0,-1],[2,1],[3,0],[4,-2],[3,-2],[1,-1],[1,-2],[0,-1],[4,-2],[0,-1],[-2,-4],[4,0],[3,-1],[3,-5],[1,-3],[1,-4],[-1,-2],[-1,0],[-10,-2],[-3,-4],[-1,0],[-2,1],[-5,4],[-6,3],[-13,11],[0,3],[-1,1],[-2,1],[-3,2],[-3,5],[-2,3],[0,3],[-2,3],[-6,6],[-3,2],[-3,1],[-2,1],[-1,1],[1,1],[0,1],[-5,1],[-5,3],[-13,8],[-6,5],[-4,2],[-2,1],[0,2],[1,1],[2,1],[2,1],[3,5],[0,2],[-2,4],[0,3],[0,2],[0,2],[0,1],[2,1],[0,1],[1,-1],[4,-4],[0,-2],[0,-6],[1,-8],[0,1],[0,2],[1,5],[0,2],[1,2],[1,1],[3,0],[2,0],[-7,4],[-4,6],[-1,0],[-3,1],[-2,-3],[-7,-8],[-2,-1],[-8,-5],[-6,-1],[-6,1],[-5,1],[-14,7],[-2,2],[3,5],[0,1],[-1,4],[-1,2],[-1,0],[0,-1],[0,-3],[-1,-1],[-2,-2],[-4,-1],[-12,4],[-13,3],[-11,0],[-15,-2],[-9,-3],[-5,0],[-4,1],[-1,1],[3,1],[-1,2],[-2,3],[-4,3],[-6,1],[-3,1],[-1,1],[-2,1],[-3,2],[-1,2],[1,7],[1,4],[1,3],[3,5],[-1,0],[-4,-4],[-3,-3],[-4,-5],[-1,-2],[-3,-2],[-3,0],[-6,3],[-4,2],[-3,0],[-2,0],[3,3],[1,2],[2,4],[0,1],[-13,1],[0,2],[0,1],[-1,1],[-2,1],[-2,-1],[-5,-2],[-1,2],[0,1],[2,0],[2,3],[-3,2],[-2,2],[-1,1],[0,6],[1,3],[8,4],[-2,1],[-6,0],[-4,-3],[-4,-4],[-3,-2],[-1,1],[-2,0],[-3,0],[-1,-1],[-1,-2],[-1,-1],[-1,-1],[-1,1],[-1,1],[-3,2],[-1,1],[-1,-1],[-1,-3],[-1,-1],[-4,-1],[-2,0],[-3,3],[0,1],[1,3],[6,12],[-1,0],[-2,-2],[-4,-5],[-2,-1],[-3,0],[-1,0],[-2,0],[-2,-1],[-1,-2],[-1,-1],[1,0],[3,1],[2,1],[0,-1],[-2,-5],[-2,-5],[-1,-1],[-2,0],[-3,-1],[0,-1],[5,-4],[1,-1],[2,-1],[1,-1],[-1,-4],[-1,-2],[-1,0],[-3,0],[-1,-1],[-3,-2],[-1,-2],[3,1],[3,1],[4,0],[3,1],[1,2],[2,-1],[2,-2],[1,-2],[-1,-2],[-1,-2],[-3,0],[-1,-2],[-1,-1],[0,-3],[0,-3],[0,-6],[-1,-1],[-1,0],[-1,-1],[-3,-8],[-1,-1],[-1,1],[-1,0],[-1,-1],[-2,-1],[-3,0],[-3,0],[-4,2],[-2,1],[-1,2],[-4,-2],[-1,0],[-3,6],[0,-1],[-1,-5],[-1,-2],[-2,-4],[-2,-8],[0,1],[-2,7],[-1,1],[-2,-4],[0,-1],[0,-5],[-5,2],[-1,0],[1,-4],[0,-1],[-6,-7],[-2,0],[-1,1],[-1,0],[-4,-3],[-1,0],[-2,2],[-1,0],[0,-2],[0,-3],[-2,-3],[-4,-5],[-2,-2],[-1,-4],[-3,2],[-4,1],[1,-2],[0,-1],[-2,-1],[-2,0],[-2,1],[-3,-1],[-4,-2],[-3,0],[-5,4],[-1,0],[0,2],[1,3],[1,2],[1,2],[4,3],[5,1],[3,2],[4,4],[2,3],[4,8],[-1,1],[-9,-8],[-1,0],[-2,0],[-7,2],[-1,2],[-1,3],[2,8],[1,4],[3,6],[5,6],[1,5],[3,11],[0,5],[-1,6],[0,3],[1,1],[10,6],[5,4],[9,7],[3,0],[1,-3],[3,-1],[2,-2],[3,1],[4,1],[6,0],[13,-5],[3,0],[0,1],[-2,3],[-9,1],[-3,2],[-11,7],[-2,3],[1,1],[2,2],[1,1],[1,1],[1,3],[3,3],[3,3],[8,5],[-3,0],[-5,-1],[-2,-1],[-4,-3],[-1,-2],[-2,-5],[-1,-1],[-4,0],[-10,-1],[-2,3],[-2,0],[-9,-6],[-3,-3],[-3,-4],[-3,-2],[-5,-2],[-4,-2],[-4,-4],[-1,-3],[0,-1],[1,-5],[-1,-1],[-3,0],[-3,-3],[-8,-9],[-1,-3],[0,-1],[1,-3],[0,-1],[-3,-3],[-4,-4],[-3,-2],[-2,0],[-2,1],[-4,3],[-3,0],[0,-1],[4,-2],[4,-4],[2,-3],[1,-2],[0,-3],[-1,-2],[-2,-5],[-3,-1],[-7,-1],[-2,-2],[-1,0],[5,-2],[0,-1],[0,-4],[-2,-1],[-4,-2],[-3,-1],[-1,1],[1,2],[0,1],[-2,1],[-1,-1],[-5,-5],[-1,0],[2,-1],[0,-1],[-3,-3],[-1,-3],[-2,-2],[-7,-6],[0,-2],[-2,-5],[-1,-5],[2,-2],[6,-2],[3,-1],[4,-2],[6,-4],[3,-3],[0,-2],[0,-1],[-1,-2],[-2,-4],[-5,-6],[-2,-1],[-4,-2],[-1,-1],[-4,-5],[-2,-3],[1,-3],[-1,-1],[-6,-4],[0,-1],[2,0],[0,-3],[-1,-4],[-1,-1],[-3,0],[-5,-2],[0,-3],[-12,-3],[-2,-5],[-2,-2],[-4,-5],[-3,-1],[-3,-1],[-2,-2],[0,-2],[-1,-1],[-3,-3],[-1,-3],[-1,-1],[-5,-1],[-1,-1],[-1,-4],[-1,0],[-2,1],[-2,-1],[-6,-5],[-1,-2],[0,-1],[1,-1],[2,-3],[-1,-2],[-2,-6],[0,-1],[-3,-1],[-1,-4],[-2,1],[-2,-1],[-1,-2],[-2,-1],[-1,0],[-2,-2],[-2,-3],[-2,-2],[-2,-1],[-2,0],[-1,0],[-2,0],[-1,-1],[-2,-2],[-1,-5],[-1,-2],[-1,-1],[-2,1],[-3,1],[-2,-1],[-5,-3],[-1,-2],[3,0],[1,-1],[0,-1],[-1,0],[-3,0],[-1,-1],[-2,-1],[-5,-2],[-1,-1],[-4,-5],[0,-2],[2,1],[2,-1],[2,-2],[0,-1],[1,-3],[-4,-5],[-1,-2],[-1,-1],[-1,6],[0,1],[-1,0],[-1,-2],[-3,-6],[-2,-3],[-18,-9],[-2,-2],[-1,-3],[0,-3],[-2,-3],[-1,-1],[0,1],[0,8],[-1,2],[-1,1],[-1,0],[-1,0],[-2,-2],[-1,-1],[-1,0],[-3,-1],[-5,-6],[-4,-2],[-1,-1],[-1,-3],[-1,-1],[-2,0],[-2,1],[-1,-1],[-2,-3],[-1,0],[-3,1],[-2,-1],[-2,-3],[-2,-2],[-2,-1],[-6,-1],[-2,1],[-1,1],[0,3],[1,3],[1,2],[1,1],[2,0],[3,-1],[0,1],[-1,1],[-3,2],[-3,1],[-2,-1],[-2,-1],[-1,-2],[-1,-2],[-1,-6],[-1,-2],[-6,-11],[-3,-3],[-3,0],[-1,-1],[-2,-3],[-1,-1],[-2,0],[-1,0],[-1,1],[0,1],[1,1],[0,2],[-2,4],[-1,2],[-3,0],[0,-2],[1,-8],[0,-2],[-2,-2],[-4,-3],[-1,0],[-4,5],[-3,1],[0,-1],[0,-4],[0,-3],[-3,-3],[-2,-2],[-1,0],[0,3],[1,4],[0,3],[0,3],[0,2],[0,2],[5,4],[2,1],[1,-2],[1,0],[2,1],[1,1],[0,2],[2,3],[4,3],[4,6],[4,8],[6,7],[6,6],[6,5],[14,7],[1,-1],[-1,-2],[0,-1],[2,0],[5,1],[2,1],[0,-1],[-1,-2],[-3,-2],[1,-1],[4,-7],[1,-1],[1,0],[1,1],[-1,5],[2,1],[3,0],[2,-1],[1,-1],[1,-1],[3,-1],[1,0],[1,2],[-1,2],[-5,4],[-1,1],[0,3],[0,3],[2,4],[2,6],[2,4],[4,5],[3,2],[7,8],[14,7],[4,5],[5,5],[2,1],[0,-2],[0,-2],[3,-1],[2,0],[1,0],[1,2],[-1,3],[0,4],[0,3],[1,2],[2,4],[3,5],[4,6],[3,3],[2,1],[3,2],[4,6],[1,1],[3,1],[1,0],[1,-2],[1,0],[3,-1],[2,1],[0,1],[-2,0],[-1,1],[-1,4],[-2,2],[-1,2],[1,4],[2,8],[0,9],[1,6],[4,1],[6,2],[-4,2],[-1,0],[-3,1],[-1,6],[0,4],[2,4],[6,8],[8,6],[-1,0],[-1,2],[3,11],[3,10],[-4,-9],[-5,-6],[-15,-7],[-10,-7],[-4,-1],[-3,1],[-3,6],[-1,3],[-2,3],[1,6],[1,3],[3,1],[4,-2],[3,0],[-4,3],[-6,3],[-2,-1],[-2,-5],[-3,-3],[-2,1],[-1,2],[1,-5],[-2,-6],[-1,-4],[3,-12],[-1,-4],[-4,-2],[-4,4],[-8,14],[-2,4],[-6,7],[-2,-1],[-3,-3],[-2,-1],[-7,5],[-3,3],[-3,5],[-4,-2],[-4,-3],[-4,-5],[-3,0],[-8,-4],[-1,0],[-1,-3],[-1,-1],[-1,-4],[-11,-3],[-11,2],[4,2],[4,2],[4,4],[-2,6],[0,3],[0,4],[4,5],[-4,0],[-3,-2],[-3,5],[-1,7],[3,5],[2,4],[1,5],[0,4],[-3,7],[-6,16],[-3,11],[-5,6],[4,10],[4,9],[5,4],[0,1],[-3,0],[-2,-1],[-2,-3],[-1,-2],[-6,-12],[-4,-5],[-2,-2],[4,-2],[0,-2],[1,-4],[-1,-5],[-1,-3],[-4,0],[-4,-4],[-10,-4],[-13,-3],[-6,1],[-7,5],[0,3],[1,2],[-10,9],[-5,9],[-4,0],[-3,3],[-4,3],[0,3],[1,3],[-3,1],[-3,0],[-3,1],[9,11],[3,8],[3,1],[3,-1],[5,-3],[4,-1],[2,-2],[1,-3],[-2,-4],[-1,-3],[2,1],[5,5],[3,4],[2,-1],[1,0],[2,-5],[3,-4],[5,4],[3,5],[-2,3],[-3,1],[-8,2],[2,1],[5,0],[2,2],[-2,2],[-3,2],[-6,-6],[-13,0],[-9,3],[-8,0],[-2,0],[-1,2],[5,5],[3,2],[0,2],[-2,0],[-4,-1],[-1,2],[0,3],[-1,0],[-1,-2],[-2,1],[-2,2],[1,1],[2,3],[-1,0],[-2,0],[-1,-3],[0,-3],[0,-4],[-3,0],[-2,0],[-2,4],[-2,8],[-4,2],[-2,4],[3,5],[-1,2],[-3,1],[-4,-3],[-1,3],[-1,2],[0,4],[1,0],[1,-1],[7,2],[1,1],[-6,3],[-1,4],[2,1],[4,1],[7,1],[-3,4],[-1,2],[0,3],[1,5],[7,11],[7,10],[2,2],[4,2],[3,-1],[3,-2],[0,1],[-1,0],[-1,4],[4,2],[3,4],[0,2],[-3,-2],[-3,-3],[0,3],[-1,7],[1,7],[1,3],[3,3],[7,1],[1,-1],[0,2],[-4,4],[2,3],[1,2],[8,3],[5,-1],[6,-3],[3,-4],[0,-2],[-1,-1],[-2,-2],[-1,-1],[1,-1],[2,3],[4,3],[2,-2],[2,-2],[2,0],[6,2],[4,2],[4,5],[5,4],[7,11],[2,4],[3,1],[2,-1],[1,-3],[3,-1],[13,0],[6,2],[5,4],[5,6],[3,4],[1,5],[-2,6],[-2,6],[-2,13],[-6,8],[-5,2],[-3,0],[2,5],[6,0],[4,1],[4,2],[1,2],[1,4],[0,5],[-1,2],[-2,2],[-3,4],[-2,1],[-1,0],[-8,-7],[-5,0],[-3,1],[-3,-4],[-9,-4],[-4,-4],[-9,-9],[-2,-4],[-2,0],[-2,8],[-9,8],[-3,-3],[1,-2],[2,-2],[4,-1],[-2,-2],[-1,-3],[-3,2],[-6,5],[-7,2],[-16,0],[-11,-5],[-1,1],[-1,1],[-2,-1],[0,-2],[-2,-1],[-2,-1],[-4,1],[-9,3],[-19,4],[-5,2],[-5,6],[1,4],[2,2],[-1,5],[-3,2],[-8,8],[-3,4],[1,0],[1,-1],[3,-1],[6,2],[2,5],[5,1],[4,0],[-1,1],[-1,1],[-11,3],[-2,-1],[-20,5],[-16,8],[-2,2],[-1,4],[2,3],[2,2],[0,-2],[1,-2],[9,4],[5,6],[9,1],[2,2],[3,3],[4,5],[6,3],[4,3],[5,1],[4,-2],[2,-1],[8,0],[2,1],[1,1],[1,1],[-8,4],[1,3],[1,2],[9,5],[7,2],[4,0],[11,6],[6,2],[11,1],[9,1],[2,-3],[-4,1],[-3,-1],[2,0],[2,-2],[-1,-2],[-3,-7],[0,-5],[-2,-2],[-2,-2],[10,-8],[14,0],[8,1],[5,-2],[4,-1],[10,1],[8,-1],[3,0],[7,12],[3,2],[3,-2],[4,-2],[3,1],[2,-3],[-1,6],[-2,3],[-11,4],[-8,-2],[-3,2],[1,5],[-8,11],[-4,3],[-4,0],[-2,4],[-2,5],[4,2],[3,1],[3,-2],[3,-7],[3,-1],[0,-6],[3,-6],[9,-6],[7,2],[5,0],[3,-1],[8,-6],[3,0],[12,3],[0,5],[-1,3],[-3,3],[-7,-1],[-6,4],[-6,-1],[-9,-6],[-5,2],[-3,3],[-5,4],[-1,6],[4,6],[3,4],[-2,2],[-7,2],[-12,-2],[0,2],[0,3],[-5,-5],[-5,1],[-7,-1],[-15,5],[-5,5],[-2,5],[-4,11],[-5,8],[-35,25],[-16,6],[-8,8],[-5,1],[-4,1],[-6,2],[4,3],[3,1],[-3,-3],[2,-1],[3,2],[2,2],[3,9],[3,12],[-1,5],[19,-1],[13,1],[5,1],[16,2],[4,2],[8,4],[9,8],[8,10],[1,3],[1,-1],[1,0],[1,4],[1,9],[4,9],[16,19],[8,8],[3,3],[2,3],[2,-3],[1,0],[1,-1],[-2,-1],[-3,-2],[-3,-2],[-1,-1],[2,0],[6,2],[4,2],[18,4],[10,7],[0,1],[14,9],[2,-1],[3,-1],[-4,-5],[2,-2],[-2,-6],[5,0],[1,-3],[1,2],[-1,4],[1,4],[1,2],[3,-1],[9,3],[-10,0],[-6,6],[-4,0],[11,9],[11,5],[2,0],[1,-1],[0,-1],[-2,-1],[-2,-2],[1,-2],[1,0],[5,1],[2,2],[11,0],[3,1],[1,1],[13,0],[3,1],[8,5],[8,6],[3,3],[7,8],[5,5],[9,5],[2,-1],[-3,-1],[-2,-2],[3,-3],[18,-6],[4,0],[2,-4],[-1,-3],[-5,-4],[-9,-4],[2,-1],[2,-4],[3,0],[5,1],[3,2],[8,7],[2,4],[2,1],[6,-1],[3,-2],[4,-3],[-1,-4],[-2,-2],[6,-2],[5,-1],[6,-2],[7,4],[6,1],[6,0],[7,2],[13,-3],[3,1],[5,-1],[5,-2],[2,-2],[-5,-4],[-1,-5],[2,-2],[3,0],[1,-3],[2,0],[11,0],[-1,-1],[0,-2],[-4,-3],[20,-2],[3,2],[4,0],[9,3],[3,-1],[4,-3],[4,0],[3,0],[8,4],[9,0],[4,-1],[4,1],[11,-5],[5,0],[5,-6],[3,0],[4,2],[3,0],[3,-2],[4,-1],[3,-3],[2,-2],[18,-2],[9,1],[13,-1],[6,-1],[6,0],[11,-6],[6,-1],[1,-2],[16,-1],[5,3],[10,1],[9,3],[5,0],[6,-1],[2,0],[2,1],[14,-4],[8,-6],[3,-4],[17,-6],[5,-3],[3,-3],[2,-1],[1,1],[6,0],[2,0]],[[3296,5915],[-1,0],[1,1],[0,1],[0,-1],[0,-1]],[[3299,5932],[0,-1],[-1,1],[1,0],[0,1],[-1,0],[0,1],[1,0],[0,1],[1,1],[0,-1],[-1,-1],[0,-2]],[[3300,5942],[0,-1],[-2,4],[0,4],[1,3],[1,1],[1,0],[1,-3],[-1,-6],[-1,-2]],[[3305,5695],[-1,-2],[-1,6],[1,2],[3,4],[1,1],[0,-1],[0,-1],[1,-2],[0,-3],[-1,-3],[-3,-1]],[[3310,5710],[-3,-2],[0,2],[1,2],[2,1],[0,1],[1,1],[1,0],[1,-1],[-2,-2],[-1,-2]],[[3188,5812],[-1,-1],[-3,1],[-1,2],[0,2],[3,0],[2,-3],[0,-1]],[[3226,5825],[1,-8],[0,-1],[-3,-5],[-2,0],[-2,0],[-1,1],[-2,3],[-1,-1],[-4,1],[-1,1],[1,4],[3,2],[1,0],[1,-2],[2,-2],[2,-1],[1,4],[3,6],[1,-2]],[[3019,5867],[-1,-3],[-2,-3],[-2,-2],[-11,-5],[-1,-2],[-1,-2],[0,-5],[0,-4],[3,-13],[1,-3],[5,-7],[-1,-1],[-2,0],[1,-9],[3,-6],[0,-4],[-2,-13],[-4,-7],[-2,-9],[-2,-3],[-4,-17],[3,-10],[0,-5],[3,-7],[2,-3],[1,-2],[0,-5],[1,-7],[1,-4],[2,-1],[3,0],[6,4],[2,2],[1,4],[3,7],[0,10],[1,11],[-1,7],[-3,11],[-2,7],[-3,7],[-2,12],[-1,3],[-1,6],[-1,9],[3,3],[-1,7],[6,2],[12,12],[8,3],[9,7],[2,3],[2,5],[1,1],[4,-5],[3,2],[1,4],[-2,7],[-2,0],[-8,-3],[-1,4],[0,2],[-2,9],[1,7],[2,6],[2,2],[3,2],[3,-3],[1,-4],[1,-3],[1,-9],[1,-10],[1,-6],[2,-5],[2,0],[1,1],[9,1],[5,-3],[6,-2],[6,-7],[6,-8],[1,-7],[1,-6],[1,-4],[-1,-4],[1,-7],[1,-6],[3,-5],[7,-1],[8,3],[13,3],[4,2],[20,1],[4,-3],[1,-3],[0,-3],[6,-12],[6,-2],[5,-4],[4,-2],[6,-3],[2,0],[3,1],[2,0],[19,21],[10,0],[1,1],[1,2],[-3,3],[-8,1],[-3,-2],[-1,5],[2,0],[9,2],[11,-1],[8,4],[5,0],[2,0],[7,2],[13,-3],[10,2],[-1,-3],[-4,-2],[-5,-1],[-4,-5],[-9,1],[-6,-2],[2,-1],[0,-5],[1,-1],[1,0],[2,-4],[0,-3],[1,-5],[-1,-5],[-1,-3],[2,1],[2,3],[0,2],[0,3],[1,-1],[1,-1],[3,-15],[3,-8],[0,1],[1,0],[0,1],[1,4],[1,-2],[1,-1],[0,3],[0,4],[0,2],[1,0],[1,-1],[2,-1],[3,-5],[2,-5],[0,-3],[1,-1],[1,-2],[1,-2],[0,4],[-1,3],[0,3],[4,0],[1,5],[2,-3],[6,-12],[2,-2],[6,-3],[4,-6],[2,-5],[-1,-6],[-4,-2],[-1,-4],[-1,-3],[0,-4],[-1,-4],[-1,-1],[0,-6],[-2,-7],[-2,-7],[-10,0],[3,-3],[2,-2],[4,-6],[3,5],[4,0],[5,5],[2,1],[9,-3],[2,4],[2,1],[4,-1],[5,-4]],[[3205,6244],[-2,0],[1,2],[2,0],[1,0],[-2,-2]],[[3211,6247],[-1,0],[0,1],[0,2],[3,0],[-2,-3]],[[3214,6263],[0,-2],[-2,2],[-1,0],[-1,1],[3,0],[1,-1]],[[3201,6209],[2,-3],[3,0],[-3,-2],[-6,-1],[0,4],[4,2]],[[3204,6241],[-2,-2],[-1,1],[-1,0],[1,2],[3,-1]],[[3198,6240],[-2,-1],[-3,3],[3,1],[1,-1],[1,-2]],[[7961,5684],[-1,0],[-1,1],[3,4],[0,-3],[0,-1],[-1,-1]],[[7890,5782],[0,-3],[0,-6],[-1,-7],[0,-3],[0,-2],[-2,13],[-3,5],[0,2],[1,0],[3,3],[1,0],[1,-2]],[[7976,5783],[-2,-4],[0,3],[2,2],[0,1],[1,0],[-1,-2]],[[7972,6379],[-1,0],[-2,4],[1,3],[3,-2],[0,-1],[0,-1],[0,-2],[-1,-1]],[[7968,6383],[-1,-1],[-1,2],[-1,2],[1,3],[1,-4],[1,-2]],[[7986,6389],[-2,-1],[-1,0],[2,3],[1,3],[1,1],[0,-3],[-1,-3]],[[7988,6406],[-4,-7],[-1,0],[1,8],[1,2],[2,-3],[1,0]],[[7998,6423],[-1,-1],[-3,0],[-3,-5],[-2,-2],[-3,-2],[-3,-3],[-1,-5],[0,-4],[-1,-4],[-5,-7],[-1,1],[-1,2],[-2,0],[-1,-1],[-1,0],[-2,-2],[-2,1],[-1,2],[-1,0],[-1,0],[-1,-2],[2,-9],[1,-4],[-6,-12],[1,-8],[-2,-6],[-3,-4],[-7,-13],[-3,0],[-2,-3],[-5,-20],[0,-7],[0,-5],[0,-5],[-2,-9],[-2,-5],[-1,-5],[3,-11],[1,-1],[1,-6],[1,-4],[2,-4],[4,-11],[3,-3],[2,-3],[5,-9],[3,-7],[-2,-4],[1,-9],[-3,3],[0,-1],[4,-5],[6,-17],[5,-8],[6,-10],[1,-9],[5,-6],[6,-9],[-1,-2],[2,-2],[4,-5],[2,-4],[1,-5],[1,-1],[1,1],[2,1],[1,-1],[2,-5],[2,-4],[1,-4],[1,0],[1,0],[0,-4],[0,-2],[3,-7],[2,-6],[3,-11],[3,-5],[2,-4],[2,-2],[2,-12],[1,-10],[3,-12],[1,-5],[0,-9],[2,-10],[1,-6],[1,-7],[0,-3],[1,-3],[1,-11],[0,-5],[-1,5],[0,-15],[1,-8],[0,-10],[1,-4],[1,-11],[2,-4],[0,-14],[0,-6],[-1,4],[-2,4],[-1,-2],[-2,-4],[2,-14],[-2,1],[0,-20],[1,-4],[0,-3],[0,-2],[-1,3],[0,3],[0,-1],[0,-2],[-1,-3],[-1,-4],[1,-4],[0,-3],[0,-3],[-1,-4],[-3,0],[-1,-8],[0,-7],[-5,-1],[-3,-7],[-4,-3],[-4,-6],[-4,-6],[-3,-1],[-2,-2],[-3,-10],[-4,-1],[-8,-8],[-3,-4],[-2,-2],[-3,-3],[-1,1],[-1,3],[-3,1],[-2,4],[0,4],[0,2],[-1,-3],[-1,-10],[0,-2],[-1,-1],[-3,3],[-2,6],[-4,-4],[2,-1],[1,0],[1,-1],[1,-4],[0,-2],[0,-2],[-3,-1],[-5,1],[3,-4],[4,-2],[1,-3],[0,-2],[-2,-3],[-1,-4],[0,-2],[0,-3],[-2,-2],[-1,0],[-3,4],[-9,17],[2,-5],[9,-19],[1,-6],[1,-4],[-1,-2],[-2,-3],[-3,0],[-5,7],[-7,17],[-3,2],[8,-19],[1,-5],[1,-5],[0,-3],[-1,-3],[-18,-17],[-3,-8],[-2,-9],[-4,-5],[-2,-5],[-6,-3],[-3,1],[3,9],[-2,3],[0,22],[1,24],[1,12],[3,3],[2,2],[1,3],[-1,3],[-1,4],[-2,2],[-3,0],[-2,5],[-1,0],[-2,-1],[-2,2],[0,3],[-3,4],[-2,4]],[[7929,6229],[-2,2],[-2,0]],[[9718,4021],[-1,-3],[-1,0],[-2,2],[0,3],[3,0],[1,-2]],[[9707,4058],[-1,-6],[-3,2],[-2,4],[-1,4],[0,8],[2,1],[1,-1],[0,-7],[4,-5]],[[9703,4093],[-2,-3],[-1,0],[-7,7],[0,2],[0,7],[1,4],[2,1],[1,0],[1,-6],[3,-2],[-2,-2],[3,-4],[1,-4]],[[9678,4173],[3,-8],[1,0],[-2,-6],[-3,-1],[-4,2],[1,2],[-1,2],[-1,0],[-1,-1],[-1,1],[1,3],[2,6],[1,0],[1,0],[3,0]],[[9678,4217],[1,0],[-1,-3],[-3,3],[-3,-1],[-1,0],[-1,2],[-1,4],[0,4],[2,2],[1,-3],[1,-1],[1,-1],[2,-4],[2,-2]],[[9674,4243],[-3,-1],[-5,2],[-1,3],[-1,2],[1,2],[2,1],[3,6],[1,-3],[1,-6],[1,-2],[1,-2],[0,-2]],[[9649,4257],[2,-2],[1,-2],[4,-6],[1,0],[1,-3],[1,-1],[1,-4],[1,-3],[-2,-4],[-4,2],[-2,-5],[-3,1],[0,3],[-1,6],[-1,9],[0,5],[-1,3],[-2,-2],[-1,-1],[-2,5],[1,8],[0,3],[2,0],[2,-2],[2,-10]],[[9644,4278],[0,-1],[-3,3],[0,4],[3,-1],[0,-5]],[[9672,4264],[-1,0],[0,3],[-2,14],[1,12],[1,-2],[2,-23],[0,-3],[-1,-1]],[[9663,4295],[-2,-3],[-3,0],[-1,2],[4,8],[5,2],[-3,-9]],[[9671,4301],[-1,-4],[-1,4],[0,18],[0,1],[0,1],[2,-13],[0,-7]],[[9631,4330],[2,-19],[2,0],[1,1],[1,4],[1,7],[1,1],[1,0],[-1,-3],[1,-5],[1,-3],[1,-1],[1,-15],[1,-3],[-1,-2],[-2,-6],[-5,1],[-3,-4],[-2,0],[0,4],[-1,3],[-2,6],[0,12],[-3,20],[0,6],[1,6],[1,1],[2,-6],[2,-5]],[[9654,4362],[-1,-3],[-3,1],[-1,1],[0,5],[1,2],[2,1],[3,-2],[-1,-5]],[[9652,4383],[-1,-1],[-1,1],[-1,7],[0,2],[2,2],[2,-4],[0,-2],[0,-2],[0,-1],[-1,-1],[0,-1]],[[54,4359],[-1,0],[-2,0],[-1,4],[1,1],[1,-1],[1,-2],[1,-1],[0,-1]],[[107,4416],[-1,-1],[0,3],[0,3],[1,1],[1,-2],[-1,-4]],[[237,4375],[-7,0],[-4,2],[-1,0],[-4,6],[0,3],[2,2],[3,1],[7,-5],[1,-3],[2,-1],[1,-1],[0,-3],[0,-1]],[[213,4408],[3,-5],[1,-7],[-1,-7],[-3,1],[-4,-1],[-2,0],[-3,9],[-2,4],[-1,3],[3,0],[4,2],[5,1]],[[6493,5912],[1,-1],[3,2],[8,0],[9,-6],[-2,-2],[-1,-2],[-4,-2],[-4,-5],[-11,-3],[-4,2],[-3,4],[-5,7],[2,4],[1,1],[1,2],[2,3],[3,0],[4,-4]],[[6187,5973],[-2,-2],[1,5],[2,1],[-1,-4]],[[6188,5989],[0,-2],[-1,1],[-2,3],[2,3],[1,-3],[0,-2]],[[6182,6065],[0,-1],[-1,2],[1,5],[1,2],[0,-4],[0,-2],[-1,-2]],[[6474,6143],[-14,-11],[-4,-4],[-3,-6],[-3,-7],[-1,-12],[1,-11],[0,-6],[-4,-4],[-3,-3],[-4,-5],[-2,-1],[-2,-3],[-2,-3],[-8,-6],[-9,-5],[-13,-6],[-5,-6],[-5,-5],[-7,-1],[-10,-6],[-6,-5],[-7,-8],[-1,-3],[-1,-5],[-3,-5],[-4,-9],[-3,-4],[-2,0],[-4,-2],[-5,-1],[-8,3],[-2,-2],[-1,-3],[-6,-6],[-7,-11],[-4,-3],[-8,-4],[-5,-5],[-3,-1],[-5,-1],[-8,0],[-8,-2],[-7,-3],[-4,-6],[-4,-10],[-6,-4],[-2,-3],[-2,-7],[-4,-2],[-3,-1],[-4,3],[-7,-8],[-3,-2],[-4,0],[-3,-2],[-2,0],[-3,4],[-6,4],[-4,-3],[0,8],[-7,25],[2,21],[0,3],[-2,10],[-4,9],[0,11],[-1,8],[-1,8],[0,2],[0,2],[-2,13],[0,2],[-1,3],[1,2],[0,2],[-1,4],[-1,7],[-6,6],[1,6],[2,-2],[1,-2],[0,4],[0,2],[-2,16],[3,22],[-1,20]],[[6051,2480],[-1,-1],[-6,1],[0,2],[1,3],[1,2],[3,-1],[2,-3],[1,-1],[-1,-2]],[[5913,3637],[-1,-13],[-4,-21],[-1,-9],[-4,-34],[-4,-18],[-3,-7],[-7,-12],[-2,-3],[-2,-1],[-3,-2],[-12,-25],[-5,-13],[-4,-17],[-4,-10],[-6,-21],[-5,-16],[-5,-15],[-9,-20],[-4,-6],[-3,-3],[-7,-12],[-9,-19],[-8,-16],[-11,-19],[-7,-9],[-10,-16],[-2,-2],[-11,-16],[-8,-9],[-13,-11],[-5,-3],[-13,3],[-5,-1],[-4,-7],[0,-9],[-2,-2],[-3,1],[-8,4],[-5,-1],[-3,-5],[-2,-6],[-6,-1],[-12,7],[-13,4],[-3,0],[-7,-5],[-2,0],[-10,1],[-5,3],[-5,0],[-4,-3],[-5,-1],[-12,-17],[-7,0],[-6,-2],[-2,0],[-6,2],[-2,0],[-2,-1],[-3,-3],[-7,-1],[-3,-3],[-11,-16],[-3,1],[-2,1],[-6,0],[-7,9],[-2,-1],[0,3],[0,4],[-1,3],[-1,2],[-3,-1],[-1,4],[-4,1],[-2,-1],[-1,-1],[-1,4],[1,3],[-1,4],[0,4],[-2,2],[-1,0],[-3,0],[-2,0],[-1,-2],[-1,-3],[0,-11],[-1,3],[-2,7],[0,6],[0,8],[3,3],[0,5],[-1,5],[-3,11],[-1,6],[-3,3],[-2,9],[-3,3],[-1,6],[-2,5],[-1,8],[2,4],[1,3],[2,-4],[3,2],[3,5],[2,9],[1,13],[-1,9],[-3,21],[-1,6],[-6,15],[-8,21],[-9,33],[-4,20],[-7,40],[-6,23],[-7,21],[-1,1]],[[5815,3905],[0,1],[8,2],[7,-2],[8,-6],[8,-2],[7,1],[5,1],[5,-1],[3,-2],[3,-4]],[[5844,4283],[-4,0],[-7,0],[-8,0],[-6,-3],[-6,-5],[-7,-7],[-2,-3],[-1,-2],[-1,-3],[-1,-6],[0,-9],[-1,-7],[-2,-6],[-10,-8],[-6,-6],[-7,-7],[-5,-10],[-3,-11],[-5,-15],[-6,-12],[-6,-14],[-7,-4],[-5,1],[-7,5],[-5,1],[-4,-3],[-4,1],[-4,5],[-2,2],[-3,-1],[-3,0],[-5,3]]],"transform":{"scale":[0.036003600360036005,0.01736158967459246],"translate":[-180,-89.99892578124998]}} \ No newline at end of file +{"type":"Topology","objects":{"countries":{"type":"GeometryCollection","geometries":[{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Aruba","adm0_a3":"ABW","geou_dif":0,"geounit":"Aruba","gu_a3":"ABW","su_dif":0,"subunit":"Aruba","su_a3":"ABW","brk_diff":0,"name":"Aruba","name_long":"Aruba","brk_a3":"ABW","brk_name":"Aruba","brk_group":null,"abbrev":"Aruba","postal":"AW","formal_en":"Aruba","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"Aruba","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":103065,"gdp_md_est":2258,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AW","iso_a3":"ABW","iso_n3":"533","un_a3":"533","wb_a2":"AW","wb_a3":"ABW","woe_id":-99,"adm0_a3_is":"ABW","adm0_a3_us":"ABW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":4,"homepart":-99},"arcs":[[0]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Afghanistan","sov_a3":"AFG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Afghanistan","adm0_a3":"AFG","geou_dif":0,"geounit":"Afghanistan","gu_a3":"AFG","su_dif":0,"subunit":"Afghanistan","su_a3":"AFG","brk_diff":0,"name":"Afghanistan","name_long":"Afghanistan","brk_a3":"AFG","brk_name":"Afghanistan","brk_group":null,"abbrev":"Afg.","postal":"AF","formal_en":"Islamic State of Afghanistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Afghanistan","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":8,"mapcolor13":7,"pop_est":28400000,"gdp_md_est":22270,"pop_year":-99,"lastcensus":1979,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"AF","iso_a3":"AFG","iso_n3":"004","un_a3":"004","wb_a2":"AF","wb_a3":"AFG","woe_id":-99,"adm0_a3_is":"AFG","adm0_a3_us":"AFG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1,2,3,4,5,6,7]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Angola","sov_a3":"AGO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Angola","adm0_a3":"AGO","geou_dif":0,"geounit":"Angola","gu_a3":"AGO","su_dif":0,"subunit":"Angola","su_a3":"AGO","brk_diff":0,"name":"Angola","name_long":"Angola","brk_a3":"AGO","brk_name":"Angola","brk_group":null,"abbrev":"Ang.","postal":"AO","formal_en":"People's Republic of Angola","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Angola","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":6,"mapcolor13":1,"pop_est":12799293,"gdp_md_est":110300,"pop_year":-99,"lastcensus":1970,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AO","iso_a3":"AGO","iso_n3":"024","un_a3":"024","wb_a2":"AO","wb_a3":"AGO","woe_id":-99,"adm0_a3_is":"AGO","adm0_a3_us":"AGO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[8,9,10,11]],[[12,13,14]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Anguilla","adm0_a3":"AIA","geou_dif":0,"geounit":"Anguilla","gu_a3":"AIA","su_dif":0,"subunit":"Anguilla","su_a3":"AIA","brk_diff":0,"name":"Anguilla","name_long":"Anguilla","brk_a3":"AIA","brk_name":"Anguilla","brk_group":null,"abbrev":"Ang.","postal":"AI","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Anguilla","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":14436,"gdp_md_est":108.9,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AI","iso_a3":"AIA","iso_n3":"660","un_a3":"660","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"AIA","adm0_a3_us":"AIA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[15]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Albania","sov_a3":"ALB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Albania","adm0_a3":"ALB","geou_dif":0,"geounit":"Albania","gu_a3":"ALB","su_dif":0,"subunit":"Albania","su_a3":"ALB","brk_diff":0,"name":"Albania","name_long":"Albania","brk_a3":"ALB","brk_name":"Albania","brk_group":null,"abbrev":"Alb.","postal":"AL","formal_en":"Republic of Albania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Albania","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":3639453,"gdp_md_est":21810,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AL","iso_a3":"ALB","iso_n3":"008","un_a3":"008","wb_a2":"AL","wb_a3":"ALB","woe_id":-99,"adm0_a3_is":"ALB","adm0_a3_us":"ALB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[16,17,18,19,20]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Finland","sov_a3":"FI1","adm0_dif":1,"level":2,"type":"Country","admin":"Aland","adm0_a3":"ALD","geou_dif":0,"geounit":"Aland","gu_a3":"ALD","su_dif":0,"subunit":"Aland","su_a3":"ALD","brk_diff":0,"name":"Aland","name_long":"Aland Islands","brk_a3":"ALD","brk_name":"Aland","brk_group":null,"abbrev":"Aland","postal":"AI","formal_en":"Åland Islands","formal_fr":null,"note_adm0":"Fin.","note_brk":null,"name_sort":"Aland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":6,"pop_est":27153,"gdp_md_est":1563,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AX","iso_a3":"ALA","iso_n3":"248","un_a3":"248","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ALA","adm0_a3_us":"ALD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":13,"abbrev_len":5,"tiny":5,"homepart":-99},"arcs":[[[21]],[[22]],[[23]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Andorra","sov_a3":"AND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Andorra","adm0_a3":"AND","geou_dif":0,"geounit":"Andorra","gu_a3":"AND","su_dif":0,"subunit":"Andorra","su_a3":"AND","brk_diff":0,"name":"Andorra","name_long":"Andorra","brk_a3":"AND","brk_name":"Andorra","brk_group":null,"abbrev":"And.","postal":"AND","formal_en":"Principality of Andorra","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Andorra","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":83888,"gdp_md_est":3660,"pop_year":-99,"lastcensus":1989,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AD","iso_a3":"AND","iso_n3":"020","un_a3":"020","wb_a2":"AD","wb_a3":"ADO","woe_id":-99,"adm0_a3_is":"AND","adm0_a3_us":"AND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[24,25]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Arab Emirates","sov_a3":"ARE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"United Arab Emirates","adm0_a3":"ARE","geou_dif":0,"geounit":"United Arab Emirates","gu_a3":"ARE","su_dif":0,"subunit":"United Arab Emirates","su_a3":"ARE","brk_diff":0,"name":"United Arab Emirates","name_long":"United Arab Emirates","brk_a3":"ARE","brk_name":"United Arab Emirates","brk_group":null,"abbrev":"U.A.E.","postal":"AE","formal_en":"United Arab Emirates","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United Arab Emirates","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":3,"pop_est":4798491,"gdp_md_est":184300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AE","iso_a3":"ARE","iso_n3":"784","un_a3":"784","wb_a2":"AE","wb_a3":"ARE","woe_id":-99,"adm0_a3_is":"ARE","adm0_a3_us":"ARE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":20,"long_len":20,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[26]],[[27]],[[28]],[[29]],[[30,31,32,33,34],[35]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Argentina","sov_a3":"ARG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Argentina","adm0_a3":"ARG","geou_dif":0,"geounit":"Argentina","gu_a3":"ARG","su_dif":0,"subunit":"Argentina","su_a3":"ARG","brk_diff":0,"name":"Argentina","name_long":"Argentina","brk_a3":"ARG","brk_name":"Argentina","brk_group":null,"abbrev":"Arg.","postal":"AR","formal_en":"Argentine Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Argentina","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":13,"pop_est":40913584,"gdp_md_est":573900,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AR","iso_a3":"ARG","iso_n3":"032","un_a3":"032","wb_a2":"AR","wb_a3":"ARG","woe_id":-99,"adm0_a3_is":"ARG","adm0_a3_us":"ARG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[36]],[[37,38]],[[39]],[[40,41,42,43,44,45]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Armenia","sov_a3":"ARM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Armenia","adm0_a3":"ARM","geou_dif":0,"geounit":"Armenia","gu_a3":"ARM","su_dif":0,"subunit":"Armenia","su_a3":"ARM","brk_diff":0,"name":"Armenia","name_long":"Armenia","brk_a3":"ARM","brk_name":"Armenia","brk_group":null,"abbrev":"Arm.","postal":"ARM","formal_en":"Republic of Armenia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Armenia","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":2,"mapcolor13":10,"pop_est":2967004,"gdp_md_est":18770,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AM","iso_a3":"ARM","iso_n3":"051","un_a3":"051","wb_a2":"AM","wb_a3":"ARM","woe_id":-99,"adm0_a3_is":"ARM","adm0_a3_us":"ARM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[46]],[[47,48,49,50,51],[52]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"American Samoa","adm0_a3":"ASM","geou_dif":0,"geounit":"American Samoa","gu_a3":"ASM","su_dif":0,"subunit":"American Samoa","su_a3":"ASM","brk_diff":0,"name":"American Samoa","name_long":"American Samoa","brk_a3":"ASM","brk_name":"American Samoa","brk_group":null,"abbrev":"Am. Samoa","postal":"AS","formal_en":"American Samoa","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"American Samoa","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":65628,"gdp_md_est":575.3,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AS","iso_a3":"ASM","iso_n3":"016","un_a3":"016","wb_a2":"AS","wb_a3":"ASM","woe_id":-99,"adm0_a3_is":"ASM","adm0_a3_us":"ASM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":14,"long_len":14,"abbrev_len":9,"tiny":3,"homepart":-99},"arcs":[[53]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Antarctica","sov_a3":"ATA","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Antarctica","adm0_a3":"ATA","geou_dif":0,"geounit":"Antarctica","gu_a3":"ATA","su_dif":0,"subunit":"Antarctica","su_a3":"ATA","brk_diff":0,"name":"Antarctica","name_long":"Antarctica","brk_a3":"ATA","brk_name":"Antarctica","brk_group":null,"abbrev":"Ant.","postal":"AQ","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Multiple claims held in abeyance","name_sort":"Antarctica","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":-99,"pop_est":3802,"gdp_md_est":760.4,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"AQ","iso_a3":"ATA","iso_n3":"010","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ATA","adm0_a3_us":"ATA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Antarctica","region_un":"Antarctica","subregion":"Antarctica","region_wb":"Antarctica","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[54]],[[55]],[[56]],[[57]],[[58]],[[59]],[[60]],[[61]],[[62]],[[63]],[[64]],[[65]],[[66]],[[67]],[[68]],[[69]],[[70]],[[71]],[[72]],[[73]],[[74]],[[75]],[[76]],[[77]],[[78]],[[79]],[[80]],[[81]],[[82]],[[83]],[[84]],[[85]],[[86]],[[87]],[[88]],[[89]],[[90]],[[91]],[[92]],[[93]],[[94]],[[95]],[[96]],[[97]],[[98]],[[99]],[[100]],[[101]],[[102]],[[103]],[[104]],[[105]],[[106]],[[107]],[[108]],[[109]],[[110]],[[111]],[[112]],[[113]],[[114]],[[115]],[[116]],[[117]],[[118]],[[119]],[[120]],[[121]],[[122]],[[123]],[[124]],[[125]],[[126]],[[127]],[[128]],[[129]],[[130]],[[131]],[[132]],[[133]],[[134]],[[135]],[[136]],[[137]],[[138]],[[139]],[[140]],[[141]],[[142]],[[143]],[[144]],[[145]],[[146]],[[147]],[[148]],[[149]],[[150]],[[151]],[[152]],[[153]],[[154]],[[155]],[[156]],[[157]],[[158]],[[159]],[[160]],[[161]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"French Southern and Antarctic Lands","adm0_a3":"ATF","geou_dif":0,"geounit":"French Southern and Antarctic Lands","gu_a3":"ATF","su_dif":0,"subunit":"French Southern and Antarctic Lands","su_a3":"ATF","brk_diff":0,"name":"Fr. S. Antarctic Lands","name_long":"French Southern and Antarctic Lands","brk_a3":"ATF","brk_name":"Fr. S. and Antarctic Lands","brk_group":null,"abbrev":"Fr. S.A.L.","postal":"TF","formal_en":"Territory of the French Southern and Antarctic Lands","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"French Southern and Antarctic Lands","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":140,"gdp_md_est":16,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TF","iso_a3":"ATF","iso_n3":"260","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"ATF","adm0_a3_us":"ATF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":22,"long_len":35,"abbrev_len":10,"tiny":2,"homepart":-99},"arcs":[[[162]],[[163]],[[164]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Antigua and Barbuda","sov_a3":"ATG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Antigua and Barbuda","adm0_a3":"ATG","geou_dif":0,"geounit":"Antigua and Barbuda","gu_a3":"ATG","su_dif":0,"subunit":"Antigua and Barbuda","su_a3":"ATG","brk_diff":0,"name":"Antigua and Barb.","name_long":"Antigua and Barbuda","brk_a3":"ATG","brk_name":"Antigua and Barb.","brk_group":null,"abbrev":"Ant.B.","postal":"AG","formal_en":"Antigua and Barbuda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Antigua and Barbuda","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":5,"pop_est":85632,"gdp_md_est":1657,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AG","iso_a3":"ATG","iso_n3":"028","un_a3":"028","wb_a2":"AG","wb_a3":"ATG","woe_id":-99,"adm0_a3_is":"ATG","adm0_a3_us":"ATG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":17,"long_len":19,"abbrev_len":6,"tiny":4,"homepart":1},"arcs":[[[165]],[[166]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Country","admin":"Australia","adm0_a3":"AUS","geou_dif":0,"geounit":"Australia","gu_a3":"AUS","su_dif":0,"subunit":"Australia","su_a3":"AUS","brk_diff":0,"name":"Australia","name_long":"Australia","brk_a3":"AUS","brk_name":"Australia","brk_group":null,"abbrev":"Auz.","postal":"AU","formal_en":"Commonwealth of Australia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Australia","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":21262641,"gdp_md_est":800200,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AU","iso_a3":"AUS","iso_n3":"036","un_a3":"036","wb_a2":"AU","wb_a3":"AUS","woe_id":-99,"adm0_a3_is":"AUS","adm0_a3_us":"AUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[167]],[[168]],[[169]],[[170]],[[171]],[[172]],[[173]],[[174]],[[175]],[[176]],[[177]],[[178]],[[179]],[[180]],[[181]],[[182]],[[183]],[[184]],[[185]],[[186]],[[187]],[[188]],[[189]],[[190]],[[191]],[[192]],[[193]],[[194]],[[195]],[[196]],[[197]],[[198]],[[199]],[[200]],[[201]],[[202]],[[203]],[[204]],[[205]],[[206]],[[207]],[[208]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Austria","sov_a3":"AUT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Austria","adm0_a3":"AUT","geou_dif":0,"geounit":"Austria","gu_a3":"AUT","su_dif":0,"subunit":"Austria","su_a3":"AUT","brk_diff":0,"name":"Austria","name_long":"Austria","brk_a3":"AUT","brk_name":"Austria","brk_group":null,"abbrev":"Aust.","postal":"A","formal_en":"Republic of Austria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Austria","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":4,"pop_est":8210281,"gdp_md_est":329500,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"AT","iso_a3":"AUT","iso_n3":"040","un_a3":"040","wb_a2":"AT","wb_a3":"AUT","woe_id":-99,"adm0_a3_is":"AUT","adm0_a3_us":"AUT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[209,210,211,212,213,214,215,216,217]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Azerbaijan","sov_a3":"AZE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Azerbaijan","adm0_a3":"AZE","geou_dif":0,"geounit":"Azerbaijan","gu_a3":"AZE","su_dif":0,"subunit":"Azerbaijan","su_a3":"AZE","brk_diff":0,"name":"Azerbaijan","name_long":"Azerbaijan","brk_a3":"AZE","brk_name":"Azerbaijan","brk_group":null,"abbrev":"Aze.","postal":"AZ","formal_en":"Republic of Azerbaijan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Azerbaijan","name_alt":null,"mapcolor7":1,"mapcolor8":6,"mapcolor9":5,"mapcolor13":8,"pop_est":8238672,"gdp_md_est":77610,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"AZ","iso_a3":"AZE","iso_n3":"031","un_a3":"031","wb_a2":"AZ","wb_a3":"AZE","woe_id":-99,"adm0_a3_is":"AZE","adm0_a3_us":"AZE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[218,219,-49]],[[-53]],[[220,221,-52,222,223],[-47]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Burundi","sov_a3":"BDI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Burundi","adm0_a3":"BDI","geou_dif":0,"geounit":"Burundi","gu_a3":"BDI","su_dif":0,"subunit":"Burundi","su_a3":"BDI","brk_diff":0,"name":"Burundi","name_long":"Burundi","brk_a3":"BDI","brk_name":"Burundi","brk_group":null,"abbrev":"Bur.","postal":"BI","formal_en":"Republic of Burundi","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Burundi","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":8,"pop_est":8988091,"gdp_md_est":3102,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BI","iso_a3":"BDI","iso_n3":"108","un_a3":"108","wb_a2":"BI","wb_a3":"BDI","woe_id":-99,"adm0_a3_is":"BDI","adm0_a3_us":"BDI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[224,225,226]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Belgium","sov_a3":"BEL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belgium","adm0_a3":"BEL","geou_dif":0,"geounit":"Belgium","gu_a3":"BEL","su_dif":0,"subunit":"Belgium","su_a3":"BEL","brk_diff":0,"name":"Belgium","name_long":"Belgium","brk_a3":"BEL","brk_name":"Belgium","brk_group":null,"abbrev":"Belg.","postal":"B","formal_en":"Kingdom of Belgium","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belgium","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":8,"pop_est":10414336,"gdp_md_est":389300,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"BE","iso_a3":"BEL","iso_n3":"056","un_a3":"056","wb_a2":"BE","wb_a3":"BEL","woe_id":-99,"adm0_a3_is":"BEL","adm0_a3_us":"BEL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[227,228,229,230,231,232,233]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Benin","sov_a3":"BEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Benin","adm0_a3":"BEN","geou_dif":0,"geounit":"Benin","gu_a3":"BEN","su_dif":0,"subunit":"Benin","su_a3":"BEN","brk_diff":0,"name":"Benin","name_long":"Benin","brk_a3":"BEN","brk_name":"Benin","brk_group":null,"abbrev":"Benin","postal":"BJ","formal_en":"Republic of Benin","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Benin","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":12,"pop_est":8791832,"gdp_md_est":12830,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BJ","iso_a3":"BEN","iso_n3":"204","un_a3":"204","wb_a2":"BJ","wb_a3":"BEN","woe_id":-99,"adm0_a3_is":"BEN","adm0_a3_us":"BEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[234,235,236,237,238]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Burkina Faso","sov_a3":"BFA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Burkina Faso","adm0_a3":"BFA","geou_dif":0,"geounit":"Burkina Faso","gu_a3":"BFA","su_dif":0,"subunit":"Burkina Faso","su_a3":"BFA","brk_diff":0,"name":"Burkina Faso","name_long":"Burkina Faso","brk_a3":"BFA","brk_name":"Burkina Faso","brk_group":null,"abbrev":"B.F.","postal":"BF","formal_en":"Burkina Faso","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Burkina Faso","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":5,"mapcolor13":11,"pop_est":15746232,"gdp_md_est":17820,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BF","iso_a3":"BFA","iso_n3":"854","un_a3":"854","wb_a2":"BF","wb_a3":"BFA","woe_id":-99,"adm0_a3_is":"BFA","adm0_a3_us":"BFA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[239,-238,240,241,242,243]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Bangladesh","sov_a3":"BGD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bangladesh","adm0_a3":"BGD","geou_dif":0,"geounit":"Bangladesh","gu_a3":"BGD","su_dif":0,"subunit":"Bangladesh","su_a3":"BGD","brk_diff":0,"name":"Bangladesh","name_long":"Bangladesh","brk_a3":"BGD","brk_name":"Bangladesh","brk_group":null,"abbrev":"Bang.","postal":"BD","formal_en":"People's Republic of Bangladesh","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bangladesh","name_alt":null,"mapcolor7":3,"mapcolor8":4,"mapcolor9":7,"mapcolor13":7,"pop_est":156050883,"gdp_md_est":224000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"BD","iso_a3":"BGD","iso_n3":"050","un_a3":"050","wb_a2":"BD","wb_a3":"BGD","woe_id":-99,"adm0_a3_is":"BGD","adm0_a3_us":"BGD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[244]],[[245]],[[246]],[[247]],[[248]],[[249]],[[250,251,252]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Bulgaria","sov_a3":"BGR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bulgaria","adm0_a3":"BGR","geou_dif":0,"geounit":"Bulgaria","gu_a3":"BGR","su_dif":0,"subunit":"Bulgaria","su_a3":"BGR","brk_diff":0,"name":"Bulgaria","name_long":"Bulgaria","brk_a3":"BGR","brk_name":"Bulgaria","brk_group":null,"abbrev":"Bulg.","postal":"BG","formal_en":"Republic of Bulgaria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bulgaria","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":8,"pop_est":7204687,"gdp_md_est":93750,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BG","iso_a3":"BGR","iso_n3":"100","un_a3":"100","wb_a2":"BG","wb_a3":"BGR","woe_id":-99,"adm0_a3_is":"BGR","adm0_a3_us":"BGR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[253,254,255,256,257,258]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Bahrain","sov_a3":"BHR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bahrain","adm0_a3":"BHR","geou_dif":0,"geounit":"Bahrain","gu_a3":"BHR","su_dif":0,"subunit":"Bahrain","su_a3":"BHR","brk_diff":0,"name":"Bahrain","name_long":"Bahrain","brk_a3":"BHR","brk_name":"Bahrain","brk_group":null,"abbrev":"Bahr.","postal":"BH","formal_en":"Kingdom of Bahrain","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bahrain","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":9,"pop_est":727785,"gdp_md_est":26820,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BH","iso_a3":"BHR","iso_n3":"048","un_a3":"048","wb_a2":"BH","wb_a3":"BHR","woe_id":-99,"adm0_a3_is":"BHR","adm0_a3_us":"BHR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[259]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"The Bahamas","sov_a3":"BHS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"The Bahamas","adm0_a3":"BHS","geou_dif":0,"geounit":"The Bahamas","gu_a3":"BHS","su_dif":0,"subunit":"The Bahamas","su_a3":"BHS","brk_diff":0,"name":"Bahamas","name_long":"Bahamas","brk_a3":"BHS","brk_name":"Bahamas","brk_group":null,"abbrev":"Bhs.","postal":"BS","formal_en":"Commonwealth of the Bahamas","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bahamas, The","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":5,"pop_est":309156,"gdp_md_est":9093,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BS","iso_a3":"BHS","iso_n3":"044","un_a3":"044","wb_a2":"BS","wb_a3":"BHS","woe_id":-99,"adm0_a3_is":"BHS","adm0_a3_us":"BHS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[260]],[[261]],[[262]],[[263]],[[264]],[[265]],[[266]],[[267]],[[268]],[[269]],[[270]],[[271]],[[272]],[[273]],[[274]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Bosnia and Herzegovina","sov_a3":"BIH","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bosnia and Herzegovina","adm0_a3":"BIH","geou_dif":0,"geounit":"Bosnia and Herzegovina","gu_a3":"BIH","su_dif":0,"subunit":"Bosnia and Herzegovina","su_a3":"BIH","brk_diff":0,"name":"Bosnia and Herz.","name_long":"Bosnia and Herzegovina","brk_a3":"BIH","brk_name":"Bosnia and Herz.","brk_group":null,"abbrev":"B.H.","postal":"BiH","formal_en":"Bosnia and Herzegovina","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bosnia and Herzegovina","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":2,"pop_est":4613414,"gdp_md_est":29700,"pop_year":-99,"lastcensus":1991,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BA","iso_a3":"BIH","iso_n3":"070","un_a3":"070","wb_a2":"BA","wb_a3":"BIH","woe_id":-99,"adm0_a3_is":"BIH","adm0_a3_us":"BIH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":16,"long_len":22,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[275,276,277,278,279]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Barthelemy","adm0_a3":"BLM","geou_dif":0,"geounit":"Saint Barthelemy","gu_a3":"BLM","su_dif":0,"subunit":"Saint Barthelemy","su_a3":"BLM","brk_diff":0,"name":"St-Barthélemy","name_long":"Saint-Barthélemy","brk_a3":"BLM","brk_name":"St-Barthélemy","brk_group":null,"abbrev":"St. B.","postal":"BL","formal_en":"Saint-Barthélemy","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St-Barthélemy","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":7448,"gdp_md_est":255,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"BL","iso_a3":"BLM","iso_n3":"652","un_a3":"652","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"BLM","adm0_a3_us":"BLM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":13,"long_len":16,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[280]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Belarus","sov_a3":"BLR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belarus","adm0_a3":"BLR","geou_dif":0,"geounit":"Belarus","gu_a3":"BLR","su_dif":0,"subunit":"Belarus","su_a3":"BLR","brk_diff":0,"name":"Belarus","name_long":"Belarus","brk_a3":"BLR","brk_name":"Belarus","brk_group":null,"abbrev":"Bela.","postal":"BY","formal_en":"Republic of Belarus","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belarus","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":5,"mapcolor13":11,"pop_est":9648533,"gdp_md_est":114100,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BY","iso_a3":"BLR","iso_n3":"112","un_a3":"112","wb_a2":"BY","wb_a3":"BLR","woe_id":-99,"adm0_a3_is":"BLR","adm0_a3_us":"BLR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[281,282,283,284,285]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Belize","sov_a3":"BLZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Belize","adm0_a3":"BLZ","geou_dif":0,"geounit":"Belize","gu_a3":"BLZ","su_dif":0,"subunit":"Belize","su_a3":"BLZ","brk_diff":0,"name":"Belize","name_long":"Belize","brk_a3":"BLZ","brk_name":"Belize","brk_group":null,"abbrev":"Belize","postal":"BZ","formal_en":"Belize","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Belize","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":5,"mapcolor13":7,"pop_est":307899,"gdp_md_est":2536,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BZ","iso_a3":"BLZ","iso_n3":"084","un_a3":"084","wb_a2":"BZ","wb_a3":"BLZ","woe_id":-99,"adm0_a3_is":"BLZ","adm0_a3_us":"BLZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[286]],[[287]],[[288,289,290]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Bermuda","adm0_a3":"BMU","geou_dif":0,"geounit":"Bermuda","gu_a3":"BMU","su_dif":0,"subunit":"Bermuda","su_a3":"BMU","brk_diff":0,"name":"Bermuda","name_long":"Bermuda","brk_a3":"BMU","brk_name":"Bermuda","brk_group":null,"abbrev":"Berm.","postal":"BM","formal_en":"The Bermudas or Somers Isles","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Bermuda","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":67837,"gdp_md_est":4500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BM","iso_a3":"BMU","iso_n3":"060","un_a3":"060","wb_a2":"BM","wb_a3":"BMU","woe_id":-99,"adm0_a3_is":"BMU","adm0_a3_us":"BMU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":7,"long_len":7,"abbrev_len":5,"tiny":4,"homepart":-99},"arcs":[[291]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Bolivia","sov_a3":"BOL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bolivia","adm0_a3":"BOL","geou_dif":0,"geounit":"Bolivia","gu_a3":"BOL","su_dif":0,"subunit":"Bolivia","su_a3":"BOL","brk_diff":0,"name":"Bolivia","name_long":"Bolivia","brk_a3":"BOL","brk_name":"Bolivia","brk_group":null,"abbrev":"Bolivia","postal":"BO","formal_en":"Plurinational State of Bolivia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bolivia","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":3,"pop_est":9775246,"gdp_md_est":43270,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BO","iso_a3":"BOL","iso_n3":"068","un_a3":"068","wb_a2":"BO","wb_a3":"BOL","woe_id":-99,"adm0_a3_is":"BOL","adm0_a3_us":"BOL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[292,-46,293,294,295]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Brazil","sov_a3":"BRA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Brazil","adm0_a3":"BRA","geou_dif":0,"geounit":"Brazil","gu_a3":"BRA","su_dif":0,"subunit":"Brazil","su_a3":"BRA","brk_diff":0,"name":"Brazil","name_long":"Brazil","brk_a3":"BRA","brk_name":"Brazil","brk_group":null,"abbrev":"Brazil","postal":"BR","formal_en":"Federative Republic of Brazil","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Brazil","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":5,"mapcolor13":7,"pop_est":198739269,"gdp_md_est":1993000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BR","iso_a3":"BRA","iso_n3":"076","un_a3":"076","wb_a2":"BR","wb_a3":"BRA","woe_id":-99,"adm0_a3_is":"BRA","adm0_a3_us":"BRA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[296]],[[297]],[[298]],[[299]],[[300]],[[301]],[[302]],[[303]],[[304]],[[305]],[[306]],[[307]],[[308]],[[309]],[[310]],[[311]],[[312,313,314,315,-42,316,-296,317,318,319,320]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Barbados","sov_a3":"BRB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Barbados","adm0_a3":"BRB","geou_dif":0,"geounit":"Barbados","gu_a3":"BRB","su_dif":0,"subunit":"Barbados","su_a3":"BRB","brk_diff":0,"name":"Barbados","name_long":"Barbados","brk_a3":"BRB","brk_name":"Barbados","brk_group":null,"abbrev":"Barb.","postal":"BB","formal_en":"Barbados","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Barbados","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":5,"mapcolor13":3,"pop_est":284589,"gdp_md_est":5425,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BB","iso_a3":"BRB","iso_n3":"052","un_a3":"052","wb_a2":"BB","wb_a3":"BRB","woe_id":-99,"adm0_a3_is":"BRB","adm0_a3_us":"BRB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[321]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Brunei","sov_a3":"BRN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Brunei","adm0_a3":"BRN","geou_dif":0,"geounit":"Brunei","gu_a3":"BRN","su_dif":0,"subunit":"Brunei","su_a3":"BRN","brk_diff":0,"name":"Brunei","name_long":"Brunei Darussalam","brk_a3":"BRN","brk_name":"Brunei","brk_group":null,"abbrev":"Brunei","postal":"BN","formal_en":"Negara Brunei Darussalam","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Brunei","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":6,"mapcolor13":12,"pop_est":388190,"gdp_md_est":20250,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"BN","iso_a3":"BRN","iso_n3":"096","un_a3":"096","wb_a2":"BN","wb_a3":"BRN","woe_id":-99,"adm0_a3_is":"BRN","adm0_a3_us":"BRN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":6,"long_len":17,"abbrev_len":6,"tiny":2,"homepart":1},"arcs":[[[322,323]],[[324,325]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Bhutan","sov_a3":"BTN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Bhutan","adm0_a3":"BTN","geou_dif":0,"geounit":"Bhutan","gu_a3":"BTN","su_dif":0,"subunit":"Bhutan","su_a3":"BTN","brk_diff":0,"name":"Bhutan","name_long":"Bhutan","brk_a3":"BTN","brk_name":"Bhutan","brk_group":null,"abbrev":"Bhutan","postal":"BT","formal_en":"Kingdom of Bhutan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Bhutan","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":1,"mapcolor13":8,"pop_est":691141,"gdp_md_est":3524,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BT","iso_a3":"BTN","iso_n3":"064","un_a3":"064","wb_a2":"BT","wb_a3":"BTN","woe_id":-99,"adm0_a3_is":"BTN","adm0_a3_us":"BTN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[326,327]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Botswana","sov_a3":"BWA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Botswana","adm0_a3":"BWA","geou_dif":0,"geounit":"Botswana","gu_a3":"BWA","su_dif":0,"subunit":"Botswana","su_a3":"BWA","brk_diff":0,"name":"Botswana","name_long":"Botswana","brk_a3":"BWA","brk_name":"Botswana","brk_group":null,"abbrev":"Bwa.","postal":"BW","formal_en":"Republic of Botswana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Botswana","name_alt":null,"mapcolor7":6,"mapcolor8":5,"mapcolor9":7,"mapcolor13":3,"pop_est":1990876,"gdp_md_est":27060,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"BW","iso_a3":"BWA","iso_n3":"072","un_a3":"072","wb_a2":"BW","wb_a3":"BWA","woe_id":-99,"adm0_a3_is":"BWA","adm0_a3_us":"BWA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[328,329,330]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Central African Republic","sov_a3":"CAF","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Central African Republic","adm0_a3":"CAF","geou_dif":0,"geounit":"Central African Republic","gu_a3":"CAF","su_dif":0,"subunit":"Central African Republic","su_a3":"CAF","brk_diff":0,"name":"Central African Rep.","name_long":"Central African Republic","brk_a3":"CAF","brk_name":"Central African Rep.","brk_group":null,"abbrev":"C.A.R.","postal":"CF","formal_en":"Central African Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Central African Republic","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":6,"mapcolor13":9,"pop_est":4511488,"gdp_md_est":3198,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"CF","iso_a3":"CAF","iso_n3":"140","un_a3":"140","wb_a2":"CF","wb_a3":"CAF","woe_id":-99,"adm0_a3_is":"CAF","adm0_a3_us":"CAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":20,"long_len":24,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[331,332,333,334,335,336]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Canada","sov_a3":"CAN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Canada","adm0_a3":"CAN","geou_dif":0,"geounit":"Canada","gu_a3":"CAN","su_dif":0,"subunit":"Canada","su_a3":"CAN","brk_diff":0,"name":"Canada","name_long":"Canada","brk_a3":"CAN","brk_name":"Canada","brk_group":null,"abbrev":"Can.","postal":"CA","formal_en":"Canada","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Canada","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":2,"mapcolor13":2,"pop_est":33487208,"gdp_md_est":1300000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CA","iso_a3":"CAN","iso_n3":"124","un_a3":"124","wb_a2":"CA","wb_a3":"CAN","woe_id":-99,"adm0_a3_is":"CAN","adm0_a3_us":"CAN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[337]],[[338]],[[339]],[[340]],[[341]],[[342]],[[343]],[[344]],[[345]],[[346]],[[347]],[[348]],[[349]],[[350]],[[351]],[[352,353]],[[354]],[[355]],[[356]],[[357]],[[358]],[[359]],[[360]],[[361]],[[362]],[[363]],[[364]],[[365]],[[366]],[[367]],[[368]],[[369]],[[370]],[[371]],[[372]],[[373]],[[374]],[[375]],[[376]],[[377]],[[378]],[[379]],[[380]],[[381,382]],[[383]],[[384]],[[385]],[[386]],[[387]],[[388]],[[389]],[[390]],[[391]],[[392]],[[393]],[[394]],[[395]],[[396]],[[397]],[[398]],[[399]],[[400]],[[401]],[[402]],[[403]],[[404]],[[405]],[[406]],[[407]],[[408]],[[409]],[[410]],[[411]],[[412]],[[413]],[[414]],[[415]],[[416]],[[417]],[[418]],[[419]],[[420]],[[421]],[[422]],[[423]],[[424]],[[425]],[[426]],[[427]],[[428]],[[429]],[[430]],[[431]],[[432]],[[433]],[[434]],[[435]],[[436]],[[437]],[[438]],[[439,440,441,442]],[[443]],[[444]],[[445]],[[446]],[[447]],[[448]],[[449]],[[450]],[[451]],[[452]],[[453]],[[454]],[[455]],[[456]],[[457]],[[458]],[[459]],[[460]],[[461]],[[462]],[[463]],[[464]],[[465]],[[466]],[[467]],[[468]],[[469]],[[470]],[[471]],[[472]],[[473]],[[474]],[[475]],[[476]],[[477]],[[478]],[[479]],[[480]],[[481]],[[482]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Switzerland","sov_a3":"CHE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Switzerland","adm0_a3":"CHE","geou_dif":0,"geounit":"Switzerland","gu_a3":"CHE","su_dif":0,"subunit":"Switzerland","su_a3":"CHE","brk_diff":0,"name":"Switzerland","name_long":"Switzerland","brk_a3":"CHE","brk_name":"Switzerland","brk_group":null,"abbrev":"Switz.","postal":"CH","formal_en":"Swiss Confederation","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Switzerland","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":7,"mapcolor13":3,"pop_est":7604467,"gdp_md_est":316700,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CH","iso_a3":"CHE","iso_n3":"756","un_a3":"756","wb_a2":"CH","wb_a3":"CHE","woe_id":-99,"adm0_a3_is":"CHE","adm0_a3_us":"CHE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-216,483,-214,484,485,486]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Chile","sov_a3":"CHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Chile","adm0_a3":"CHL","geou_dif":0,"geounit":"Chile","gu_a3":"CHL","su_dif":0,"subunit":"Chile","su_a3":"CHL","brk_diff":0,"name":"Chile","name_long":"Chile","brk_a3":"CHL","brk_name":"Chile","brk_group":null,"abbrev":"Chile","postal":"CL","formal_en":"Republic of Chile","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Chile","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":5,"mapcolor13":9,"pop_est":16601707,"gdp_md_est":244500,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CL","iso_a3":"CHL","iso_n3":"152","un_a3":"152","wb_a2":"CL","wb_a3":"CHL","woe_id":-99,"adm0_a3_is":"CHL","adm0_a3_us":"CHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[487]],[[488]],[[489]],[[490]],[[491]],[[492]],[[493]],[[494]],[[495]],[[-38,496]],[[497]],[[498]],[[499]],[[500]],[[501]],[[502]],[[503]],[[504]],[[505]],[[506]],[[507]],[[508]],[[509]],[[510]],[[511]],[[512]],[[513]],[[514]],[[515]],[[516]],[[-45,517,518,-294]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"China","adm0_a3":"CHN","geou_dif":0,"geounit":"China","gu_a3":"CHN","su_dif":0,"subunit":"China","su_a3":"CHN","brk_diff":0,"name":"China","name_long":"China","brk_a3":"CHN","brk_name":"China","brk_group":null,"abbrev":"China","postal":"CN","formal_en":"People's Republic of China","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":1338612970,"gdp_md_est":7973000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CN","iso_a3":"CHN","iso_n3":"156","un_a3":"156","wb_a2":"CN","wb_a3":"CHN","woe_id":-99,"adm0_a3_is":"CHN","adm0_a3_us":"CHN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[519]],[[520]],[[521]],[[522]],[[523]],[[524]],[[525]],[[526]],[[527]],[[528]],[[529]],[[530]],[[531,532,533,534,535,536,537,538,539,540,-328,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,-2,557,558,559,560,561,562]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ivory Coast","sov_a3":"CIV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ivory Coast","adm0_a3":"CIV","geou_dif":0,"geounit":"Ivory Coast","gu_a3":"CIV","su_dif":0,"subunit":"Ivory Coast","su_a3":"CIV","brk_diff":0,"name":"Côte d'Ivoire","name_long":"Côte d'Ivoire","brk_a3":"CIV","brk_name":"Côte d'Ivoire","brk_group":null,"abbrev":"I.C.","postal":"CI","formal_en":"Republic of Ivory Coast","formal_fr":"Republic of Cote D'Ivoire","note_adm0":null,"note_brk":null,"name_sort":"Côte d'Ivoire","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":3,"mapcolor13":3,"pop_est":20617068,"gdp_md_est":33850,"pop_year":-99,"lastcensus":1998,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CI","iso_a3":"CIV","iso_n3":"384","un_a3":"384","wb_a2":"CI","wb_a3":"CIV","woe_id":-99,"adm0_a3_is":"CIV","adm0_a3_us":"CIV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":13,"long_len":13,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[563,564]],[[-243,565,566,567,568,569]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cameroon","sov_a3":"CMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cameroon","adm0_a3":"CMR","geou_dif":0,"geounit":"Cameroon","gu_a3":"CMR","su_dif":0,"subunit":"Cameroon","su_a3":"CMR","brk_diff":0,"name":"Cameroon","name_long":"Cameroon","brk_a3":"CMR","brk_name":"Cameroon","brk_group":null,"abbrev":"Cam.","postal":"CM","formal_en":"Republic of Cameroon","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cameroon","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":3,"pop_est":18879301,"gdp_md_est":42750,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CM","iso_a3":"CMR","iso_n3":"120","un_a3":"120","wb_a2":"CM","wb_a3":"CMR","woe_id":-99,"adm0_a3_is":"CMR","adm0_a3_us":"CMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-336,570,571,572,573,574,575]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Democratic Republic of the Congo","sov_a3":"COD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Democratic Republic of the Congo","adm0_a3":"COD","geou_dif":0,"geounit":"Democratic Republic of the Congo","gu_a3":"COD","su_dif":0,"subunit":"Democratic Republic of the Congo","su_a3":"COD","brk_diff":0,"name":"Dem. Rep. Congo","name_long":"Democratic Republic of the Congo","brk_a3":"COD","brk_name":"Democratic Republic of the Congo","brk_group":null,"abbrev":"D.R.C.","postal":"DRC","formal_en":"Democratic Republic of the Congo","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Congo, Dem. Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":7,"pop_est":68692542,"gdp_md_est":20640,"pop_year":-99,"lastcensus":1984,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"CD","iso_a3":"COD","iso_n3":"180","un_a3":"180","wb_a2":"ZR","wb_a3":"ZAR","woe_id":-99,"adm0_a3_is":"COD","adm0_a3_us":"COD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":15,"long_len":32,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[576,577,578,-226,579,580,-12,581,-15,582,-334]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Republic of Congo","sov_a3":"COG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Republic of Congo","adm0_a3":"COG","geou_dif":0,"geounit":"Republic of Congo","gu_a3":"COG","su_dif":0,"subunit":"Republic of Congo","su_a3":"COG","brk_diff":0,"name":"Congo","name_long":"Republic of Congo","brk_a3":"COG","brk_name":"Republic of Congo","brk_group":null,"abbrev":"Rep. Congo","postal":"CG","formal_en":"Republic of Congo","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Congo, Rep.","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":10,"pop_est":4012809,"gdp_md_est":15350,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CG","iso_a3":"COG","iso_n3":"178","un_a3":"178","wb_a2":"CG","wb_a3":"COG","woe_id":-99,"adm0_a3_is":"COG","adm0_a3_us":"COG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":17,"abbrev_len":10,"tiny":-99,"homepart":1},"arcs":[[-583,-14,583,584,-571,-335]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Cook Islands","adm0_a3":"COK","geou_dif":0,"geounit":"Cook Islands","gu_a3":"COK","su_dif":0,"subunit":"Cook Islands","su_a3":"COK","brk_diff":0,"name":"Cook Is.","name_long":"Cook Islands","brk_a3":"COK","brk_name":"Cook Is.","brk_group":null,"abbrev":"Cook Is.","postal":"CK","formal_en":null,"formal_fr":null,"note_adm0":"Assoc. with N.Z.","note_brk":null,"name_sort":"Cook Islands","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":11870,"gdp_md_est":183.2,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CK","iso_a3":"COK","iso_n3":"184","un_a3":"184","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"COK","adm0_a3_us":"COK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":8,"long_len":12,"abbrev_len":8,"tiny":3,"homepart":-99},"arcs":[[585]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Colombia","sov_a3":"COL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Colombia","adm0_a3":"COL","geou_dif":0,"geounit":"Colombia","gu_a3":"COL","su_dif":0,"subunit":"Colombia","su_a3":"COL","brk_diff":0,"name":"Colombia","name_long":"Colombia","brk_a3":"COL","brk_name":"Colombia","brk_group":null,"abbrev":"Col.","postal":"CO","formal_en":"Republic of Colombia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Colombia","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":3,"mapcolor13":1,"pop_est":45644023,"gdp_md_est":395400,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CO","iso_a3":"COL","iso_n3":"170","un_a3":"170","wb_a2":"CO","wb_a3":"COL","woe_id":-99,"adm0_a3_is":"COL","adm0_a3_us":"COL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[586]],[[587,-319,588,589,590,591,592]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Comoros","sov_a3":"COM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Comoros","adm0_a3":"COM","geou_dif":0,"geounit":"Comoros","gu_a3":"COM","su_dif":0,"subunit":"Comoros","su_a3":"COM","brk_diff":0,"name":"Comoros","name_long":"Comoros","brk_a3":"COM","brk_name":"Comoros","brk_group":null,"abbrev":"Com.","postal":"KM","formal_en":"Union of the Comoros","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Comoros","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":4,"mapcolor13":10,"pop_est":752438,"gdp_md_est":751.2,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KM","iso_a3":"COM","iso_n3":"174","un_a3":"174","wb_a2":"KM","wb_a3":"COM","woe_id":-99,"adm0_a3_is":"COM","adm0_a3_us":"COM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[593]],[[594]],[[595]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Cape Verde","sov_a3":"CPV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cape Verde","adm0_a3":"CPV","geou_dif":0,"geounit":"Cape Verde","gu_a3":"CPV","su_dif":0,"subunit":"Cape Verde","su_a3":"CPV","brk_diff":0,"name":"Cape Verde","name_long":"Cape Verde","brk_a3":"CPV","brk_name":"Cape Verde","brk_group":null,"abbrev":"C.Vd.","postal":"CV","formal_en":"Republic of Cape Verde","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cape Verde","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":4,"mapcolor13":11,"pop_est":429474,"gdp_md_est":1626,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CV","iso_a3":"CPV","iso_n3":"132","un_a3":"132","wb_a2":"CV","wb_a3":"CPV","woe_id":-99,"adm0_a3_is":"CPV","adm0_a3_us":"CPV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[596]],[[597]],[[598]],[[599]],[[600]],[[601]],[[602]],[[603]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Costa Rica","sov_a3":"CRI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Costa Rica","adm0_a3":"CRI","geou_dif":0,"geounit":"Costa Rica","gu_a3":"CRI","su_dif":0,"subunit":"Costa Rica","su_a3":"CRI","brk_diff":0,"name":"Costa Rica","name_long":"Costa Rica","brk_a3":"CRI","brk_name":"Costa Rica","brk_group":null,"abbrev":"C.R.","postal":"CR","formal_en":"Republic of Costa Rica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Costa Rica","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":4,"mapcolor13":2,"pop_est":4253877,"gdp_md_est":48320,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CR","iso_a3":"CRI","iso_n3":"188","un_a3":"188","wb_a2":"CR","wb_a3":"CRI","woe_id":-99,"adm0_a3_is":"CRI","adm0_a3_us":"CRI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[604,605,606,607]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cuba","sov_a3":"CUB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cuba","adm0_a3":"CUB","geou_dif":0,"geounit":"Cuba","gu_a3":"CUB","su_dif":0,"subunit":"Cuba","su_a3":"CUB","brk_diff":0,"name":"Cuba","name_long":"Cuba","brk_a3":"CUB","brk_name":"Cuba","brk_group":null,"abbrev":"Cuba","postal":"CU","formal_en":"Republic of Cuba","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cuba","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":4,"pop_est":11451652,"gdp_md_est":108200,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"CU","iso_a3":"CUB","iso_n3":"192","un_a3":"192","wb_a2":"CU","wb_a3":"CUB","woe_id":-99,"adm0_a3_is":"CUB","adm0_a3_us":"CUB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[608]],[[609]],[[610]],[[611]],[[612]],[[613]],[[614]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Curaçao","adm0_a3":"CUW","geou_dif":0,"geounit":"Curaçao","gu_a3":"CUW","su_dif":0,"subunit":"Curaçao","su_a3":"CUW","brk_diff":0,"name":"Curaçao","name_long":"Curaçao","brk_a3":"CUW","brk_name":"Curaçao","brk_group":null,"abbrev":"Cur.","postal":"CW","formal_en":"Curaçao","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"Curaçao","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":141766,"gdp_md_est":2838,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"CW","iso_a3":"CUW","iso_n3":"531","un_a3":"531","wb_a2":"CW","wb_a3":"CUW","woe_id":-99,"adm0_a3_is":"CUW","adm0_a3_us":"CUW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":4,"homepart":-99},"arcs":[[615]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Cayman Islands","adm0_a3":"CYM","geou_dif":0,"geounit":"Cayman Islands","gu_a3":"CYM","su_dif":0,"subunit":"Cayman Islands","su_a3":"CYM","brk_diff":0,"name":"Cayman Is.","name_long":"Cayman Islands","brk_a3":"CYM","brk_name":"Cayman Is.","brk_group":null,"abbrev":"Cym. Is.","postal":"KY","formal_en":"Cayman Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Cayman Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":49035,"gdp_md_est":1939,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KY","iso_a3":"CYM","iso_n3":"136","un_a3":"136","wb_a2":"KY","wb_a3":"CYM","woe_id":-99,"adm0_a3_is":"CYM","adm0_a3_us":"CYM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":10,"long_len":14,"abbrev_len":8,"tiny":2,"homepart":-99},"arcs":[[[616]],[[617]],[[618]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Northern Cyprus","sov_a3":"CYN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Northern Cyprus","adm0_a3":"CYN","geou_dif":0,"geounit":"Northern Cyprus","gu_a3":"CYN","su_dif":0,"subunit":"Northern Cyprus","su_a3":"CYN","brk_diff":1,"name":"N. Cyprus","name_long":"Northern Cyprus","brk_a3":"B20","brk_name":"N. Cyprus","brk_group":null,"abbrev":"N. Cy.","postal":"CN","formal_en":"Turkish Republic of Northern Cyprus","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Cyprus","name_sort":"Cyprus, Northern","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":265100,"gdp_md_est":3600,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"CYP","adm0_a3_us":"CYP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":9,"long_len":15,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[619,620]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Cyprus","sov_a3":"CYP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cyprus","adm0_a3":"CYP","geou_dif":0,"geounit":"Cyprus","gu_a3":"CYP","su_dif":0,"subunit":"Cyprus","su_a3":"CYP","brk_diff":0,"name":"Cyprus","name_long":"Cyprus","brk_a3":"CYP","brk_name":"Cyprus","brk_group":null,"abbrev":"Cyp.","postal":"CY","formal_en":"Republic of Cyprus","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cyprus","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":3,"mapcolor13":7,"pop_est":531640,"gdp_md_est":22700,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"CY","iso_a3":"CYP","iso_n3":"196","un_a3":"196","wb_a2":"CY","wb_a3":"CYP","woe_id":-99,"adm0_a3_is":"CYP","adm0_a3_us":"CYP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-620,621]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Czech Republic","sov_a3":"CZE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Czech Republic","adm0_a3":"CZE","geou_dif":0,"geounit":"Czech Republic","gu_a3":"CZE","su_dif":0,"subunit":"Czech Republic","su_a3":"CZE","brk_diff":0,"name":"Czech Rep.","name_long":"Czech Republic","brk_a3":"CZE","brk_name":"Czech Rep.","brk_group":null,"abbrev":"Cz. Rep.","postal":"CZ","formal_en":"Czech Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Czech Republic","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":6,"pop_est":10211904,"gdp_md_est":265200,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"CZ","iso_a3":"CZE","iso_n3":"203","un_a3":"203","wb_a2":"CZ","wb_a3":"CZE","woe_id":-99,"adm0_a3_is":"CZE","adm0_a3_us":"CZE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":14,"abbrev_len":8,"tiny":-99,"homepart":1},"arcs":[[622,623,-218,624]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Germany","sov_a3":"DEU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Germany","adm0_a3":"DEU","geou_dif":0,"geounit":"Germany","gu_a3":"DEU","su_dif":0,"subunit":"Germany","su_a3":"DEU","brk_diff":0,"name":"Germany","name_long":"Germany","brk_a3":"DEU","brk_name":"Germany","brk_group":null,"abbrev":"Ger.","postal":"D","formal_en":"Federal Republic of Germany","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Germany","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":5,"mapcolor13":1,"pop_est":82329758,"gdp_md_est":2918000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"DE","iso_a3":"DEU","iso_n3":"276","un_a3":"276","wb_a2":"DE","wb_a3":"DEU","woe_id":-99,"adm0_a3_is":"DEU","adm0_a3_us":"DEU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[625,626]],[[627]],[[628]],[[629]],[[630,631,-625,-217,-487,632,633,-229,634,635,636]],[[637]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Djibouti","sov_a3":"DJI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Djibouti","adm0_a3":"DJI","geou_dif":0,"geounit":"Djibouti","gu_a3":"DJI","su_dif":0,"subunit":"Djibouti","su_a3":"DJI","brk_diff":0,"name":"Djibouti","name_long":"Djibouti","brk_a3":"DJI","brk_name":"Djibouti","brk_group":null,"abbrev":"Dji.","postal":"DJ","formal_en":"Republic of Djibouti","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Djibouti","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":4,"mapcolor13":8,"pop_est":516055,"gdp_md_est":1885,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DJ","iso_a3":"DJI","iso_n3":"262","un_a3":"262","wb_a2":"DJ","wb_a3":"DJI","woe_id":-99,"adm0_a3_is":"DJI","adm0_a3_us":"DJI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Middle East & North Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[638,639,640,641]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Dominica","sov_a3":"DMA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Dominica","adm0_a3":"DMA","geou_dif":0,"geounit":"Dominica","gu_a3":"DMA","su_dif":0,"subunit":"Dominica","su_a3":"DMA","brk_diff":0,"name":"Dominica","name_long":"Dominica","brk_a3":"DMA","brk_name":"Dominica","brk_group":null,"abbrev":"D'inca","postal":"DM","formal_en":"Commonwealth of Dominica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Dominica","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":2,"mapcolor13":12,"pop_est":72660,"gdp_md_est":719.6,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DM","iso_a3":"DMA","iso_n3":"212","un_a3":"212","wb_a2":"DM","wb_a3":"DMA","woe_id":-99,"adm0_a3_is":"DMA","adm0_a3_us":"DMA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":6,"tiny":4,"homepart":1},"arcs":[[642]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Country","admin":"Denmark","adm0_a3":"DNK","geou_dif":0,"geounit":"Denmark","gu_a3":"DNK","su_dif":0,"subunit":"Denmark","su_a3":"DNK","brk_diff":0,"name":"Denmark","name_long":"Denmark","brk_a3":"DNK","brk_name":"Denmark","brk_group":null,"abbrev":"Den.","postal":"DK","formal_en":"Kingdom of Denmark","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Denmark","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":5500510,"gdp_md_est":203600,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"DK","iso_a3":"DNK","iso_n3":"208","un_a3":"208","wb_a2":"DK","wb_a3":"DNK","woe_id":-99,"adm0_a3_is":"DNK","adm0_a3_us":"DNK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[643]],[[644]],[[645]],[[646]],[[647]],[[648]],[[649]],[[650]],[[651]],[[652]],[[653]],[[-637,654]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Dominican Republic","sov_a3":"DOM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Dominican Republic","adm0_a3":"DOM","geou_dif":0,"geounit":"Dominican Republic","gu_a3":"DOM","su_dif":0,"subunit":"Dominican Republic","su_a3":"DOM","brk_diff":0,"name":"Dominican Rep.","name_long":"Dominican Republic","brk_a3":"DOM","brk_name":"Dominican Rep.","brk_group":null,"abbrev":"Dom. Rep.","postal":"DO","formal_en":"Dominican Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Dominican Republic","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":5,"mapcolor13":7,"pop_est":9650054,"gdp_md_est":78000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DO","iso_a3":"DOM","iso_n3":"214","un_a3":"214","wb_a2":"DO","wb_a3":"DOM","woe_id":-99,"adm0_a3_is":"DOM","adm0_a3_us":"DOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":14,"long_len":18,"abbrev_len":9,"tiny":-99,"homepart":1},"arcs":[[655,656]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Algeria","sov_a3":"DZA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Algeria","adm0_a3":"DZA","geou_dif":0,"geounit":"Algeria","gu_a3":"DZA","su_dif":0,"subunit":"Algeria","su_a3":"DZA","brk_diff":0,"name":"Algeria","name_long":"Algeria","brk_a3":"DZA","brk_name":"Algeria","brk_group":null,"abbrev":"Alg.","postal":"DZ","formal_en":"People's Democratic Republic of Algeria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Algeria","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":6,"mapcolor13":3,"pop_est":34178188,"gdp_md_est":232900,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"DZ","iso_a3":"DZA","iso_n3":"012","un_a3":"012","wb_a2":"DZ","wb_a3":"DZA","woe_id":-99,"adm0_a3_is":"DZA","adm0_a3_us":"DZA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[657,658,659,660,661,662,663,664]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ecuador","sov_a3":"ECU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ecuador","adm0_a3":"ECU","geou_dif":0,"geounit":"Ecuador","gu_a3":"ECU","su_dif":0,"subunit":"Ecuador","su_a3":"ECU","brk_diff":0,"name":"Ecuador","name_long":"Ecuador","brk_a3":"ECU","brk_name":"Ecuador","brk_group":null,"abbrev":"Ecu.","postal":"EC","formal_en":"Republic of Ecuador","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ecuador","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":12,"pop_est":14573101,"gdp_md_est":107700,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"EC","iso_a3":"ECU","iso_n3":"218","un_a3":"218","wb_a2":"EC","wb_a3":"ECU","woe_id":-99,"adm0_a3_is":"ECU","adm0_a3_us":"ECU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[665]],[[666]],[[667]],[[668]],[[669]],[[670]],[[671]],[[672]],[[673,674,-590]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Egypt","sov_a3":"EGY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Egypt","adm0_a3":"EGY","geou_dif":0,"geounit":"Egypt","gu_a3":"EGY","su_dif":0,"subunit":"Egypt","su_a3":"EGY","brk_diff":0,"name":"Egypt","name_long":"Egypt","brk_a3":"EGY","brk_name":"Egypt","brk_group":null,"abbrev":"Egypt","postal":"EG","formal_en":"Arab Republic of Egypt","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Egypt, Arab Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":7,"mapcolor13":2,"pop_est":83082869,"gdp_md_est":443700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"EG","iso_a3":"EGY","iso_n3":"818","un_a3":"818","wb_a2":"EG","wb_a3":"EGY","woe_id":-99,"adm0_a3_is":"EGY","adm0_a3_us":"EGY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[675,676,677,678,679,680]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Eritrea","sov_a3":"ERI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Eritrea","adm0_a3":"ERI","geou_dif":0,"geounit":"Eritrea","gu_a3":"ERI","su_dif":0,"subunit":"Eritrea","su_a3":"ERI","brk_diff":0,"name":"Eritrea","name_long":"Eritrea","brk_a3":"ERI","brk_name":"Eritrea","brk_group":null,"abbrev":"Erit.","postal":"ER","formal_en":"State of Eritrea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Eritrea","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":2,"mapcolor13":12,"pop_est":5647168,"gdp_md_est":3945,"pop_year":-99,"lastcensus":1984,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ER","iso_a3":"ERI","iso_n3":"232","un_a3":"232","wb_a2":"ER","wb_a3":"ERI","woe_id":-99,"adm0_a3_is":"ERI","adm0_a3_us":"ERI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[681]],[[682]],[[683,-641,684,685]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Spain","sov_a3":"ESP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Spain","adm0_a3":"ESP","geou_dif":0,"geounit":"Spain","gu_a3":"ESP","su_dif":0,"subunit":"Spain","su_a3":"ESP","brk_diff":0,"name":"Spain","name_long":"Spain","brk_a3":"ESP","brk_name":"Spain","brk_group":null,"abbrev":"Sp.","postal":"E","formal_en":"Kingdom of Spain","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Spain","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":5,"mapcolor13":5,"pop_est":40525002,"gdp_md_est":1403000,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"ES","iso_a3":"ESP","iso_n3":"724","un_a3":"724","wb_a2":"ES","wb_a3":"ESP","woe_id":-99,"adm0_a3_is":"ESP","adm0_a3_us":"ESP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":5,"abbrev_len":3,"tiny":-99,"homepart":1},"arcs":[[[686]],[[687]],[[688]],[[689]],[[690]],[[691]],[[692]],[[693]],[[694]],[[695]],[[696]],[[697,-25,698,699,700,701]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Estonia","sov_a3":"EST","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Estonia","adm0_a3":"EST","geou_dif":0,"geounit":"Estonia","gu_a3":"EST","su_dif":0,"subunit":"Estonia","su_a3":"EST","brk_diff":0,"name":"Estonia","name_long":"Estonia","brk_a3":"EST","brk_name":"Estonia","brk_group":null,"abbrev":"Est.","postal":"EST","formal_en":"Republic of Estonia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Estonia","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":10,"pop_est":1299371,"gdp_md_est":27410,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"EE","iso_a3":"EST","iso_n3":"233","un_a3":"233","wb_a2":"EE","wb_a3":"EST","woe_id":-99,"adm0_a3_is":"EST","adm0_a3_us":"EST","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[702]],[[703]],[[704]],[[705,706,707]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Ethiopia","sov_a3":"ETH","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ethiopia","adm0_a3":"ETH","geou_dif":0,"geounit":"Ethiopia","gu_a3":"ETH","su_dif":0,"subunit":"Ethiopia","su_a3":"ETH","brk_diff":0,"name":"Ethiopia","name_long":"Ethiopia","brk_a3":"ETH","brk_name":"Ethiopia","brk_group":null,"abbrev":"Eth.","postal":"ET","formal_en":"Federal Democratic Republic of Ethiopia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ethiopia","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":1,"mapcolor13":13,"pop_est":85237338,"gdp_md_est":68770,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ET","iso_a3":"ETH","iso_n3":"231","un_a3":"231","wb_a2":"ET","wb_a3":"ETH","woe_id":-99,"adm0_a3_is":"ETH","adm0_a3_us":"ETH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-640,708,709,710,711,712,-685]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Finland","sov_a3":"FI1","adm0_dif":1,"level":2,"type":"Country","admin":"Finland","adm0_a3":"FIN","geou_dif":0,"geounit":"Finland","gu_a3":"FIN","su_dif":0,"subunit":"Finland","su_a3":"FIN","brk_diff":0,"name":"Finland","name_long":"Finland","brk_a3":"FIN","brk_name":"Finland","brk_group":null,"abbrev":"Fin.","postal":"FIN","formal_en":"Republic of Finland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Finland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":6,"pop_est":5250275,"gdp_md_est":193500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FI","iso_a3":"FIN","iso_n3":"246","un_a3":"246","wb_a2":"FI","wb_a3":"FIN","woe_id":-99,"adm0_a3_is":"FIN","adm0_a3_us":"FIN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[713]],[[714]],[[715]],[[716]],[[717]],[[718]],[[719]],[[720,721,722,723]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Fiji","sov_a3":"FJI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Fiji","adm0_a3":"FJI","geou_dif":0,"geounit":"Fiji","gu_a3":"FJI","su_dif":0,"subunit":"Fiji","su_a3":"FJI","brk_diff":0,"name":"Fiji","name_long":"Fiji","brk_a3":"FJI","brk_name":"Fiji","brk_group":null,"abbrev":"Fiji","postal":"FJ","formal_en":"Republic of Fiji","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Fiji","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":2,"mapcolor13":2,"pop_est":944720,"gdp_md_est":3579,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"FJ","iso_a3":"FJI","iso_n3":"242","un_a3":"242","wb_a2":"FJ","wb_a3":"FJI","woe_id":-99,"adm0_a3_is":"FJI","adm0_a3_us":"FJI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[724]],[[725]],[[726]],[[727]],[[728]],[[729]],[[730]],[[731]],[[732]],[[733]],[[734]],[[735]],[[736]],[[737]],[[738]],[[739]],[[740]],[[741]],[[742]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Falkland Islands","adm0_a3":"FLK","geou_dif":0,"geounit":"Falkland Islands","gu_a3":"FLK","su_dif":0,"subunit":"Falkland Islands","su_a3":"FLK","brk_diff":1,"name":"Falkland Is.","name_long":"Falkland Islands","brk_a3":"B12","brk_name":"Falkland Is.","brk_group":null,"abbrev":"Flk. Is.","postal":"FK","formal_en":"Falkland Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":"Admin. by U.K.; Claimed by Argentina","name_sort":"Falkland Islands","name_alt":"Islas Malvinas","mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":3140,"gdp_md_est":105.1,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FK","iso_a3":"FLK","iso_n3":"238","un_a3":"238","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"FLK","adm0_a3_us":"FLK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":12,"long_len":16,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[[743]],[[744]],[[745]],[[746]],[[747]],[[748]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Country","admin":"France","adm0_a3":"FRA","geou_dif":0,"geounit":"France","gu_a3":"FRA","su_dif":0,"subunit":"France","su_a3":"FRA","brk_diff":0,"name":"France","name_long":"France","brk_a3":"FRA","brk_name":"France","brk_group":null,"abbrev":"Fr.","postal":"F","formal_en":"French Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"France","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":64057792,"gdp_md_est":2128000,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"FR","iso_a3":"FRA","iso_n3":"250","un_a3":"250","wb_a2":"FR","wb_a3":"FRA","woe_id":-99,"adm0_a3_is":"FRA","adm0_a3_us":"FRA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":3,"tiny":-99,"homepart":1},"arcs":[[[749]],[[750]],[[-314,751,752]],[[753]],[[754]],[[755]],[[756]],[[757]],[[758]],[[759,-633,-486,760,761,762,763,-699,-26,-698,764,-231]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Faroe Islands","adm0_a3":"FRO","geou_dif":0,"geounit":"Faroe Islands","gu_a3":"FRO","su_dif":0,"subunit":"Faroe Islands","su_a3":"FRO","brk_diff":0,"name":"Faeroe Is.","name_long":"Faeroe Islands","brk_a3":"FRO","brk_name":"Faeroe Islands","brk_group":null,"abbrev":"Faeroe Is.","postal":"FO","formal_en":"Føroyar Is. (Faeroe Is.)","formal_fr":null,"note_adm0":"Den.","note_brk":null,"name_sort":"Faeroe Islands","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":48856,"gdp_md_est":1000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"FO","iso_a3":"FRO","iso_n3":"234","un_a3":"234","wb_a2":"FO","wb_a3":"FRO","woe_id":-99,"adm0_a3_is":"FRO","adm0_a3_us":"FRO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":14,"abbrev_len":10,"tiny":3,"homepart":-99},"arcs":[[[765]],[[766]],[[767]],[[768]],[[769]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Federated States of Micronesia","sov_a3":"FSM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Federated States of Micronesia","adm0_a3":"FSM","geou_dif":0,"geounit":"Federated States of Micronesia","gu_a3":"FSM","su_dif":0,"subunit":"Federated States of Micronesia","su_a3":"FSM","brk_diff":0,"name":"Micronesia","name_long":"Federated States of Micronesia","brk_a3":"FSM","brk_name":"Micronesia","brk_group":null,"abbrev":"F.S.M.","postal":"FSM","formal_en":"Federated States of Micronesia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Micronesia, Federated States of","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":4,"mapcolor13":13,"pop_est":107434,"gdp_md_est":238.1,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"FM","iso_a3":"FSM","iso_n3":"583","un_a3":"583","wb_a2":"FM","wb_a3":"FSM","woe_id":-99,"adm0_a3_is":"FSM","adm0_a3_us":"FSM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":10,"long_len":30,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[770]],[[771]],[[772]],[[773]],[[774]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Gabon","sov_a3":"GAB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Gabon","adm0_a3":"GAB","geou_dif":0,"geounit":"Gabon","gu_a3":"GAB","su_dif":0,"subunit":"Gabon","su_a3":"GAB","brk_diff":0,"name":"Gabon","name_long":"Gabon","brk_a3":"GAB","brk_name":"Gabon","brk_group":null,"abbrev":"Gabon","postal":"GA","formal_en":"Gabonese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Gabon","name_alt":null,"mapcolor7":6,"mapcolor8":2,"mapcolor9":5,"mapcolor13":5,"pop_est":1514993,"gdp_md_est":21110,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GA","iso_a3":"GAB","iso_n3":"266","un_a3":"266","wb_a2":"GA","wb_a3":"GAB","woe_id":-99,"adm0_a3_is":"GAB","adm0_a3_us":"GAB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[-585,775,776,-572]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"United Kingdom","adm0_a3":"GBR","geou_dif":0,"geounit":"United Kingdom","gu_a3":"GBR","su_dif":0,"subunit":"United Kingdom","su_a3":"GBR","brk_diff":0,"name":"United Kingdom","name_long":"United Kingdom","brk_a3":"GBR","brk_name":"United Kingdom","brk_group":null,"abbrev":"U.K.","postal":"GB","formal_en":"United Kingdom of Great Britain and Northern Ireland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United Kingdom","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":62262000,"gdp_md_est":1977704,"pop_year":0,"lastcensus":2011,"gdp_year":2009,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"GB","iso_a3":"GBR","iso_n3":"826","un_a3":"826","wb_a2":"GB","wb_a3":"GBR","woe_id":-99,"adm0_a3_is":"GBR","adm0_a3_us":"GBR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":14,"long_len":14,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[777]],[[778]],[[779,780]],[[781]],[[782]],[[783]],[[784]],[[785]],[[786]],[[787]],[[788]],[[789]],[[790]],[[791]],[[792]],[[793]],[[794]],[[795]],[[796]],[[797]],[[798]],[[799]],[[800]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Georgia","sov_a3":"GEO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Georgia","adm0_a3":"GEO","geou_dif":0,"geounit":"Georgia","gu_a3":"GEO","su_dif":0,"subunit":"Georgia","su_a3":"GEO","brk_diff":0,"name":"Georgia","name_long":"Georgia","brk_a3":"GEO","brk_name":"Georgia","brk_group":null,"abbrev":"Geo.","postal":"GE","formal_en":"Georgia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Georgia","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":3,"mapcolor13":2,"pop_est":4615807,"gdp_md_est":21510,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GE","iso_a3":"GEO","iso_n3":"268","un_a3":"268","wb_a2":"GE","wb_a3":"GEO","woe_id":-99,"adm0_a3_is":"GEO","adm0_a3_us":"GEO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-223,-51,801,802,803]]},{"type":"Polygon","properties":{"scalerank":4,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Guernsey","adm0_a3":"GGY","geou_dif":0,"geounit":"Guernsey","gu_a3":"GGY","su_dif":0,"subunit":"Guernsey","su_a3":"GGY","brk_diff":0,"name":"Guernsey","name_long":"Guernsey","brk_a3":"GGY","brk_name":"Guernsey","brk_group":"Channel Islands","abbrev":"Guern.","postal":"GG","formal_en":"Bailiwick of Guernsey","formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Guernsey","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":68633,"gdp_md_est":2742,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GG","iso_a3":"GGY","iso_n3":"831","un_a3":"831","wb_a2":"JG","wb_a3":"CHI","woe_id":-99,"adm0_a3_is":"GGY","adm0_a3_us":"GGY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[804]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ghana","sov_a3":"GHA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ghana","adm0_a3":"GHA","geou_dif":0,"geounit":"Ghana","gu_a3":"GHA","su_dif":0,"subunit":"Ghana","su_a3":"GHA","brk_diff":0,"name":"Ghana","name_long":"Ghana","brk_a3":"GHA","brk_name":"Ghana","brk_group":null,"abbrev":"Ghana","postal":"GH","formal_en":"Republic of Ghana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ghana","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":1,"mapcolor13":4,"pop_est":23832495,"gdp_md_est":34200,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GH","iso_a3":"GHA","iso_n3":"288","un_a3":"288","wb_a2":"GH","wb_a3":"GHA","woe_id":-99,"adm0_a3_is":"GHA","adm0_a3_us":"GHA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[805,806,-564,807,-566,-242]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Guinea","sov_a3":"GIN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guinea","adm0_a3":"GIN","geou_dif":0,"geounit":"Guinea","gu_a3":"GIN","su_dif":0,"subunit":"Guinea","su_a3":"GIN","brk_diff":0,"name":"Guinea","name_long":"Guinea","brk_a3":"GIN","brk_name":"Guinea","brk_group":null,"abbrev":"Gin.","postal":"GN","formal_en":"Republic of Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guinea","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":7,"mapcolor13":2,"pop_est":10057975,"gdp_md_est":10600,"pop_year":-99,"lastcensus":1996,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GN","iso_a3":"GIN","iso_n3":"324","un_a3":"324","wb_a2":"GN","wb_a3":"GIN","woe_id":-99,"adm0_a3_is":"GIN","adm0_a3_us":"GIN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[808,-569,809,810,811,812,813]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Gambia","sov_a3":"GMB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Gambia","adm0_a3":"GMB","geou_dif":0,"geounit":"Gambia","gu_a3":"GMB","su_dif":0,"subunit":"Gambia","su_a3":"GMB","brk_diff":0,"name":"Gambia","name_long":"The Gambia","brk_a3":"GMB","brk_name":"Gambia","brk_group":null,"abbrev":"Gambia","postal":"GM","formal_en":"Republic of the Gambia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Gambia, The","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":1782893,"gdp_md_est":2272,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GM","iso_a3":"GMB","iso_n3":"270","un_a3":"270","wb_a2":"GM","wb_a3":"GMB","woe_id":-99,"adm0_a3_is":"GMB","adm0_a3_us":"GMB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":10,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[814,815]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Guinea Bissau","sov_a3":"GNB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guinea Bissau","adm0_a3":"GNB","geou_dif":0,"geounit":"Guinea Bissau","gu_a3":"GNB","su_dif":0,"subunit":"Guinea Bissau","su_a3":"GNB","brk_diff":0,"name":"Guinea-Bissau","name_long":"Guinea-Bissau","brk_a3":"GNB","brk_name":"Guinea-Bissau","brk_group":null,"abbrev":"GnB.","postal":"GW","formal_en":"Republic of Guinea-Bissau","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guinea-Bissau","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":4,"pop_est":1533964,"gdp_md_est":904.2,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GW","iso_a3":"GNB","iso_n3":"624","un_a3":"624","wb_a2":"GW","wb_a3":"GNB","woe_id":-99,"adm0_a3_is":"GNB","adm0_a3_us":"GNB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":13,"long_len":13,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[816]],[[817]],[[818]],[[819]],[[820]],[[821]],[[822,823,-813]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Equatorial Guinea","sov_a3":"GNQ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Equatorial Guinea","adm0_a3":"GNQ","geou_dif":0,"geounit":"Equatorial Guinea","gu_a3":"GNQ","su_dif":0,"subunit":"Equatorial Guinea","su_a3":"GNQ","brk_diff":0,"name":"Eq. Guinea","name_long":"Equatorial Guinea","brk_a3":"GNQ","brk_name":"Eq. Guinea","brk_group":null,"abbrev":"Eq. G.","postal":"GQ","formal_en":"Republic of Equatorial Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Equatorial Guinea","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":650702,"gdp_md_est":14060,"pop_year":0,"lastcensus":2002,"gdp_year":0,"economy":"7. Least developed region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GQ","iso_a3":"GNQ","iso_n3":"226","un_a3":"226","wb_a2":"GQ","wb_a3":"GNQ","woe_id":-99,"adm0_a3_is":"GNQ","adm0_a3_us":"GNQ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":17,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[824,-573,-777]],[[825]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Greece","sov_a3":"GRC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Greece","adm0_a3":"GRC","geou_dif":0,"geounit":"Greece","gu_a3":"GRC","su_dif":0,"subunit":"Greece","su_a3":"GRC","brk_diff":0,"name":"Greece","name_long":"Greece","brk_a3":"GRC","brk_name":"Greece","brk_group":null,"abbrev":"Greece","postal":"GR","formal_en":"Hellenic Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Greece","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":10737428,"gdp_md_est":343000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"GR","iso_a3":"GRC","iso_n3":"300","un_a3":"300","wb_a2":"GR","wb_a3":"GRC","woe_id":-99,"adm0_a3_is":"GRC","adm0_a3_us":"GRC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[826]],[[827]],[[828]],[[829]],[[830]],[[831]],[[832]],[[833]],[[834]],[[835]],[[836]],[[837]],[[838]],[[839]],[[840]],[[841]],[[842]],[[843]],[[844]],[[845]],[[846]],[[847]],[[848]],[[849]],[[850]],[[851]],[[852]],[[853]],[[854]],[[855]],[[856]],[[857]],[[858]],[[859]],[[860]],[[861]],[[862]],[[863]],[[864]],[[865,-19,866,-256,867]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Grenada","sov_a3":"GRD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Grenada","adm0_a3":"GRD","geou_dif":0,"geounit":"Grenada","gu_a3":"GRD","su_dif":0,"subunit":"Grenada","su_a3":"GRD","brk_diff":0,"name":"Grenada","name_long":"Grenada","brk_a3":"GRD","brk_name":"Grenada","brk_group":null,"abbrev":"Gren.","postal":"GD","formal_en":"Grenada","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Grenada","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":3,"mapcolor13":6,"pop_est":90739,"gdp_md_est":1161,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GD","iso_a3":"GRD","iso_n3":"308","un_a3":"308","wb_a2":"GD","wb_a3":"GRD","woe_id":-99,"adm0_a3_is":"GRD","adm0_a3_us":"GRD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[868]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Denmark","sov_a3":"DN1","adm0_dif":1,"level":2,"type":"Country","admin":"Greenland","adm0_a3":"GRL","geou_dif":0,"geounit":"Greenland","gu_a3":"GRL","su_dif":0,"subunit":"Greenland","su_a3":"GRL","brk_diff":0,"name":"Greenland","name_long":"Greenland","brk_a3":"GRL","brk_name":"Greenland","brk_group":null,"abbrev":"Grlnd.","postal":"GL","formal_en":"Greenland","formal_fr":null,"note_adm0":"Den.","note_brk":null,"name_sort":"Greenland","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":3,"mapcolor13":12,"pop_est":57600,"gdp_md_est":1100,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GL","iso_a3":"GRL","iso_n3":"304","un_a3":"304","wb_a2":"GL","wb_a3":"GRL","woe_id":-99,"adm0_a3_is":"GRL","adm0_a3_us":"GRL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[[869]],[[870]],[[871]],[[872]],[[873]],[[874]],[[875]],[[876]],[[877]],[[878]],[[879]],[[880]],[[881]],[[882]],[[883]],[[884]],[[885]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Guatemala","sov_a3":"GTM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guatemala","adm0_a3":"GTM","geou_dif":0,"geounit":"Guatemala","gu_a3":"GTM","su_dif":0,"subunit":"Guatemala","su_a3":"GTM","brk_diff":0,"name":"Guatemala","name_long":"Guatemala","brk_a3":"GTM","brk_name":"Guatemala","brk_group":null,"abbrev":"Guat.","postal":"GT","formal_en":"Republic of Guatemala","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guatemala","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":3,"mapcolor13":6,"pop_est":13276517,"gdp_md_est":68580,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GT","iso_a3":"GTM","iso_n3":"320","un_a3":"320","wb_a2":"GT","wb_a3":"GTM","woe_id":-99,"adm0_a3_is":"GTM","adm0_a3_us":"GTM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":5,"tiny":4,"homepart":1},"arcs":[[-289,886,887,888,889,890]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Guam","adm0_a3":"GUM","geou_dif":0,"geounit":"Guam","gu_a3":"GUM","su_dif":0,"subunit":"Guam","su_a3":"GUM","brk_diff":0,"name":"Guam","name_long":"Guam","brk_a3":"GUM","brk_name":"Guam","brk_group":null,"abbrev":"Guam","postal":"GU","formal_en":"Territory of Guam","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"Guam","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":178430,"gdp_md_est":2500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"GU","iso_a3":"GUM","iso_n3":"316","un_a3":"316","wb_a2":"GU","wb_a3":"GUM","woe_id":-99,"adm0_a3_is":"GUM","adm0_a3_us":"GUM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":2,"homepart":-99},"arcs":[[891]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Guyana","sov_a3":"GUY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Guyana","adm0_a3":"GUY","geou_dif":0,"geounit":"Guyana","gu_a3":"GUY","su_dif":0,"subunit":"Guyana","su_a3":"GUY","brk_diff":0,"name":"Guyana","name_long":"Guyana","brk_a3":"GUY","brk_name":"Guyana","brk_group":null,"abbrev":"Guy.","postal":"GY","formal_en":"Co-operative Republic of Guyana","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Guyana","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":4,"mapcolor13":8,"pop_est":772298,"gdp_md_est":2966,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"GY","iso_a3":"GUY","iso_n3":"328","un_a3":"328","wb_a2":"GY","wb_a3":"GUY","woe_id":-99,"adm0_a3_is":"GUY","adm0_a3_us":"GUY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[892,-321,893,894]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"Hong Kong S.A.R.","adm0_a3":"HKG","geou_dif":0,"geounit":"Hong Kong S.A.R.","gu_a3":"HKG","su_dif":0,"subunit":"Hong Kong S.A.R.","su_a3":"HKG","brk_diff":0,"name":"Hong Kong","name_long":"Hong Kong","brk_a3":"HKG","brk_name":"Hong Kong","brk_group":null,"abbrev":"H.K.","postal":"HK","formal_en":"Hong Kong Special Administrative Region, PRC","formal_fr":null,"note_adm0":"China","note_brk":null,"name_sort":"Hong Kong SAR, China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":7061200,"gdp_md_est":351119,"pop_year":2010,"lastcensus":2006,"gdp_year":2011,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":0,"fips_10":null,"iso_a2":"HK","iso_a3":"HKG","iso_n3":"344","un_a3":"344","wb_a2":"HK","wb_a3":"HKG","woe_id":-99,"adm0_a3_is":"HKG","adm0_a3_us":"HKG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[895]],[[896]],[[-534,897]]]},{"type":"Polygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Heard Island and McDonald Islands","adm0_a3":"HMD","geou_dif":0,"geounit":"Heard Island and McDonald Islands","gu_a3":"HMD","su_dif":0,"subunit":"Heard Island and McDonald Islands","su_a3":"HMD","brk_diff":0,"name":"Heard I. and McDonald Is.","name_long":"Heard I. and McDonald Islands","brk_a3":"HMD","brk_name":"Heard I. and McDonald Is.","brk_group":null,"abbrev":"H.M.Is.","postal":"HM","formal_en":"Territory of Heard Island and McDonald Islands","formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Heard Island and McDonald Islands","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":-99,"gdp_md_est":-99,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"HM","iso_a3":"HMD","iso_n3":"334","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"HMD","adm0_a3_us":"HMD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":25,"long_len":29,"abbrev_len":7,"tiny":-99,"homepart":-99},"arcs":[[898]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Honduras","sov_a3":"HND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Honduras","adm0_a3":"HND","geou_dif":0,"geounit":"Honduras","gu_a3":"HND","su_dif":0,"subunit":"Honduras","su_a3":"HND","brk_diff":0,"name":"Honduras","name_long":"Honduras","brk_a3":"HND","brk_name":"Honduras","brk_group":null,"abbrev":"Hond.","postal":"HN","formal_en":"Republic of Honduras","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Honduras","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":2,"mapcolor13":5,"pop_est":7792854,"gdp_md_est":33720,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"HN","iso_a3":"HND","iso_n3":"340","un_a3":"340","wb_a2":"HN","wb_a3":"HND","woe_id":-99,"adm0_a3_is":"HND","adm0_a3_us":"HND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[899,900,901,-888,902]],[[903]],[[904]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Croatia","sov_a3":"HRV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Croatia","adm0_a3":"HRV","geou_dif":0,"geounit":"Croatia","gu_a3":"HRV","su_dif":0,"subunit":"Croatia","su_a3":"HRV","brk_diff":0,"name":"Croatia","name_long":"Croatia","brk_a3":"HRV","brk_name":"Croatia","brk_group":null,"abbrev":"Cro.","postal":"HR","formal_en":"Republic of Croatia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Croatia","name_alt":null,"mapcolor7":5,"mapcolor8":4,"mapcolor9":5,"mapcolor13":1,"pop_est":4489409,"gdp_md_est":82390,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"HR","iso_a3":"HRV","iso_n3":"191","un_a3":"191","wb_a2":"HR","wb_a3":"HRV","woe_id":-99,"adm0_a3_is":"HRV","adm0_a3_us":"HRV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[905]],[[906]],[[-278,907,908]],[[909]],[[910]],[[911]],[[912]],[[913]],[[914]],[[915]],[[916]],[[917]],[[918,-280,919,920,921]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Haiti","sov_a3":"HTI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Haiti","adm0_a3":"HTI","geou_dif":0,"geounit":"Haiti","gu_a3":"HTI","su_dif":0,"subunit":"Haiti","su_a3":"HTI","brk_diff":0,"name":"Haiti","name_long":"Haiti","brk_a3":"HTI","brk_name":"Haiti","brk_group":null,"abbrev":"Haiti","postal":"HT","formal_en":"Republic of Haiti","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Haiti","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":7,"mapcolor13":2,"pop_est":9035536,"gdp_md_est":11500,"pop_year":-99,"lastcensus":2003,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"HT","iso_a3":"HTI","iso_n3":"332","un_a3":"332","wb_a2":"HT","wb_a3":"HTI","woe_id":-99,"adm0_a3_is":"HTI","adm0_a3_us":"HTI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[922]],[[-656,923]],[[924]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Hungary","sov_a3":"HUN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Hungary","adm0_a3":"HUN","geou_dif":0,"geounit":"Hungary","gu_a3":"HUN","su_dif":0,"subunit":"Hungary","su_a3":"HUN","brk_diff":0,"name":"Hungary","name_long":"Hungary","brk_a3":"HUN","brk_name":"Hungary","brk_group":null,"abbrev":"Hun.","postal":"HU","formal_en":"Republic of Hungary","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Hungary","name_alt":null,"mapcolor7":4,"mapcolor8":6,"mapcolor9":1,"mapcolor13":5,"pop_est":9905596,"gdp_md_est":196600,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"HU","iso_a3":"HUN","iso_n3":"348","un_a3":"348","wb_a2":"HU","wb_a3":"HUN","woe_id":-99,"adm0_a3_is":"HUN","adm0_a3_us":"HUN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[925,926,927,-922,928,-211,929]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Indonesia","sov_a3":"IDN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Indonesia","adm0_a3":"IDN","geou_dif":0,"geounit":"Indonesia","gu_a3":"IDN","su_dif":0,"subunit":"Indonesia","su_a3":"IDN","brk_diff":0,"name":"Indonesia","name_long":"Indonesia","brk_a3":"IDN","brk_name":"Indonesia","brk_group":null,"abbrev":"Indo.","postal":"INDO","formal_en":"Republic of Indonesia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Indonesia","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":11,"pop_est":240271522,"gdp_md_est":914600,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ID","iso_a3":"IDN","iso_n3":"360","un_a3":"360","wb_a2":"ID","wb_a3":"IDN","woe_id":-99,"adm0_a3_is":"IDN","adm0_a3_us":"IDN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[930]],[[931]],[[932]],[[933]],[[934,935,936,937]],[[938]],[[939]],[[940]],[[941]],[[942]],[[943]],[[944]],[[945]],[[946]],[[947]],[[948]],[[949]],[[950]],[[951]],[[952]],[[953]],[[954]],[[955]],[[956]],[[957]],[[958]],[[959]],[[960]],[[961]],[[962]],[[963]],[[964]],[[965]],[[966]],[[967]],[[968]],[[969]],[[970]],[[971]],[[972]],[[973]],[[974]],[[975]],[[976]],[[977]],[[978]],[[979]],[[980]],[[981]],[[982]],[[983]],[[984]],[[985]],[[986]],[[987]],[[988]],[[989]],[[990]],[[991]],[[992]],[[993]],[[994]],[[995]],[[996]],[[997]],[[998]],[[999]],[[1000]],[[1001]],[[1002]],[[1003]],[[1004]],[[1005]],[[1006]],[[1007]],[[1008]],[[1009]],[[1010]],[[1011]],[[1012]],[[1013]],[[1014]],[[1015]],[[1016]],[[1017]],[[1018]],[[1019]],[[1020]],[[1021,1022,1023]],[[1024]],[[1025]],[[1026]],[[1027]],[[1028]],[[1029]],[[1030]],[[1031]],[[1032]],[[1033]],[[1034]],[[1035]],[[1036]],[[1037]],[[1038]],[[1039]],[[1040]],[[1041]],[[1042]],[[1043]],[[1044]],[[1045]],[[1046]],[[1047]],[[1048]],[[1049]],[[1050]],[[1051]],[[1052]],[[1053]],[[1054]],[[1055]],[[1056]],[[1057]],[[1058]],[[1059]],[[1060]],[[1061]],[[1062,1063]],[[1064]],[[1065,1066]],[[1067]],[[1068]],[[1069]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Isle of Man","adm0_a3":"IMN","geou_dif":0,"geounit":"Isle of Man","gu_a3":"IMN","su_dif":0,"subunit":"Isle of Man","su_a3":"IMN","brk_diff":0,"name":"Isle of Man","name_long":"Isle of Man","brk_a3":"IMN","brk_name":"Isle of Man","brk_group":null,"abbrev":"IoMan","postal":"IM","formal_en":null,"formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Isle of Man","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":76512,"gdp_md_est":2719,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"IM","iso_a3":"IMN","iso_n3":"833","un_a3":"833","wb_a2":"IM","wb_a3":"IMY","woe_id":-99,"adm0_a3_is":"IMN","adm0_a3_us":"IMN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":-99},"arcs":[[1070]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"India","sov_a3":"IND","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"India","adm0_a3":"IND","geou_dif":0,"geounit":"India","gu_a3":"IND","su_dif":0,"subunit":"India","su_a3":"IND","brk_diff":0,"name":"India","name_long":"India","brk_a3":"IND","brk_name":"India","brk_group":null,"abbrev":"India","postal":"IND","formal_en":"Republic of India","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"India","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":2,"mapcolor13":2,"pop_est":1166079220,"gdp_md_est":3297000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IN","iso_a3":"IND","iso_n3":"356","un_a3":"356","wb_a2":"IN","wb_a3":"IND","woe_id":-99,"adm0_a3_is":"IND","adm0_a3_us":"IND","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1071]],[[1072]],[[1073]],[[1074]],[[1075]],[[1076]],[[1077]],[[1078]],[[1079]],[[1080]],[[1081]],[[1082]],[[1083,-549,1084,-547,1085,1086,-544,1087,-542,-327,-541,1088,-253,1089,1090,1091,1092,-554,1093,-552,1094,-550]]]},{"type":"MultiPolygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Indian Ocean Territories","adm0_a3":"IOA","geou_dif":0,"geounit":"Indian Ocean Territories","gu_a3":"IOA","su_dif":0,"subunit":"Indian Ocean Territories","su_a3":"IOA","brk_diff":0,"name":"Indian Ocean Ter.","name_long":"Indian Ocean Territories","brk_a3":"IOA","brk_name":"Indian Ocean Ter.","brk_group":null,"abbrev":"Ind. Oc. Ter.","postal":"IOT","formal_en":null,"formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Indian Ocean Territories","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":2069,"gdp_md_est":31.035,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"AUS","adm0_a3_us":"AUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"East Asia & Pacific","name_len":17,"long_len":24,"abbrev_len":13,"tiny":-99,"homepart":-99},"arcs":[[[1095]],[[1096]],[[1097]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"British Indian Ocean Territory","adm0_a3":"IOT","geou_dif":0,"geounit":"British Indian Ocean Territory","gu_a3":"IOT","su_dif":0,"subunit":"British Indian Ocean Territory","su_a3":"IOT","brk_diff":1,"name":"Br. Indian Ocean Ter.","name_long":"British Indian Ocean Territory","brk_a3":"B69","brk_name":"Br. Indian Ocean Ter.","brk_group":null,"abbrev":"I.O.T.","postal":"IO","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":"Admin. by U.K.; Claimed by Mauritius and Seychelles","name_sort":"British Indian Ocean Territory","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":4000,"gdp_md_est":160,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"IO","iso_a3":"IOT","iso_n3":"086","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"IOT","adm0_a3_us":"IOT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Sub-Saharan Africa","name_len":21,"long_len":30,"abbrev_len":6,"tiny":5,"homepart":-99},"arcs":[[1098]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ireland","sov_a3":"IRL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ireland","adm0_a3":"IRL","geou_dif":0,"geounit":"Ireland","gu_a3":"IRL","su_dif":0,"subunit":"Ireland","su_a3":"IRL","brk_diff":0,"name":"Ireland","name_long":"Ireland","brk_a3":"IRL","brk_name":"Ireland","brk_group":null,"abbrev":"Ire.","postal":"IRL","formal_en":"Ireland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ireland","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":2,"mapcolor13":2,"pop_est":4203200,"gdp_md_est":188400,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IE","iso_a3":"IRL","iso_n3":"372","un_a3":"372","wb_a2":"IE","wb_a3":"IRL","woe_id":-99,"adm0_a3_is":"IRL","adm0_a3_us":"IRL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1099]],[[1100,-780]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Iran","sov_a3":"IRN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iran","adm0_a3":"IRN","geou_dif":0,"geounit":"Iran","gu_a3":"IRN","su_dif":0,"subunit":"Iran","su_a3":"IRN","brk_diff":0,"name":"Iran","name_long":"Iran","brk_a3":"IRN","brk_name":"Iran","brk_group":null,"abbrev":"Iran","postal":"IRN","formal_en":"Islamic Republic of Iran","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iran, Islamic Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":3,"mapcolor9":4,"mapcolor13":13,"pop_est":66429284,"gdp_md_est":841700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IR","iso_a3":"IRN","iso_n3":"364","un_a3":"364","wb_a2":"IR","wb_a3":"IRN","woe_id":-99,"adm0_a3_is":"IRN","adm0_a3_us":"IRN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1101]],[[-48,-222,1102,1103,-5,1104,1105,1106,1107,1108,-219]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Iraq","sov_a3":"IRQ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iraq","adm0_a3":"IRQ","geou_dif":0,"geounit":"Iraq","gu_a3":"IRQ","su_dif":0,"subunit":"Iraq","su_a3":"IRQ","brk_diff":0,"name":"Iraq","name_long":"Iraq","brk_a3":"IRQ","brk_name":"Iraq","brk_group":null,"abbrev":"Iraq","postal":"IRQ","formal_en":"Republic of Iraq","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iraq","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":3,"mapcolor13":1,"pop_est":31129225,"gdp_md_est":103900,"pop_year":-99,"lastcensus":1997,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"IQ","iso_a3":"IRQ","iso_n3":"368","un_a3":"368","wb_a2":"IQ","wb_a3":"IRQ","woe_id":-99,"adm0_a3_is":"IRQ","adm0_a3_us":"IRQ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1108,1109,1110,1111,1112,1113,1114]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Iceland","sov_a3":"ISL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Iceland","adm0_a3":"ISL","geou_dif":0,"geounit":"Iceland","gu_a3":"ISL","su_dif":0,"subunit":"Iceland","su_a3":"ISL","brk_diff":0,"name":"Iceland","name_long":"Iceland","brk_a3":"ISL","brk_name":"Iceland","brk_group":null,"abbrev":"Iceland","postal":"IS","formal_en":"Republic of Iceland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Iceland","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":4,"mapcolor13":9,"pop_est":306694,"gdp_md_est":12710,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IS","iso_a3":"ISL","iso_n3":"352","un_a3":"352","wb_a2":"IS","wb_a3":"ISL","woe_id":-99,"adm0_a3_is":"ISL","adm0_a3_us":"ISL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[1115]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Israel","sov_a3":"ISR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Israel","adm0_a3":"ISR","geou_dif":0,"geounit":"Israel","gu_a3":"ISR","su_dif":0,"subunit":"Israel","su_a3":"ISR","brk_diff":0,"name":"Israel","name_long":"Israel","brk_a3":"ISR","brk_name":"Israel","brk_group":null,"abbrev":"Isr.","postal":"IS","formal_en":"State of Israel","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Israel","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":9,"pop_est":7233701,"gdp_md_est":201400,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IL","iso_a3":"ISR","iso_n3":"376","un_a3":"376","wb_a2":"IL","wb_a3":"ISR","woe_id":-99,"adm0_a3_is":"ISR","adm0_a3_us":"ISR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1116,1117,1118,1119,-677,1120,1121,1122,1123]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Italy","sov_a3":"ITA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Italy","adm0_a3":"ITA","geou_dif":0,"geounit":"Italy","gu_a3":"ITA","su_dif":0,"subunit":"Italy","su_a3":"ITA","brk_diff":0,"name":"Italy","name_long":"Italy","brk_a3":"ITA","brk_name":"Italy","brk_group":null,"abbrev":"Italy","postal":"I","formal_en":"Italian Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Italy","name_alt":null,"mapcolor7":6,"mapcolor8":7,"mapcolor9":8,"mapcolor13":7,"pop_est":58126212,"gdp_md_est":1823000,"pop_year":-99,"lastcensus":2012,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"IT","iso_a3":"ITA","iso_n3":"380","un_a3":"380","wb_a2":"IT","wb_a3":"ITA","woe_id":-99,"adm0_a3_is":"ITA","adm0_a3_us":"ITA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1124]],[[1125]],[[1126]],[[1127]],[[1128]],[[1129]],[[1130]],[[1131,1132,-761,-485,-213],[1133]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Jamaica","sov_a3":"JAM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Jamaica","adm0_a3":"JAM","geou_dif":0,"geounit":"Jamaica","gu_a3":"JAM","su_dif":0,"subunit":"Jamaica","su_a3":"JAM","brk_diff":0,"name":"Jamaica","name_long":"Jamaica","brk_a3":"JAM","brk_name":"Jamaica","brk_group":null,"abbrev":"Jam.","postal":"J","formal_en":"Jamaica","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Jamaica","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":4,"mapcolor13":10,"pop_est":2825928,"gdp_md_est":20910,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"JM","iso_a3":"JAM","iso_n3":"388","un_a3":"388","wb_a2":"JM","wb_a3":"JAM","woe_id":-99,"adm0_a3_is":"JAM","adm0_a3_us":"JAM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1134]]},{"type":"Polygon","properties":{"scalerank":4,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Country","admin":"Jersey","adm0_a3":"JEY","geou_dif":0,"geounit":"Jersey","gu_a3":"JEY","su_dif":0,"subunit":"Jersey","su_a3":"JEY","brk_diff":0,"name":"Jersey","name_long":"Jersey","brk_a3":"JEY","brk_name":"Jersey","brk_group":"Channel Islands","abbrev":"Jey.","postal":"JE","formal_en":"Bailiwick of Jersey","formal_fr":null,"note_adm0":"U.K. crown dependency","note_brk":null,"name_sort":"Jersey","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":91626,"gdp_md_est":5100,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"JE","iso_a3":"JEY","iso_n3":"832","un_a3":"832","wb_a2":"JG","wb_a3":"CHI","woe_id":-99,"adm0_a3_is":"JEY","adm0_a3_us":"JEY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[1135]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Jordan","sov_a3":"JOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Jordan","adm0_a3":"JOR","geou_dif":0,"geounit":"Jordan","gu_a3":"JOR","su_dif":0,"subunit":"Jordan","su_a3":"JOR","brk_diff":0,"name":"Jordan","name_long":"Jordan","brk_a3":"JOR","brk_name":"Jordan","brk_group":null,"abbrev":"Jord.","postal":"J","formal_en":"Hashemite Kingdom of Jordan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Jordan","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":6342948,"gdp_md_est":31610,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"JO","iso_a3":"JOR","iso_n3":"400","un_a3":"400","wb_a2":"JO","wb_a3":"JOR","woe_id":-99,"adm0_a3_is":"JOR","adm0_a3_us":"JOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1136,1137,-1119,1138,-1117,1139,-1113]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Japan","sov_a3":"JPN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Japan","adm0_a3":"JPN","geou_dif":0,"geounit":"Japan","gu_a3":"JPN","su_dif":0,"subunit":"Japan","su_a3":"JPN","brk_diff":0,"name":"Japan","name_long":"Japan","brk_a3":"JPN","brk_name":"Japan","brk_group":null,"abbrev":"Japan","postal":"J","formal_en":"Japan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Japan","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":5,"mapcolor13":4,"pop_est":127078679,"gdp_md_est":4329000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"JP","iso_a3":"JPN","iso_n3":"392","un_a3":"392","wb_a2":"JP","wb_a3":"JPN","woe_id":-99,"adm0_a3_is":"JPN","adm0_a3_us":"JPN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1140]],[[1141]],[[1142]],[[1143]],[[1144]],[[1145]],[[1146]],[[1147]],[[1148]],[[1149]],[[1150]],[[1151]],[[1152]],[[1153]],[[1154]],[[1155]],[[1156]],[[1157]],[[1158]],[[1159]],[[1160]],[[1161]],[[1162]],[[1163]],[[1164]],[[1165]],[[1166]],[[1167]],[[1168]],[[1169]],[[1170]],[[1171]],[[1172]],[[1173]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Kashmir","sov_a3":"KAS","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Siachen Glacier","adm0_a3":"KAS","geou_dif":0,"geounit":"Siachen Glacier","gu_a3":"KAS","su_dif":0,"subunit":"Siachen Glacier","su_a3":"KAS","brk_diff":1,"name":"Siachen Glacier","name_long":"Siachen Glacier","brk_a3":"B45","brk_name":"Siachen Glacier","brk_group":"Jammu and Kashmir","abbrev":"Siachen","postal":"SG","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Claimed by Pakistan and India","name_sort":"Kashmir","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":6,"mapcolor13":-99,"pop_est":6000,"gdp_md_est":15,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"-99","adm0_a3_us":"KAS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":15,"long_len":15,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-1092,1174,-556]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Kazakhstan","sov_a3":"KAZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kazakhstan","adm0_a3":"KAZ","geou_dif":0,"geounit":"Kazakhstan","gu_a3":"KAZ","su_dif":0,"subunit":"Kazakhstan","su_a3":"KAZ","brk_diff":0,"name":"Kazakhstan","name_long":"Kazakhstan","brk_a3":"KAZ","brk_name":"Kazakhstan","brk_group":null,"abbrev":"Kaz.","postal":"KZ","formal_en":"Republic of Kazakhstan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kazakhstan","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":6,"mapcolor13":1,"pop_est":15399437,"gdp_md_est":175800,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"KZ","iso_a3":"KAZ","iso_n3":"398","un_a3":"398","wb_a2":"KZ","wb_a3":"KAZ","woe_id":-99,"adm0_a3_is":"KAZ","adm0_a3_us":"KAZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1175]],[[1176]],[[1177]],[[-560,1178,1179,1180,1181,1182]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Kenya","sov_a3":"KEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kenya","adm0_a3":"KEN","geou_dif":0,"geounit":"Kenya","gu_a3":"KEN","su_dif":0,"subunit":"Kenya","su_a3":"KEN","brk_diff":0,"name":"Kenya","name_long":"Kenya","brk_a3":"KEN","brk_name":"Kenya","brk_group":null,"abbrev":"Ken.","postal":"KE","formal_en":"Republic of Kenya","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kenya","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":7,"mapcolor13":3,"pop_est":39002772,"gdp_md_est":61510,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KE","iso_a3":"KEN","iso_n3":"404","un_a3":"404","wb_a2":"KE","wb_a3":"KEN","woe_id":-99,"adm0_a3_is":"KEN","adm0_a3_us":"KEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1183]],[[1184,1185,1186,1187,1188,-711]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Kyrgyzstan","sov_a3":"KGZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kyrgyzstan","adm0_a3":"KGZ","geou_dif":0,"geounit":"Kyrgyzstan","gu_a3":"KGZ","su_dif":0,"subunit":"Kyrgyzstan","su_a3":"KGZ","brk_diff":0,"name":"Kyrgyzstan","name_long":"Kyrgyzstan","brk_a3":"KGZ","brk_name":"Kyrgyzstan","brk_group":null,"abbrev":"Kgz.","postal":"KG","formal_en":"Kyrgyz Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kyrgyz Republic","name_alt":null,"mapcolor7":5,"mapcolor8":7,"mapcolor9":7,"mapcolor13":6,"pop_est":5431747,"gdp_md_est":11610,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KG","iso_a3":"KGZ","iso_n3":"417","un_a3":"417","wb_a2":"KG","wb_a3":"KGZ","woe_id":-99,"adm0_a3_is":"KGZ","adm0_a3_us":"KGZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-559,1189,1190,-1179],[1191],[1192],[1193]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Cambodia","sov_a3":"KHM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Cambodia","adm0_a3":"KHM","geou_dif":0,"geounit":"Cambodia","gu_a3":"KHM","su_dif":0,"subunit":"Cambodia","su_a3":"KHM","brk_diff":0,"name":"Cambodia","name_long":"Cambodia","brk_a3":"KHM","brk_name":"Cambodia","brk_group":null,"abbrev":"Camb.","postal":"KH","formal_en":"Kingdom of Cambodia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Cambodia","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":5,"pop_est":14494293,"gdp_md_est":27940,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KH","iso_a3":"KHM","iso_n3":"116","un_a3":"116","wb_a2":"KH","wb_a3":"KHM","woe_id":-99,"adm0_a3_is":"KHM","adm0_a3_us":"KHM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1194]],[[1195]],[[1196,1197,1198,1199]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kiribati","sov_a3":"KIR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kiribati","adm0_a3":"KIR","geou_dif":0,"geounit":"Kiribati","gu_a3":"KIR","su_dif":0,"subunit":"Kiribati","su_a3":"KIR","brk_diff":0,"name":"Kiribati","name_long":"Kiribati","brk_a3":"KIR","brk_name":"Kiribati","brk_group":null,"abbrev":"Kir.","postal":"KI","formal_en":"Republic of Kiribati","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kiribati","name_alt":null,"mapcolor7":5,"mapcolor8":7,"mapcolor9":6,"mapcolor13":12,"pop_est":112850,"gdp_md_est":579.5,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"KI","iso_a3":"KIR","iso_n3":"296","un_a3":"296","wb_a2":"KI","wb_a3":"KIR","woe_id":-99,"adm0_a3_is":"KIR","adm0_a3_us":"KIR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[1200]],[[1201]],[[1202]],[[1203]],[[1204]],[[1205]],[[1206]],[[1207]],[[1208]],[[1209]],[[1210]],[[1211]],[[1212]],[[1213]],[[1214]],[[1215]],[[1216]],[[1217]],[[1218]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Kitts and Nevis","sov_a3":"KNA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Kitts and Nevis","adm0_a3":"KNA","geou_dif":0,"geounit":"Saint Kitts and Nevis","gu_a3":"KNA","su_dif":0,"subunit":"Saint Kitts and Nevis","su_a3":"KNA","brk_diff":0,"name":"St. Kitts and Nevis","name_long":"Saint Kitts and Nevis","brk_a3":"KNA","brk_name":"Saint Kitts and Nevis","brk_group":null,"abbrev":"St.K.N.","postal":"KN","formal_en":"Federation of Saint Kitts and Nevis","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Kitts and Nevis","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":40131,"gdp_md_est":777.7,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KN","iso_a3":"KNA","iso_n3":"659","un_a3":"659","wb_a2":"KN","wb_a3":"KNA","woe_id":-99,"adm0_a3_is":"KNA","adm0_a3_us":"KNA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":19,"long_len":21,"abbrev_len":7,"tiny":4,"homepart":1},"arcs":[[[1219]],[[1220]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"South Korea","sov_a3":"KOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Korea","adm0_a3":"KOR","geou_dif":0,"geounit":"South Korea","gu_a3":"KOR","su_dif":0,"subunit":"South Korea","su_a3":"KOR","brk_diff":0,"name":"Korea","name_long":"Republic of Korea","brk_a3":"KOR","brk_name":"Republic of Korea","brk_group":null,"abbrev":"S.K.","postal":"KR","formal_en":"Republic of Korea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Korea, Rep.","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":1,"mapcolor13":5,"pop_est":48508972,"gdp_md_est":1335000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"KR","iso_a3":"KOR","iso_n3":"410","un_a3":"410","wb_a2":"KR","wb_a3":"KOR","woe_id":-99,"adm0_a3_is":"KOR","adm0_a3_us":"KOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":17,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1221]],[[1222]],[[1223]],[[1224]],[[1225]],[[1226]],[[1227]],[[1228]],[[1229]],[[1230]],[[1231,1232]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kosovo","sov_a3":"KOS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kosovo","adm0_a3":"KOS","geou_dif":0,"geounit":"Kosovo","gu_a3":"KOS","su_dif":0,"subunit":"Kosovo","su_a3":"KOS","brk_diff":1,"name":"Kosovo","name_long":"Kosovo","brk_a3":"B57","brk_name":"Kosovo","brk_group":null,"abbrev":"Kos.","postal":"KO","formal_en":"Republic of Kosovo","formal_fr":null,"note_adm0":null,"note_brk":"Self admin.; Claimed by Serbia","name_sort":"Kosovo","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":11,"pop_est":1804838,"gdp_md_est":5352,"pop_year":-99,"lastcensus":1981,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"KV","wb_a3":"KSV","woe_id":-99,"adm0_a3_is":"SRB","adm0_a3_us":"KOS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1233,-17,1234,1235]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Kuwait","sov_a3":"KWT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Kuwait","adm0_a3":"KWT","geou_dif":0,"geounit":"Kuwait","gu_a3":"KWT","su_dif":0,"subunit":"Kuwait","su_a3":"KWT","brk_diff":0,"name":"Kuwait","name_long":"Kuwait","brk_a3":"KWT","brk_name":"Kuwait","brk_group":null,"abbrev":"Kwt.","postal":"KW","formal_en":"State of Kuwait","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Kuwait","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":2,"mapcolor13":2,"pop_est":2691158,"gdp_md_est":149100,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"KW","iso_a3":"KWT","iso_n3":"414","un_a3":"414","wb_a2":"KW","wb_a3":"KWT","woe_id":-99,"adm0_a3_is":"KWT","adm0_a3_us":"KWT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1236]],[[1237,-1111,1238]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Laos","sov_a3":"LAO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Laos","adm0_a3":"LAO","geou_dif":0,"geounit":"Laos","gu_a3":"LAO","su_dif":0,"subunit":"Laos","su_a3":"LAO","brk_diff":0,"name":"Lao PDR","name_long":"Lao PDR","brk_a3":"LAO","brk_name":"Laos","brk_group":null,"abbrev":"Laos","postal":"LA","formal_en":"Lao People's Democratic Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lao PDR","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":1,"mapcolor13":9,"pop_est":6834942,"gdp_md_est":13980,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LA","iso_a3":"LAO","iso_n3":"418","un_a3":"418","wb_a2":"LA","wb_a3":"LAO","woe_id":-99,"adm0_a3_is":"LAO","adm0_a3_us":"LAO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1239,1240,1241,-1199,1242,1243,-539]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Lebanon","sov_a3":"LBN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lebanon","adm0_a3":"LBN","geou_dif":0,"geounit":"Lebanon","gu_a3":"LBN","su_dif":0,"subunit":"Lebanon","su_a3":"LBN","brk_diff":0,"name":"Lebanon","name_long":"Lebanon","brk_a3":"LBN","brk_name":"Lebanon","brk_group":null,"abbrev":"Leb.","postal":"LB","formal_en":"Lebanese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lebanon","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":12,"pop_est":4017095,"gdp_md_est":44060,"pop_year":-99,"lastcensus":1970,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LB","iso_a3":"LBN","iso_n3":"422","un_a3":"422","wb_a2":"LB","wb_a3":"LBN","woe_id":-99,"adm0_a3_is":"LBN","adm0_a3_us":"LBN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":4,"homepart":1},"arcs":[[-1123,1244,1245]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Liberia","sov_a3":"LBR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Liberia","adm0_a3":"LBR","geou_dif":0,"geounit":"Liberia","gu_a3":"LBR","su_dif":0,"subunit":"Liberia","su_a3":"LBR","brk_diff":0,"name":"Liberia","name_long":"Liberia","brk_a3":"LBR","brk_name":"Liberia","brk_group":null,"abbrev":"Liberia","postal":"LR","formal_en":"Republic of Liberia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Liberia","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":4,"mapcolor13":9,"pop_est":3441790,"gdp_md_est":1526,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"LR","iso_a3":"LBR","iso_n3":"430","un_a3":"430","wb_a2":"LR","wb_a3":"LBR","woe_id":-99,"adm0_a3_is":"LBR","adm0_a3_us":"LBR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-568,1246,1247,-810]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Libya","sov_a3":"LBY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Libya","adm0_a3":"LBY","geou_dif":0,"geounit":"Libya","gu_a3":"LBY","su_dif":0,"subunit":"Libya","su_a3":"LBY","brk_diff":0,"name":"Libya","name_long":"Libya","brk_a3":"LBY","brk_name":"Libya","brk_group":null,"abbrev":"Libya","postal":"LY","formal_en":"Libya","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Libya","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":11,"pop_est":6310434,"gdp_md_est":88830,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LY","iso_a3":"LBY","iso_n3":"434","un_a3":"434","wb_a2":"LY","wb_a3":"LBY","woe_id":-99,"adm0_a3_is":"LBY","adm0_a3_us":"LBY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-680,1248,1249,1250,-659,1251,1252]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Lucia","sov_a3":"LCA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Lucia","adm0_a3":"LCA","geou_dif":0,"geounit":"Saint Lucia","gu_a3":"LCA","su_dif":0,"subunit":"Saint Lucia","su_a3":"LCA","brk_diff":0,"name":"Saint Lucia","name_long":"Saint Lucia","brk_a3":"LCA","brk_name":"Saint Lucia","brk_group":null,"abbrev":"S.L.","postal":"LC","formal_en":"Saint Lucia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Lucia","name_alt":null,"mapcolor7":3,"mapcolor8":4,"mapcolor9":3,"mapcolor13":4,"pop_est":160267,"gdp_md_est":1778,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LC","iso_a3":"LCA","iso_n3":"662","un_a3":"662","wb_a2":"LC","wb_a3":"LCA","woe_id":-99,"adm0_a3_is":"LCA","adm0_a3_us":"LCA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":4,"tiny":4,"homepart":1},"arcs":[[1253]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Liechtenstein","sov_a3":"LIE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Liechtenstein","adm0_a3":"LIE","geou_dif":0,"geounit":"Liechtenstein","gu_a3":"LIE","su_dif":0,"subunit":"Liechtenstein","su_a3":"LIE","brk_diff":0,"name":"Liechtenstein","name_long":"Liechtenstein","brk_a3":"LIE","brk_name":"Liechtenstein","brk_group":null,"abbrev":"Liech.","postal":"FL","formal_en":"Principality of Liechtenstein","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Liechtenstein","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":2,"mapcolor13":9,"pop_est":34761,"gdp_md_est":4160,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"LI","iso_a3":"LIE","iso_n3":"438","un_a3":"438","wb_a2":"LI","wb_a3":"LIE","woe_id":-99,"adm0_a3_is":"LIE","adm0_a3_us":"LIE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":13,"long_len":13,"abbrev_len":6,"tiny":6,"homepart":1},"arcs":[[-484,-215]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sri Lanka","sov_a3":"LKA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sri Lanka","adm0_a3":"LKA","geou_dif":0,"geounit":"Sri Lanka","gu_a3":"LKA","su_dif":0,"subunit":"Sri Lanka","su_a3":"LKA","brk_diff":0,"name":"Sri Lanka","name_long":"Sri Lanka","brk_a3":"LKA","brk_name":"Sri Lanka","brk_group":null,"abbrev":"Sri L.","postal":"LK","formal_en":"Democratic Socialist Republic of Sri Lanka","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sri Lanka","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":4,"mapcolor13":9,"pop_est":21324791,"gdp_md_est":91870,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LK","iso_a3":"LKA","iso_n3":"144","un_a3":"144","wb_a2":"LK","wb_a3":"LKA","woe_id":-99,"adm0_a3_is":"LKA","adm0_a3_us":"LKA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":9,"long_len":9,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1254]],[[1255]],[[1256]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Lesotho","sov_a3":"LSO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lesotho","adm0_a3":"LSO","geou_dif":0,"geounit":"Lesotho","gu_a3":"LSO","su_dif":0,"subunit":"Lesotho","su_a3":"LSO","brk_diff":0,"name":"Lesotho","name_long":"Lesotho","brk_a3":"LSO","brk_name":"Lesotho","brk_group":null,"abbrev":"Les.","postal":"LS","formal_en":"Kingdom of Lesotho","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lesotho","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":2,"mapcolor13":8,"pop_est":2130819,"gdp_md_est":3293,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LS","iso_a3":"LSO","iso_n3":"426","un_a3":"426","wb_a2":"LS","wb_a3":"LSO","woe_id":-99,"adm0_a3_is":"LSO","adm0_a3_us":"LSO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1257]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Lithuania","sov_a3":"LTU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Lithuania","adm0_a3":"LTU","geou_dif":0,"geounit":"Lithuania","gu_a3":"LTU","su_dif":0,"subunit":"Lithuania","su_a3":"LTU","brk_diff":0,"name":"Lithuania","name_long":"Lithuania","brk_a3":"LTU","brk_name":"Lithuania","brk_group":null,"abbrev":"Lith.","postal":"LT","formal_en":"Republic of Lithuania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Lithuania","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":3,"mapcolor13":9,"pop_est":3555179,"gdp_md_est":63330,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LT","iso_a3":"LTU","iso_n3":"440","un_a3":"440","wb_a2":"LT","wb_a3":"LTU","woe_id":-99,"adm0_a3_is":"LTU","adm0_a3_us":"LTU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1258,1259]],[[-285,1260,1261,1262,1263]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Luxembourg","sov_a3":"LUX","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Luxembourg","adm0_a3":"LUX","geou_dif":0,"geounit":"Luxembourg","gu_a3":"LUX","su_dif":0,"subunit":"Luxembourg","su_a3":"LUX","brk_diff":0,"name":"Luxembourg","name_long":"Luxembourg","brk_a3":"LUX","brk_name":"Luxembourg","brk_group":null,"abbrev":"Lux.","postal":"L","formal_en":"Grand Duchy of Luxembourg","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Luxembourg","name_alt":null,"mapcolor7":1,"mapcolor8":7,"mapcolor9":3,"mapcolor13":7,"pop_est":491775,"gdp_md_est":39370,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"LU","iso_a3":"LUX","iso_n3":"442","un_a3":"442","wb_a2":"LU","wb_a3":"LUX","woe_id":-99,"adm0_a3_is":"LUX","adm0_a3_us":"LUX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[-634,-760,-230]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Latvia","sov_a3":"LVA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Latvia","adm0_a3":"LVA","geou_dif":0,"geounit":"Latvia","gu_a3":"LVA","su_dif":0,"subunit":"Latvia","su_a3":"LVA","brk_diff":0,"name":"Latvia","name_long":"Latvia","brk_a3":"LVA","brk_name":"Latvia","brk_group":null,"abbrev":"Lat.","postal":"LV","formal_en":"Republic of Latvia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Latvia","name_alt":null,"mapcolor7":4,"mapcolor8":7,"mapcolor9":6,"mapcolor13":13,"pop_est":2231503,"gdp_md_est":38860,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"LV","iso_a3":"LVA","iso_n3":"428","un_a3":"428","wb_a2":"LV","wb_a3":"LVA","woe_id":-99,"adm0_a3_is":"LVA","adm0_a3_us":"LVA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1264,-286,-1264,1265,-707]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"China","sov_a3":"CH1","adm0_dif":1,"level":2,"type":"Country","admin":"Macao S.A.R","adm0_a3":"MAC","geou_dif":0,"geounit":"Macao S.A.R","gu_a3":"MAC","su_dif":0,"subunit":"Macao S.A.R","su_a3":"MAC","brk_diff":0,"name":"Macao","name_long":"Macao","brk_a3":"MAC","brk_name":"Macao","brk_group":null,"abbrev":"Mac.","postal":"MO","formal_en":"Macao Special Administrative Region, PRC","formal_fr":null,"note_adm0":"China","note_brk":null,"name_sort":"Macao SAR, China","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":3,"pop_est":559846,"gdp_md_est":18140,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MO","iso_a3":"MAC","iso_n3":"446","un_a3":"446","wb_a2":"MO","wb_a3":"MAC","woe_id":-99,"adm0_a3_is":"MAC","adm0_a3_us":"MAC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[-536,1266]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Martin","adm0_a3":"MAF","geou_dif":0,"geounit":"Saint Martin","gu_a3":"MAF","su_dif":0,"subunit":"Saint Martin","su_a3":"MAF","brk_diff":0,"name":"St-Martin","name_long":"Saint-Martin","brk_a3":"MAF","brk_name":"Saint-Martin","brk_group":null,"abbrev":"St. M.","postal":"MF","formal_en":"Saint-Martin (French part)","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St. Martin (French part)","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":36661,"gdp_md_est":449,"pop_year":2008,"lastcensus":-99,"gdp_year":1999,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":0,"fips_10":null,"iso_a2":"MF","iso_a3":"MAF","iso_n3":"663","un_a3":"663","wb_a2":"MF","wb_a3":"MAF","woe_id":-99,"adm0_a3_is":"MAF","adm0_a3_us":"MAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":9,"long_len":12,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[1267,1268]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Morocco","sov_a3":"MAR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Morocco","adm0_a3":"MAR","geou_dif":0,"geounit":"Morocco","gu_a3":"MAR","su_dif":0,"subunit":"Morocco","su_a3":"MAR","brk_diff":0,"name":"Morocco","name_long":"Morocco","brk_a3":"MAR","brk_name":"Morocco","brk_group":null,"abbrev":"Mor.","postal":"MA","formal_en":"Kingdom of Morocco","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Morocco","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":9,"pop_est":34859364,"gdp_md_est":136600,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MA","iso_a3":"MAR","iso_n3":"504","un_a3":"504","wb_a2":"MA","wb_a3":"MAR","woe_id":-99,"adm0_a3_is":"MAR","adm0_a3_us":"MAR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-664,1269,1270]]},{"type":"Polygon","properties":{"scalerank":6,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Monaco","sov_a3":"MCO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Monaco","adm0_a3":"MCO","geou_dif":0,"geounit":"Monaco","gu_a3":"MCO","su_dif":0,"subunit":"Monaco","su_a3":"MCO","brk_diff":0,"name":"Monaco","name_long":"Monaco","brk_a3":"MCO","brk_name":"Monaco","brk_group":null,"abbrev":"Mco.","postal":"MC","formal_en":"Principality of Monaco","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Monaco","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":2,"mapcolor13":12,"pop_est":32965,"gdp_md_est":976.3,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MC","iso_a3":"MCO","iso_n3":"492","un_a3":"492","wb_a2":"MC","wb_a3":"MCO","woe_id":-99,"adm0_a3_is":"MCO","adm0_a3_us":"MCO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[1271,-763]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Moldova","sov_a3":"MDA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Moldova","adm0_a3":"MDA","geou_dif":0,"geounit":"Moldova","gu_a3":"MDA","su_dif":0,"subunit":"Moldova","su_a3":"MDA","brk_diff":0,"name":"Moldova","name_long":"Moldova","brk_a3":"MDA","brk_name":"Moldova","brk_group":null,"abbrev":"Mda.","postal":"MD","formal_en":"Republic of Moldova","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Moldova","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":4,"mapcolor13":12,"pop_est":4320748,"gdp_md_est":10670,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MD","iso_a3":"MDA","iso_n3":"498","un_a3":"498","wb_a2":"MD","wb_a3":"MDA","woe_id":-99,"adm0_a3_is":"MDA","adm0_a3_us":"MDA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1272,1273]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Madagascar","sov_a3":"MDG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Madagascar","adm0_a3":"MDG","geou_dif":0,"geounit":"Madagascar","gu_a3":"MDG","su_dif":0,"subunit":"Madagascar","su_a3":"MDG","brk_diff":0,"name":"Madagascar","name_long":"Madagascar","brk_a3":"MDG","brk_name":"Madagascar","brk_group":null,"abbrev":"Mad.","postal":"MG","formal_en":"Republic of Madagascar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Madagascar","name_alt":null,"mapcolor7":6,"mapcolor8":5,"mapcolor9":2,"mapcolor13":3,"pop_est":20653556,"gdp_md_est":20130,"pop_year":-99,"lastcensus":1993,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MG","iso_a3":"MDG","iso_n3":"450","un_a3":"450","wb_a2":"MG","wb_a3":"MDG","woe_id":-99,"adm0_a3_is":"MDG","adm0_a3_us":"MDG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1274]],[[1275]],[[1276]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Maldives","sov_a3":"MDV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Maldives","adm0_a3":"MDV","geou_dif":0,"geounit":"Maldives","gu_a3":"MDV","su_dif":0,"subunit":"Maldives","su_a3":"MDV","brk_diff":0,"name":"Maldives","name_long":"Maldives","brk_a3":"MDV","brk_name":"Maldives","brk_group":null,"abbrev":"Mald.","postal":"MV","formal_en":"Republic of Maldives","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Maldives","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":1,"mapcolor13":7,"pop_est":396334,"gdp_md_est":1716,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MV","iso_a3":"MDV","iso_n3":"462","un_a3":"462","wb_a2":"MV","wb_a3":"MDV","woe_id":-99,"adm0_a3_is":"MDV","adm0_a3_us":"B13","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1277]],[[1278]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Mexico","sov_a3":"MEX","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mexico","adm0_a3":"MEX","geou_dif":0,"geounit":"Mexico","gu_a3":"MEX","su_dif":0,"subunit":"Mexico","su_a3":"MEX","brk_diff":0,"name":"Mexico","name_long":"Mexico","brk_a3":"MEX","brk_name":"Mexico","brk_group":null,"abbrev":"Mex.","postal":"MX","formal_en":"United Mexican States","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mexico","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":7,"mapcolor13":3,"pop_est":111211789,"gdp_md_est":1563000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MX","iso_a3":"MEX","iso_n3":"484","un_a3":"484","wb_a2":"MX","wb_a3":"MEX","woe_id":-99,"adm0_a3_is":"MEX","adm0_a3_us":"MEX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1279]],[[1280]],[[1281]],[[1282]],[[1283]],[[1284]],[[1285]],[[1286]],[[1287]],[[1288]],[[1289]],[[1290]],[[1291]],[[1292]],[[1293]],[[1294,-290,-891,1295,1296]]]},{"type":"MultiPolygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Marshall Islands","sov_a3":"MHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Marshall Islands","adm0_a3":"MHL","geou_dif":0,"geounit":"Marshall Islands","gu_a3":"MHL","su_dif":0,"subunit":"Marshall Islands","su_a3":"MHL","brk_diff":0,"name":"Marshall Is.","name_long":"Marshall Islands","brk_a3":"MHL","brk_name":"Marshall Is.","brk_group":null,"abbrev":"M. Is.","postal":"MH","formal_en":"Republic of the Marshall Islands","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Marshall Islands","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":5,"mapcolor13":3,"pop_est":64522,"gdp_md_est":133.5,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MH","iso_a3":"MHL","iso_n3":"584","un_a3":"584","wb_a2":"MH","wb_a3":"MHL","woe_id":-99,"adm0_a3_is":"MHL","adm0_a3_us":"MHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":12,"long_len":16,"abbrev_len":6,"tiny":2,"homepart":1},"arcs":[[[1297]],[[1298]],[[1299]],[[1300]],[[1301]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Macedonia","sov_a3":"MKD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Macedonia","adm0_a3":"MKD","geou_dif":0,"geounit":"Macedonia","gu_a3":"MKD","su_dif":0,"subunit":"Macedonia","su_a3":"MKD","brk_diff":0,"name":"Macedonia","name_long":"Macedonia","brk_a3":"MKD","brk_name":"Macedonia","brk_group":null,"abbrev":"Mkd.","postal":"MK","formal_en":"Former Yugoslav Republic of Macedonia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Macedonia, FYR","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":2066718,"gdp_md_est":18780,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MK","iso_a3":"MKD","iso_n3":"807","un_a3":"807","wb_a2":"MK","wb_a3":"MKD","woe_id":-99,"adm0_a3_is":"MKD","adm0_a3_us":"MKD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-257,-867,-18,-1234,1302]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mali","sov_a3":"MLI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mali","adm0_a3":"MLI","geou_dif":0,"geounit":"Mali","gu_a3":"MLI","su_dif":0,"subunit":"Mali","su_a3":"MLI","brk_diff":0,"name":"Mali","name_long":"Mali","brk_a3":"MLI","brk_name":"Mali","brk_group":null,"abbrev":"Mali","postal":"ML","formal_en":"Republic of Mali","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mali","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":7,"pop_est":12666987,"gdp_md_est":14590,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ML","iso_a3":"MLI","iso_n3":"466","un_a3":"466","wb_a2":"ML","wb_a3":"MLI","woe_id":-99,"adm0_a3_is":"MLI","adm0_a3_us":"MLI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1303,-244,-570,-809,1304,1305,-661]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Malta","sov_a3":"MLT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malta","adm0_a3":"MLT","geou_dif":0,"geounit":"Malta","gu_a3":"MLT","su_dif":0,"subunit":"Malta","su_a3":"MLT","brk_diff":0,"name":"Malta","name_long":"Malta","brk_a3":"MLT","brk_name":"Malta","brk_group":null,"abbrev":"Malta","postal":"M","formal_en":"Republic of Malta","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malta","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":8,"pop_est":405165,"gdp_md_est":9962,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MT","iso_a3":"MLT","iso_n3":"470","un_a3":"470","wb_a2":"MT","wb_a3":"MLT","woe_id":-99,"adm0_a3_is":"MLT","adm0_a3_us":"MLT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[[1306]],[[1307]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Myanmar","sov_a3":"MMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Myanmar","adm0_a3":"MMR","geou_dif":0,"geounit":"Myanmar","gu_a3":"MMR","su_dif":0,"subunit":"Myanmar","su_a3":"MMR","brk_diff":0,"name":"Myanmar","name_long":"Myanmar","brk_a3":"MMR","brk_name":"Myanmar","brk_group":null,"abbrev":"Myan.","postal":"MM","formal_en":"Republic of the Union of Myanmar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Myanmar","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":5,"mapcolor13":13,"pop_est":48137741,"gdp_md_est":55130,"pop_year":-99,"lastcensus":1983,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MM","iso_a3":"MMR","iso_n3":"104","un_a3":"104","wb_a2":"MM","wb_a3":"MMR","woe_id":-99,"adm0_a3_is":"MMR","adm0_a3_us":"MMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1308]],[[1309]],[[1310]],[[1311]],[[1312]],[[1313]],[[1314]],[[1315]],[[1316]],[[1317]],[[1318]],[[1319]],[[1320]],[[1321]],[[1322]],[[1323]],[[1324]],[[1325]],[[-1244,1326,1327,-251,-1089,-540]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Montenegro","sov_a3":"MNE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Montenegro","adm0_a3":"MNE","geou_dif":0,"geounit":"Montenegro","gu_a3":"MNE","su_dif":0,"subunit":"Montenegro","su_a3":"MNE","brk_diff":0,"name":"Montenegro","name_long":"Montenegro","brk_a3":"MNE","brk_name":"Montenegro","brk_group":null,"abbrev":"Mont.","postal":"ME","formal_en":"Montenegro","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Montenegro","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":4,"mapcolor13":5,"pop_est":672180,"gdp_md_est":6816,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ME","iso_a3":"MNE","iso_n3":"499","un_a3":"499","wb_a2":"ME","wb_a3":"MNE","woe_id":-99,"adm0_a3_is":"MNE","adm0_a3_us":"MNE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1328,-1235,-21,1329,-908,-277]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mongolia","sov_a3":"MNG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mongolia","adm0_a3":"MNG","geou_dif":0,"geounit":"Mongolia","gu_a3":"MNG","su_dif":0,"subunit":"Mongolia","su_a3":"MNG","brk_diff":0,"name":"Mongolia","name_long":"Mongolia","brk_a3":"MNG","brk_name":"Mongolia","brk_group":null,"abbrev":"Mong.","postal":"MN","formal_en":"Mongolia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mongolia","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":5,"mapcolor13":6,"pop_est":3041142,"gdp_md_est":9476,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MN","iso_a3":"MNG","iso_n3":"496","un_a3":"496","wb_a2":"MN","wb_a3":"MNG","woe_id":-99,"adm0_a3_is":"MNG","adm0_a3_us":"MNG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-562,1330]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Northern Mariana Islands","adm0_a3":"MNP","geou_dif":0,"geounit":"Northern Mariana Islands","gu_a3":"MNP","su_dif":0,"subunit":"Northern Mariana Islands","su_a3":"MNP","brk_diff":0,"name":"N. Mariana Is.","name_long":"Northern Mariana Islands","brk_a3":"MNP","brk_name":"N. Mariana Is.","brk_group":null,"abbrev":"N.M.I.","postal":"MP","formal_en":"Commonwealth of the Northern Mariana Islands","formal_fr":null,"note_adm0":"Commonwealth of U.S.A.","note_brk":null,"name_sort":"Northern Mariana Islands","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":88662,"gdp_md_est":900,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"MP","iso_a3":"MNP","iso_n3":"580","un_a3":"580","wb_a2":"MP","wb_a3":"MNP","woe_id":-99,"adm0_a3_is":"MNP","adm0_a3_us":"MNP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":14,"long_len":24,"abbrev_len":6,"tiny":3,"homepart":-99},"arcs":[[[1331]],[[1332]],[[1333]],[[1334]],[[1335]],[[1336]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mozambique","sov_a3":"MOZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mozambique","adm0_a3":"MOZ","geou_dif":0,"geounit":"Mozambique","gu_a3":"MOZ","su_dif":0,"subunit":"Mozambique","su_a3":"MOZ","brk_diff":0,"name":"Mozambique","name_long":"Mozambique","brk_a3":"MOZ","brk_name":"Mozambique","brk_group":null,"abbrev":"Moz.","postal":"MZ","formal_en":"Republic of Mozambique","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mozambique","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":1,"mapcolor13":4,"pop_est":21669278,"gdp_md_est":18940,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MZ","iso_a3":"MOZ","iso_n3":"508","un_a3":"508","wb_a2":"MZ","wb_a3":"MOZ","woe_id":-99,"adm0_a3_is":"MOZ","adm0_a3_us":"MOZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1337,1338,1339,1340,1341,1342,1343,1344],[1345],[1346]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Mauritania","sov_a3":"MRT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mauritania","adm0_a3":"MRT","geou_dif":0,"geounit":"Mauritania","gu_a3":"MRT","su_dif":0,"subunit":"Mauritania","su_a3":"MRT","brk_diff":0,"name":"Mauritania","name_long":"Mauritania","brk_a3":"MRT","brk_name":"Mauritania","brk_group":null,"abbrev":"Mrt.","postal":"MR","formal_en":"Islamic Republic of Mauritania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mauritania","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":2,"mapcolor13":1,"pop_est":3129486,"gdp_md_est":6308,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MR","iso_a3":"MRT","iso_n3":"478","un_a3":"478","wb_a2":"MR","wb_a3":"MRT","woe_id":-99,"adm0_a3_is":"MRT","adm0_a3_us":"MRT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1347]],[[1348,1349,1350,-662,-1306]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Montserrat","adm0_a3":"MSR","geou_dif":0,"geounit":"Montserrat","gu_a3":"MSR","su_dif":0,"subunit":"Montserrat","su_a3":"MSR","brk_diff":0,"name":"Montserrat","name_long":"Montserrat","brk_a3":"MSR","brk_name":"Montserrat","brk_group":null,"abbrev":"Monts.","postal":"MS","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Montserrat","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":5097,"gdp_md_est":29,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MS","iso_a3":"MSR","iso_n3":"500","un_a3":"500","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"MSR","adm0_a3_us":"MSR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":10,"long_len":10,"abbrev_len":6,"tiny":6,"homepart":-99},"arcs":[[1351]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Mauritius","sov_a3":"MUS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Mauritius","adm0_a3":"MUS","geou_dif":0,"geounit":"Mauritius","gu_a3":"MUS","su_dif":0,"subunit":"Mauritius","su_a3":"MUS","brk_diff":0,"name":"Mauritius","name_long":"Mauritius","brk_a3":"MUS","brk_name":"Mauritius","brk_group":null,"abbrev":"Mus.","postal":"MU","formal_en":"Republic of Mauritius","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Mauritius","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":5,"mapcolor13":7,"pop_est":1284264,"gdp_md_est":15270,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MU","iso_a3":"MUS","iso_n3":"480","un_a3":"480","wb_a2":"MU","wb_a3":"MUS","woe_id":-99,"adm0_a3_is":"MUS","adm0_a3_us":"MUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[1352]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Malawi","sov_a3":"MWI","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malawi","adm0_a3":"MWI","geou_dif":0,"geounit":"Malawi","gu_a3":"MWI","su_dif":0,"subunit":"Malawi","su_a3":"MWI","brk_diff":0,"name":"Malawi","name_long":"Malawi","brk_a3":"MWI","brk_name":"Malawi","brk_group":null,"abbrev":"Mal.","postal":"MW","formal_en":"Republic of Malawi","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malawi","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":4,"mapcolor13":5,"pop_est":14268711,"gdp_md_est":11810,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"MW","iso_a3":"MWI","iso_n3":"454","un_a3":"454","wb_a2":"MW","wb_a3":"MWI","woe_id":-99,"adm0_a3_is":"MWI","adm0_a3_us":"MWI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[-1347]],[[-1346]],[[-1343,1353,1354]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Malaysia","sov_a3":"MYS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Malaysia","adm0_a3":"MYS","geou_dif":0,"geounit":"Malaysia","gu_a3":"MYS","su_dif":0,"subunit":"Malaysia","su_a3":"MYS","brk_diff":0,"name":"Malaysia","name_long":"Malaysia","brk_a3":"MYS","brk_name":"Malaysia","brk_group":null,"abbrev":"Malay.","postal":"MY","formal_en":"Malaysia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Malaysia","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":3,"mapcolor13":6,"pop_est":25715819,"gdp_md_est":384300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"MY","iso_a3":"MYS","iso_n3":"458","un_a3":"458","wb_a2":"MY","wb_a3":"MYS","woe_id":-99,"adm0_a3_is":"MYS","adm0_a3_us":"MYS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1355]],[[1356]],[[1357]],[[-1064,1358]],[[1359]],[[1360]],[[1361,1362]],[[-1067,1363,-325,-324,1364]],[[1365]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Namibia","sov_a3":"NAM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Namibia","adm0_a3":"NAM","geou_dif":0,"geounit":"Namibia","gu_a3":"NAM","su_dif":0,"subunit":"Namibia","su_a3":"NAM","brk_diff":0,"name":"Namibia","name_long":"Namibia","brk_a3":"NAM","brk_name":"Namibia","brk_group":null,"abbrev":"Nam.","postal":"NA","formal_en":"Republic of Namibia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Namibia","name_alt":null,"mapcolor7":4,"mapcolor8":1,"mapcolor9":1,"mapcolor13":7,"pop_est":2108665,"gdp_md_est":13250,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NA","iso_a3":"NAM","iso_n3":"516","un_a3":"516","wb_a2":"NA","wb_a3":"NAM","woe_id":-99,"adm0_a3_is":"NAM","adm0_a3_us":"NAM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1366,-331,1367,1368,-10]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"New Caledonia","adm0_a3":"NCL","geou_dif":0,"geounit":"New Caledonia","gu_a3":"NCL","su_dif":0,"subunit":"New Caledonia","su_a3":"NCL","brk_diff":0,"name":"New Caledonia","name_long":"New Caledonia","brk_a3":"NCL","brk_name":"New Caledonia","brk_group":null,"abbrev":"New C.","postal":"NC","formal_en":"New Caledonia","formal_fr":"Nouvelle-Calédonie","note_adm0":"Fr.","note_brk":null,"name_sort":"New Caledonia","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":227436,"gdp_md_est":3158,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"NC","iso_a3":"NCL","iso_n3":"540","un_a3":"540","wb_a2":"NC","wb_a3":"NCL","woe_id":-99,"adm0_a3_is":"NCL","adm0_a3_us":"NCL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":13,"long_len":13,"abbrev_len":6,"tiny":-99,"homepart":-99},"arcs":[[[1369]],[[1370]],[[1371]],[[1372]],[[1373]],[[1374]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Niger","sov_a3":"NER","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Niger","adm0_a3":"NER","geou_dif":0,"geounit":"Niger","gu_a3":"NER","su_dif":0,"subunit":"Niger","su_a3":"NER","brk_diff":0,"name":"Niger","name_long":"Niger","brk_a3":"NER","brk_name":"Niger","brk_group":null,"abbrev":"Niger","postal":"NE","formal_en":"Republic of Niger","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Niger","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":3,"mapcolor13":13,"pop_est":15306252,"gdp_md_est":10040,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"NE","iso_a3":"NER","iso_n3":"562","un_a3":"562","wb_a2":"NE","wb_a3":"NER","woe_id":-99,"adm0_a3_is":"NER","adm0_a3_us":"NER","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1375,1376,-239,-240,-1304,-660,-1251]]},{"type":"Polygon","properties":{"scalerank":5,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Australia","sov_a3":"AU1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Norfolk Island","adm0_a3":"NFK","geou_dif":0,"geounit":"Norfolk Island","gu_a3":"NFK","su_dif":0,"subunit":"Norfolk Island","su_a3":"NFK","brk_diff":0,"name":"Norfolk Island","name_long":"Norfolk Island","brk_a3":"NFK","brk_name":"Norfolk Island","brk_group":null,"abbrev":"Nfk. I.","postal":"NF","formal_en":"Territory of Norfolk Island","formal_fr":null,"note_adm0":"Auz.","note_brk":null,"name_sort":"Norfolk Island","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":7,"pop_est":2141,"gdp_md_est":32.115,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NF","iso_a3":"NFK","iso_n3":"574","un_a3":"574","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NFK","adm0_a3_us":"NFK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":14,"long_len":14,"abbrev_len":7,"tiny":-99,"homepart":-99},"arcs":[[1377]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Nigeria","sov_a3":"NGA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nigeria","adm0_a3":"NGA","geou_dif":0,"geounit":"Nigeria","gu_a3":"NGA","su_dif":0,"subunit":"Nigeria","su_a3":"NGA","brk_diff":0,"name":"Nigeria","name_long":"Nigeria","brk_a3":"NGA","brk_name":"Nigeria","brk_group":null,"abbrev":"Nigeria","postal":"NG","formal_en":"Federal Republic of Nigeria","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nigeria","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":2,"pop_est":149229090,"gdp_md_est":335400,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NG","iso_a3":"NGA","iso_n3":"566","un_a3":"566","wb_a2":"NG","wb_a3":"NGA","woe_id":-99,"adm0_a3_is":"NGA","adm0_a3_us":"NGA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[[1378]],[[1379,-575,1380,-235,-1377]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Nicaragua","sov_a3":"NIC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nicaragua","adm0_a3":"NIC","geou_dif":0,"geounit":"Nicaragua","gu_a3":"NIC","su_dif":0,"subunit":"Nicaragua","su_a3":"NIC","brk_diff":0,"name":"Nicaragua","name_long":"Nicaragua","brk_a3":"NIC","brk_name":"Nicaragua","brk_group":null,"abbrev":"Nic.","postal":"NI","formal_en":"Republic of Nicaragua","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nicaragua","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":9,"pop_est":5891199,"gdp_md_est":16790,"pop_year":-99,"lastcensus":2005,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NI","iso_a3":"NIC","iso_n3":"558","un_a3":"558","wb_a2":"NI","wb_a3":"NIC","woe_id":-99,"adm0_a3_is":"NIC","adm0_a3_us":"NIC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1381,-608,1382,-900]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Niue","adm0_a3":"NIU","geou_dif":0,"geounit":"Niue","gu_a3":"NIU","su_dif":0,"subunit":"Niue","su_a3":"NIU","brk_diff":0,"name":"Niue","name_long":"Niue","brk_a3":"NIU","brk_name":"Niue","brk_group":null,"abbrev":"Niue","postal":"NU","formal_en":null,"formal_fr":null,"note_adm0":"Assoc. with N.Z.","note_brk":null,"name_sort":"Niue","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":1398,"gdp_md_est":10.01,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NU","iso_a3":"NIU","iso_n3":"570","un_a3":"570","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NIU","adm0_a3_us":"NIU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":4,"long_len":4,"abbrev_len":4,"tiny":3,"homepart":-99},"arcs":[[1383]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Netherlands","adm0_a3":"NLD","geou_dif":0,"geounit":"Netherlands","gu_a3":"NLD","su_dif":0,"subunit":"Netherlands","su_a3":"NLD","brk_diff":0,"name":"Netherlands","name_long":"Netherlands","brk_a3":"NLD","brk_name":"Netherlands","brk_group":null,"abbrev":"Neth.","postal":"NL","formal_en":"Kingdom of the Netherlands","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Netherlands","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":16715999,"gdp_md_est":672000,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NL","iso_a3":"NLD","iso_n3":"528","un_a3":"528","wb_a2":"NL","wb_a3":"NLD","woe_id":-99,"adm0_a3_is":"NLD","adm0_a3_us":"NLD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Western Europe","region_wb":"Europe & Central Asia","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1384]],[[1385]],[[-233,1386]],[[1387]],[[1388]],[[1389]],[[1390,-635,1391,-234]],[[1392]],[[1393]],[[1394]],[[1395]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Norway","sov_a3":"NOR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Norway","adm0_a3":"NOR","geou_dif":0,"geounit":"Norway","gu_a3":"NOR","su_dif":0,"subunit":"Norway","su_a3":"NOR","brk_diff":0,"name":"Norway","name_long":"Norway","brk_a3":"NOR","brk_name":"Norway","brk_group":null,"abbrev":"Nor.","postal":"N","formal_en":"Kingdom of Norway","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Norway","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":8,"mapcolor13":12,"pop_est":4676305,"gdp_md_est":276400,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NO","iso_a3":"NOR","iso_n3":"578","un_a3":"578","wb_a2":"NO","wb_a3":"NOR","woe_id":-99,"adm0_a3_is":"NOR","adm0_a3_us":"NOR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1396]],[[1397]],[[1398]],[[1399]],[[1400]],[[1401]],[[1402]],[[1403]],[[1404]],[[1405]],[[1406]],[[1407]],[[1408]],[[1409]],[[1410]],[[1411]],[[1412]],[[1413]],[[1414]],[[1415]],[[1416,-724,1417,1418]],[[1419]],[[1420]],[[1421]],[[1422]],[[1423]],[[1424]],[[1425]],[[1426]],[[1427]],[[1428]],[[1429]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Nepal","sov_a3":"NPL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nepal","adm0_a3":"NPL","geou_dif":0,"geounit":"Nepal","gu_a3":"NPL","su_dif":0,"subunit":"Nepal","su_a3":"NPL","brk_diff":0,"name":"Nepal","name_long":"Nepal","brk_a3":"NPL","brk_name":"Nepal","brk_group":null,"abbrev":"Nepal","postal":"NP","formal_en":"Nepal","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nepal","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":12,"pop_est":28563377,"gdp_md_est":31080,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"NP","iso_a3":"NPL","iso_n3":"524","un_a3":"524","wb_a2":"NP","wb_a3":"NPL","woe_id":-99,"adm0_a3_is":"NPL","adm0_a3_us":"NPL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1088,-543]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Nauru","sov_a3":"NRU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Nauru","adm0_a3":"NRU","geou_dif":0,"geounit":"Nauru","gu_a3":"NRU","su_dif":0,"subunit":"Nauru","su_a3":"NRU","brk_diff":0,"name":"Nauru","name_long":"Nauru","brk_a3":"NRU","brk_name":"Nauru","brk_group":null,"abbrev":"Nauru","postal":"NR","formal_en":"Republic of Nauru","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Nauru","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":6,"mapcolor13":9,"pop_est":14019,"gdp_md_est":60,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"NR","iso_a3":"NRU","iso_n3":"520","un_a3":"520","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"NRU","adm0_a3_us":"NRU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[1430]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"New Zealand","sov_a3":"NZ1","adm0_dif":1,"level":2,"type":"Country","admin":"New Zealand","adm0_a3":"NZL","geou_dif":0,"geounit":"New Zealand","gu_a3":"NZL","su_dif":0,"subunit":"New Zealand","su_a3":"NZL","brk_diff":0,"name":"New Zealand","name_long":"New Zealand","brk_a3":"NZL","brk_name":"New Zealand","brk_group":null,"abbrev":"N.Z.","postal":"NZ","formal_en":"New Zealand","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"New Zealand","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":4,"pop_est":4213418,"gdp_md_est":116700,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"NZ","iso_a3":"NZL","iso_n3":"554","un_a3":"554","wb_a2":"NZ","wb_a3":"NZL","woe_id":-99,"adm0_a3_is":"NZL","adm0_a3_us":"NZL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Australia and New Zealand","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1431]],[[1432]],[[1433]],[[1434]],[[1435]],[[1436]],[[1437]],[[1438]],[[1439]],[[1440]],[[1441]],[[1442]],[[1443]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Oman","sov_a3":"OMN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Oman","adm0_a3":"OMN","geou_dif":0,"geounit":"Oman","gu_a3":"OMN","su_dif":0,"subunit":"Oman","su_a3":"OMN","brk_diff":0,"name":"Oman","name_long":"Oman","brk_a3":"OMN","brk_name":"Oman","brk_group":null,"abbrev":"Oman","postal":"OM","formal_en":"Sultanate of Oman","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Oman","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":3418085,"gdp_md_est":66980,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"OM","iso_a3":"OMN","iso_n3":"512","un_a3":"512","wb_a2":"OM","wb_a3":"OMN","woe_id":-99,"adm0_a3_is":"OMN","adm0_a3_us":"OMN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1444]],[[1445,1446,1447,-32]],[[-36]],[[-35,1448]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Pakistan","sov_a3":"PAK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Pakistan","adm0_a3":"PAK","geou_dif":0,"geounit":"Pakistan","gu_a3":"PAK","su_dif":0,"subunit":"Pakistan","su_a3":"PAK","brk_diff":0,"name":"Pakistan","name_long":"Pakistan","brk_a3":"PAK","brk_name":"Pakistan","brk_group":null,"abbrev":"Pak.","postal":"PK","formal_en":"Islamic Republic of Pakistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Pakistan","name_alt":null,"mapcolor7":2,"mapcolor8":2,"mapcolor9":3,"mapcolor13":11,"pop_est":176242949,"gdp_md_est":427300,"pop_year":-99,"lastcensus":1998,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PK","iso_a3":"PAK","iso_n3":"586","un_a3":"586","wb_a2":"PK","wb_a3":"PAK","woe_id":-99,"adm0_a3_is":"PAK","adm0_a3_us":"PAK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Southern Asia","region_wb":"South Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1175,-1091,1449,-1106,-3,-557]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Panama","sov_a3":"PAN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Panama","adm0_a3":"PAN","geou_dif":0,"geounit":"Panama","gu_a3":"PAN","su_dif":0,"subunit":"Panama","su_a3":"PAN","brk_diff":0,"name":"Panama","name_long":"Panama","brk_a3":"PAN","brk_name":"Panama","brk_group":null,"abbrev":"Pan.","postal":"PA","formal_en":"Republic of Panama","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Panama","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":6,"mapcolor13":3,"pop_est":3360474,"gdp_md_est":38830,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PA","iso_a3":"PAN","iso_n3":"591","un_a3":"591","wb_a2":"PA","wb_a3":"PAN","woe_id":-99,"adm0_a3_is":"PAN","adm0_a3_us":"PAN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1450]],[[1451]],[[1452]],[[1453]],[[-592,1454,-606,1455]]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Pitcairn Islands","adm0_a3":"PCN","geou_dif":0,"geounit":"Pitcairn Islands","gu_a3":"PCN","su_dif":0,"subunit":"Pitcairn Islands","su_a3":"PCN","brk_diff":0,"name":"Pitcairn Is.","name_long":"Pitcairn Islands","brk_a3":"PCN","brk_name":"Pitcairn Is.","brk_group":null,"abbrev":"Pit. Is.","postal":"PN","formal_en":"Pitcairn, Henderson, Ducie and Oeno Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Pitcairn Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":48,"gdp_md_est":0.72,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"PN","iso_a3":"PCN","iso_n3":"612","un_a3":"612","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"PCN","adm0_a3_us":"PCN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":12,"long_len":16,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[1456]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Peru","sov_a3":"PER","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Peru","adm0_a3":"PER","geou_dif":0,"geounit":"Peru","gu_a3":"PER","su_dif":0,"subunit":"Peru","su_a3":"PER","brk_diff":0,"name":"Peru","name_long":"Peru","brk_a3":"PER","brk_name":"Peru","brk_group":null,"abbrev":"Peru","postal":"PE","formal_en":"Republic of Peru","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Peru","name_alt":null,"mapcolor7":4,"mapcolor8":4,"mapcolor9":4,"mapcolor13":11,"pop_est":29546963,"gdp_md_est":247300,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PE","iso_a3":"PER","iso_n3":"604","un_a3":"604","wb_a2":"PE","wb_a3":"PER","woe_id":-99,"adm0_a3_is":"PER","adm0_a3_us":"PER","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-318,-295,-519,1457,-674,-589]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Philippines","sov_a3":"PHL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Philippines","adm0_a3":"PHL","geou_dif":0,"geounit":"Philippines","gu_a3":"PHL","su_dif":0,"subunit":"Philippines","su_a3":"PHL","brk_diff":0,"name":"Philippines","name_long":"Philippines","brk_a3":"PHL","brk_name":"Philippines","brk_group":null,"abbrev":"Phil.","postal":"PH","formal_en":"Republic of the Philippines","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Philippines","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":2,"mapcolor13":8,"pop_est":97976603,"gdp_md_est":317500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PH","iso_a3":"PHL","iso_n3":"608","un_a3":"608","wb_a2":"PH","wb_a3":"PHL","woe_id":-99,"adm0_a3_is":"PHL","adm0_a3_us":"PHL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1458]],[[1459]],[[1460]],[[1461]],[[1462]],[[1463]],[[1464]],[[1465]],[[1466]],[[1467]],[[1468]],[[1469]],[[1470]],[[1471]],[[1472]],[[1473]],[[1474]],[[1475]],[[1476]],[[1477]],[[1478]],[[1479]],[[1480]],[[1481]],[[1482]],[[1483]],[[1484]],[[1485]],[[1486]],[[1487]],[[1488]],[[1489]],[[1490]],[[1491]],[[1492]],[[1493]],[[1494]],[[1495]],[[1496]],[[1497]],[[1498]],[[1499]],[[1500]],[[1501]],[[1502]],[[1503]],[[1504]],[[1505]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Palau","sov_a3":"PLW","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Palau","adm0_a3":"PLW","geou_dif":0,"geounit":"Palau","gu_a3":"PLW","su_dif":0,"subunit":"Palau","su_a3":"PLW","brk_diff":0,"name":"Palau","name_long":"Palau","brk_a3":"PLW","brk_name":"Palau","brk_group":null,"abbrev":"Palau","postal":"PW","formal_en":"Republic of Palau","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Palau","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":1,"mapcolor13":12,"pop_est":20796,"gdp_md_est":164,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PW","iso_a3":"PLW","iso_n3":"585","un_a3":"585","wb_a2":"PW","wb_a3":"PLW","woe_id":-99,"adm0_a3_is":"PLW","adm0_a3_us":"PLW","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Micronesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1506]],[[1507]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Papua New Guinea","sov_a3":"PNG","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Papua New Guinea","adm0_a3":"PNG","geou_dif":0,"geounit":"Papua New Guinea","gu_a3":"PNG","su_dif":1,"subunit":"Papua New Guinea","su_a3":"PN1","brk_diff":0,"name":"Papua New Guinea","name_long":"Papua New Guinea","brk_a3":"PN1","brk_name":"Papua New Guinea","brk_group":null,"abbrev":"P.N.G.","postal":"PG","formal_en":"Independent State of Papua New Guinea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Papua New Guinea","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":3,"mapcolor13":1,"pop_est":6057263,"gdp_md_est":13210,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PG","iso_a3":"PNG","iso_n3":"598","un_a3":"598","wb_a2":"PG","wb_a3":"PNG","woe_id":-99,"adm0_a3_is":"PNG","adm0_a3_us":"PNG","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":16,"long_len":16,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1508]],[[1509]],[[1510]],[[1511]],[[1512]],[[1513]],[[1514]],[[1515]],[[1516]],[[1517]],[[1518]],[[1519]],[[1520]],[[1521]],[[1522]],[[1523]],[[1524]],[[1525]],[[1526]],[[1527]],[[-1023,1528,1529]],[[1530]],[[1531]],[[1532]],[[1533]],[[1534]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Poland","sov_a3":"POL","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Poland","adm0_a3":"POL","geou_dif":0,"geounit":"Poland","gu_a3":"POL","su_dif":0,"subunit":"Poland","su_a3":"POL","brk_diff":0,"name":"Poland","name_long":"Poland","brk_a3":"POL","brk_name":"Poland","brk_group":null,"abbrev":"Pol.","postal":"PL","formal_en":"Republic of Poland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Poland","name_alt":null,"mapcolor7":3,"mapcolor8":7,"mapcolor9":1,"mapcolor13":2,"pop_est":38482919,"gdp_md_est":667900,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"PL","iso_a3":"POL","iso_n3":"616","un_a3":"616","wb_a2":"PL","wb_a3":"POL","woe_id":-99,"adm0_a3_is":"POL","adm0_a3_us":"POL","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1535,-1261,-284,1536,1537,-623,-632,1538,-627,1539]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Puerto Rico","adm0_a3":"PRI","geou_dif":0,"geounit":"Puerto Rico","gu_a3":"PRI","su_dif":0,"subunit":"Puerto Rico","su_a3":"PRI","brk_diff":0,"name":"Puerto Rico","name_long":"Puerto Rico","brk_a3":"PRI","brk_name":"Puerto Rico","brk_group":null,"abbrev":"P.R.","postal":"PR","formal_en":"Commonwealth of Puerto Rico","formal_fr":null,"note_adm0":"Commonwealth of U.S.A.","note_brk":null,"name_sort":"Puerto Rico","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":3971020,"gdp_md_est":70230,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"PR","iso_a3":"PRI","iso_n3":"630","un_a3":"630","wb_a2":"PR","wb_a3":"PRI","woe_id":-99,"adm0_a3_is":"PRI","adm0_a3_us":"PRI","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[1540]],[[1541]],[[1542]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"North Korea","sov_a3":"PRK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"North Korea","adm0_a3":"PRK","geou_dif":0,"geounit":"North Korea","gu_a3":"PRK","su_dif":0,"subunit":"North Korea","su_a3":"PRK","brk_diff":0,"name":"Dem. Rep. Korea","name_long":"Dem. Rep. Korea","brk_a3":"PRK","brk_name":"Dem. Rep. Korea","brk_group":null,"abbrev":"N.K.","postal":"KP","formal_en":"Democratic People's Republic of Korea","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Korea, Dem. Rep.","name_alt":null,"mapcolor7":3,"mapcolor8":5,"mapcolor9":3,"mapcolor13":9,"pop_est":22665345,"gdp_md_est":40000,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"KP","iso_a3":"PRK","iso_n3":"408","un_a3":"408","wb_a2":"KP","wb_a3":"PRK","woe_id":-99,"adm0_a3_is":"PRK","adm0_a3_us":"PRK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":15,"long_len":15,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1543]],[[1544,1545,-1233,1546,-532]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Portugal","sov_a3":"PRT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Portugal","adm0_a3":"PRT","geou_dif":0,"geounit":"Portugal","gu_a3":"PRT","su_dif":1,"subunit":"Portugal","su_a3":"PR1","brk_diff":0,"name":"Portugal","name_long":"Portugal","brk_a3":"PR1","brk_name":"Portugal","brk_group":null,"abbrev":"Port.","postal":"P","formal_en":"Portuguese Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Portugal","name_alt":null,"mapcolor7":1,"mapcolor8":7,"mapcolor9":1,"mapcolor13":4,"pop_est":10707924,"gdp_md_est":208627,"pop_year":-99,"lastcensus":2011,"gdp_year":0,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"PT","iso_a3":"PRT","iso_n3":"620","un_a3":"620","wb_a2":"PT","wb_a3":"PRT","woe_id":-99,"adm0_a3_is":"PRT","adm0_a3_us":"PRT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1547]],[[1548]],[[1549]],[[1550]],[[1551]],[[1552]],[[1553]],[[1554]],[[1555,-701]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Paraguay","sov_a3":"PRY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Paraguay","adm0_a3":"PRY","geou_dif":0,"geounit":"Paraguay","gu_a3":"PRY","su_dif":0,"subunit":"Paraguay","su_a3":"PRY","brk_diff":0,"name":"Paraguay","name_long":"Paraguay","brk_a3":"PRY","brk_name":"Paraguay","brk_group":null,"abbrev":"Para.","postal":"PY","formal_en":"Republic of Paraguay","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Paraguay","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":2,"pop_est":6995655,"gdp_md_est":28890,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PY","iso_a3":"PRY","iso_n3":"600","un_a3":"600","wb_a2":"PY","wb_a3":"PRY","woe_id":-99,"adm0_a3_is":"PRY","adm0_a3_us":"PRY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-317,-41,-293]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Israel","sov_a3":"ISR","adm0_dif":1,"level":2,"type":"Disputed","admin":"Palestine","adm0_a3":"PSX","geou_dif":0,"geounit":"Palestine","gu_a3":"PSX","su_dif":0,"subunit":"Palestine","su_a3":"PSX","brk_diff":0,"name":"Palestine","name_long":"Palestine","brk_a3":"PSX","brk_name":"Palestine","brk_group":null,"abbrev":"Pal.","postal":"PAL","formal_en":"West Bank and Gaza","formal_fr":null,"note_adm0":"Partial self-admin.","note_brk":"Partial self-admin.","name_sort":"Palestine (West Bank and Gaza)","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":5,"mapcolor13":8,"pop_est":4119083,"gdp_md_est":11950.77,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PS","iso_a3":"PSE","iso_n3":"275","un_a3":"275","wb_a2":"GZ","wb_a3":"WBG","woe_id":-99,"adm0_a3_is":"PSE","adm0_a3_us":"PSX","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":-99},"arcs":[[[-676,1556,-1121]],[[-1118,-1139]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"French Polynesia","adm0_a3":"PYF","geou_dif":0,"geounit":"French Polynesia","gu_a3":"PYF","su_dif":0,"subunit":"French Polynesia","su_a3":"PYF","brk_diff":0,"name":"Fr. Polynesia","name_long":"French Polynesia","brk_a3":"PYF","brk_name":"Fr. Polynesia","brk_group":null,"abbrev":"Fr. Poly.","postal":"PF","formal_en":"French Polynesia","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"French Polynesia","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":287032,"gdp_md_est":4718,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"PF","iso_a3":"PYF","iso_n3":"258","un_a3":"258","wb_a2":"PF","wb_a3":"PYF","woe_id":-99,"adm0_a3_is":"PYF","adm0_a3_us":"PYF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":13,"long_len":16,"abbrev_len":9,"tiny":2,"homepart":-99},"arcs":[[[1557]],[[1558]],[[1559]],[[1560]],[[1561]],[[1562]],[[1563]],[[1564]],[[1565]],[[1566]],[[1567]],[[1568]],[[1569]],[[1570]],[[1571]],[[1572]],[[1573]],[[1574]],[[1575]],[[1576]],[[1577]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Qatar","sov_a3":"QAT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Qatar","adm0_a3":"QAT","geou_dif":0,"geounit":"Qatar","gu_a3":"QAT","su_dif":0,"subunit":"Qatar","su_a3":"QAT","brk_diff":0,"name":"Qatar","name_long":"Qatar","brk_a3":"QAT","brk_name":"Qatar","brk_group":null,"abbrev":"Qatar","postal":"QA","formal_en":"State of Qatar","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Qatar","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":4,"pop_est":833285,"gdp_md_est":91330,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"QA","iso_a3":"QAT","iso_n3":"634","un_a3":"634","wb_a2":"QA","wb_a3":"QAT","woe_id":-99,"adm0_a3_is":"QAT","adm0_a3_us":"QAT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1578,1579]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Romania","sov_a3":"ROU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Romania","adm0_a3":"ROU","geou_dif":0,"geounit":"Romania","gu_a3":"ROU","su_dif":0,"subunit":"Romania","su_a3":"ROU","brk_diff":0,"name":"Romania","name_long":"Romania","brk_a3":"ROU","brk_name":"Romania","brk_group":null,"abbrev":"Rom.","postal":"RO","formal_en":"Romania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Romania","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":3,"mapcolor13":13,"pop_est":22215421,"gdp_md_est":271400,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RO","iso_a3":"ROU","iso_n3":"642","un_a3":"642","wb_a2":"RO","wb_a3":"ROM","woe_id":-99,"adm0_a3_is":"ROU","adm0_a3_us":"ROU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1580,1581,-259,1582,-927,1583,-1273]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Russia","sov_a3":"RUS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Russia","adm0_a3":"RUS","geou_dif":0,"geounit":"Russia","gu_a3":"RUS","su_dif":0,"subunit":"Russia","su_a3":"RUS","brk_diff":0,"name":"Russia","name_long":"Russian Federation","brk_a3":"RUS","brk_name":"Russia","brk_group":null,"abbrev":"Rus.","postal":"RUS","formal_en":"Russian Federation","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Russian Federation","name_alt":null,"mapcolor7":2,"mapcolor8":5,"mapcolor9":7,"mapcolor13":7,"pop_est":140041247,"gdp_md_est":2266000,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"3. Emerging region: BRIC","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RU","iso_a3":"RUS","iso_n3":"643","un_a3":"643","wb_a2":"RU","wb_a3":"RUS","woe_id":-99,"adm0_a3_is":"RUS","adm0_a3_us":"RUS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":18,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1584]],[[1585]],[[1586]],[[1587]],[[1588]],[[1589]],[[1590]],[[1591]],[[1592]],[[1593]],[[1594]],[[1595]],[[1596]],[[1597]],[[1598]],[[1599]],[[1600]],[[1601]],[[1602]],[[-1262,-1536,1603,-1259,1604]],[[1605]],[[1606]],[[1607]],[[1608]],[[1609]],[[1610]],[[1611]],[[1612]],[[1613]],[[1614]],[[1615]],[[1616]],[[1617]],[[1618]],[[1619]],[[1620]],[[1621]],[[1622]],[[1623]],[[1624]],[[1625]],[[1626]],[[1627]],[[1628]],[[1629]],[[1630]],[[1631]],[[1632]],[[1633]],[[1634]],[[1635]],[[1636]],[[1637]],[[1638]],[[1639]],[[1640]],[[1641]],[[1642]],[[1643]],[[1644]],[[1645]],[[1646]],[[1647]],[[1648]],[[1649]],[[1650]],[[1651]],[[-1545,-563,-1331,-561,-1183,1652,-224,-804,1653,1654,-282,-1265,-706,1655,-721,-1417,1656]],[[1657]],[[1658]],[[1659]],[[1660]],[[1661]],[[1662]],[[1663]],[[1664]],[[1665]],[[1666]],[[1667]],[[1668]],[[1669]],[[1670]],[[1671]],[[1672]],[[1673]],[[1674]],[[1675]],[[1676]],[[1677]],[[1678]],[[1679]],[[1680]],[[1681]],[[1682]],[[1683]],[[1684]],[[1685]],[[1686]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Rwanda","sov_a3":"RWA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Rwanda","adm0_a3":"RWA","geou_dif":0,"geounit":"Rwanda","gu_a3":"RWA","su_dif":0,"subunit":"Rwanda","su_a3":"RWA","brk_diff":0,"name":"Rwanda","name_long":"Rwanda","brk_a3":"RWA","brk_name":"Rwanda","brk_group":null,"abbrev":"Rwa.","postal":"RW","formal_en":"Republic of Rwanda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Rwanda","name_alt":null,"mapcolor7":5,"mapcolor8":2,"mapcolor9":3,"mapcolor13":10,"pop_est":10473282,"gdp_md_est":9706,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"RW","iso_a3":"RWA","iso_n3":"646","un_a3":"646","wb_a2":"RW","wb_a3":"RWA","woe_id":-99,"adm0_a3_is":"RWA","adm0_a3_us":"RWA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1687,-227,-579,1688]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":7,"sovereignt":"Western Sahara","sov_a3":"SAH","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Western Sahara","adm0_a3":"SAH","geou_dif":0,"geounit":"Western Sahara","gu_a3":"SAH","su_dif":0,"subunit":"Western Sahara","su_a3":"SAH","brk_diff":1,"name":"W. Sahara","name_long":"Western Sahara","brk_a3":"B28","brk_name":"W. Sahara","brk_group":null,"abbrev":"W. Sah.","postal":"WS","formal_en":"Sahrawi Arab Democratic Republic","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Morocco","name_sort":"Western Sahara","name_alt":null,"mapcolor7":4,"mapcolor8":7,"mapcolor9":4,"mapcolor13":4,"pop_est":-99,"gdp_md_est":-99,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"EH","iso_a3":"ESH","iso_n3":"732","un_a3":"732","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"MAR","adm0_a3_us":"SAH","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":9,"long_len":14,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-1351,1689,-1270,-663]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Saudi Arabia","sov_a3":"SAU","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saudi Arabia","adm0_a3":"SAU","geou_dif":0,"geounit":"Saudi Arabia","gu_a3":"SAU","su_dif":0,"subunit":"Saudi Arabia","su_a3":"SAU","brk_diff":0,"name":"Saudi Arabia","name_long":"Saudi Arabia","brk_a3":"SAU","brk_name":"Saudi Arabia","brk_group":null,"abbrev":"Saud.","postal":"SA","formal_en":"Kingdom of Saudi Arabia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Saudi Arabia","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":6,"mapcolor13":7,"pop_est":28686633,"gdp_md_est":576500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SA","iso_a3":"SAU","iso_n3":"682","un_a3":"682","wb_a2":"SA","wb_a3":"SAU","woe_id":-99,"adm0_a3_is":"SAU","adm0_a3_us":"SAU","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1690]],[[1691]],[[1692]],[[-1238,1693,-1579,1694,-33,-1448,1695,1696,-1137,-1112]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sudan","sov_a3":"SDN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sudan","adm0_a3":"SDN","geou_dif":0,"geounit":"Sudan","gu_a3":"SDN","su_dif":0,"subunit":"Sudan","su_a3":"SDN","brk_diff":0,"name":"Sudan","name_long":"Sudan","brk_a3":"SDN","brk_name":"Sudan","brk_group":null,"abbrev":"Sudan","postal":"SD","formal_en":"Republic of the Sudan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sudan","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":4,"mapcolor13":1,"pop_est":25946220,"gdp_md_est":88080,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SD","iso_a3":"SDN","iso_n3":"729","un_a3":"729","wb_a2":"SD","wb_a3":"SDN","woe_id":-99,"adm0_a3_is":"SDN","adm0_a3_us":"SDN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Sub-Saharan Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[1697,-686,-713,1698,-332,1699,-1249,-679]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"South Sudan","sov_a3":"SDS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Sudan","adm0_a3":"SDS","geou_dif":0,"geounit":"South Sudan","gu_a3":"SDS","su_dif":0,"subunit":"South Sudan","su_a3":"SDS","brk_diff":0,"name":"S. Sudan","name_long":"South Sudan","brk_a3":"SDS","brk_name":"S. Sudan","brk_group":null,"abbrev":"S. Sud.","postal":"SS","formal_en":"Republic of South Sudan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"South Sudan","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":3,"mapcolor13":5,"pop_est":10625176,"gdp_md_est":13227,"pop_year":-99,"lastcensus":2008,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SS","iso_a3":"SSD","iso_n3":"728","un_a3":"728","wb_a2":"SS","wb_a3":"SSD","woe_id":-99,"adm0_a3_is":"SSD","adm0_a3_us":"SDS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":11,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[-712,-1189,1700,-577,-333,-1699]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Senegal","sov_a3":"SEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Senegal","adm0_a3":"SEN","geou_dif":0,"geounit":"Senegal","gu_a3":"SEN","su_dif":0,"subunit":"Senegal","su_a3":"SEN","brk_diff":0,"name":"Senegal","name_long":"Senegal","brk_a3":"SEN","brk_name":"Senegal","brk_group":null,"abbrev":"Sen.","postal":"SN","formal_en":"Republic of Senegal","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Senegal","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":5,"mapcolor13":5,"pop_est":13711597,"gdp_md_est":21980,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SN","iso_a3":"SEN","iso_n3":"686","un_a3":"686","wb_a2":"SN","wb_a3":"SEN","woe_id":-99,"adm0_a3_is":"SEN","adm0_a3_us":"SEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1305,-814,-824,1701,-816,1702,-1349]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Singapore","sov_a3":"SGP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Singapore","adm0_a3":"SGP","geou_dif":0,"geounit":"Singapore","gu_a3":"SGP","su_dif":0,"subunit":"Singapore","su_a3":"SGP","brk_diff":0,"name":"Singapore","name_long":"Singapore","brk_a3":"SGP","brk_name":"Singapore","brk_group":null,"abbrev":"Sing.","postal":"SG","formal_en":"Republic of Singapore","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Singapore","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":4657542,"gdp_md_est":237300,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SG","iso_a3":"SGP","iso_n3":"702","un_a3":"702","wb_a2":"SG","wb_a3":"SGP","woe_id":-99,"adm0_a3_is":"SGP","adm0_a3_us":"SGP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":9,"long_len":9,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[1703]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"South Georgia and South Sandwich Islands","adm0_a3":"SGS","geou_dif":0,"geounit":"South Georgia and South Sandwich Islands","gu_a3":"SGS","su_dif":0,"subunit":"South Georgia and South Sandwich Islands","su_a3":"SGS","brk_diff":0,"name":"S. Geo. and S. Sandw. Is.","name_long":"South Georgia and South Sandwich Islands","brk_a3":"SGS","brk_name":"S. Geo. and S. Sandw. Is.","brk_group":null,"abbrev":"S.G. S.S. Is.","postal":"GS","formal_en":"South Georgia and South Sandwich Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"South Georgia and the Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":30,"gdp_md_est":0.3,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"GS","iso_a3":"SGS","iso_n3":"239","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SGS","adm0_a3_us":"SGS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Seven seas (open ocean)","subregion":"Seven seas (open ocean)","region_wb":"Antarctica","name_len":25,"long_len":40,"abbrev_len":13,"tiny":3,"homepart":-99},"arcs":[[[1704]],[[1705]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Helena","adm0_a3":"SHN","geou_dif":0,"geounit":"Saint Helena","gu_a3":"SHN","su_dif":0,"subunit":"Saint Helena","su_a3":"SHN","brk_diff":0,"name":"Saint Helena","name_long":"Saint Helena","brk_a3":"SHN","brk_name":"Saint Helena","brk_group":null,"abbrev":"St.H.","postal":"SH","formal_en":null,"formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"St. Helena","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":7637,"gdp_md_est":18,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SH","iso_a3":"SHN","iso_n3":"654","un_a3":"654","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SHN","adm0_a3_us":"SHN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":-99},"arcs":[[[1706]],[[1707]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Solomon Islands","sov_a3":"SLB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Solomon Islands","adm0_a3":"SLB","geou_dif":0,"geounit":"Solomon Islands","gu_a3":"SLB","su_dif":0,"subunit":"Solomon Islands","su_a3":"SLB","brk_diff":0,"name":"Solomon Is.","name_long":"Solomon Islands","brk_a3":"SLB","brk_name":"Solomon Is.","brk_group":null,"abbrev":"S. Is.","postal":"SB","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Solomon Islands","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":6,"pop_est":595613,"gdp_md_est":1078,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SB","iso_a3":"SLB","iso_n3":"090","un_a3":"090","wb_a2":"SB","wb_a3":"SLB","woe_id":-99,"adm0_a3_is":"SLB","adm0_a3_us":"SLB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":11,"long_len":15,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1708]],[[1709]],[[1710]],[[1711]],[[1712]],[[1713]],[[1714]],[[1715]],[[1716]],[[1717]],[[1718]],[[1719]],[[1720]],[[1721]],[[1722]],[[1723]],[[1724]],[[1725]],[[1726]],[[1727]],[[1728]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Sierra Leone","sov_a3":"SLE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sierra Leone","adm0_a3":"SLE","geou_dif":0,"geounit":"Sierra Leone","gu_a3":"SLE","su_dif":0,"subunit":"Sierra Leone","su_a3":"SLE","brk_diff":0,"name":"Sierra Leone","name_long":"Sierra Leone","brk_a3":"SLE","brk_name":"Sierra Leone","brk_group":null,"abbrev":"S.L.","postal":"SL","formal_en":"Republic of Sierra Leone","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sierra Leone","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":1,"mapcolor13":7,"pop_est":6440053,"gdp_md_est":4285,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SL","iso_a3":"SLE","iso_n3":"694","un_a3":"694","wb_a2":"SL","wb_a3":"SLE","woe_id":-99,"adm0_a3_is":"SLE","adm0_a3_us":"SLE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1729]],[[-1248,1730,-811]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"El Salvador","sov_a3":"SLV","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"El Salvador","adm0_a3":"SLV","geou_dif":0,"geounit":"El Salvador","gu_a3":"SLV","su_dif":0,"subunit":"El Salvador","su_a3":"SLV","brk_diff":0,"name":"El Salvador","name_long":"El Salvador","brk_a3":"SLV","brk_name":"El Salvador","brk_group":null,"abbrev":"El. S.","postal":"SV","formal_en":"Republic of El Salvador","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"El Salvador","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":6,"mapcolor13":8,"pop_est":7185218,"gdp_md_est":43630,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SV","iso_a3":"SLV","iso_n3":"222","un_a3":"222","wb_a2":"SV","wb_a3":"SLV","woe_id":-99,"adm0_a3_is":"SLV","adm0_a3_us":"SLV","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Central America","region_wb":"Latin America & Caribbean","name_len":11,"long_len":11,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-902,1731,-889]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"San Marino","sov_a3":"SMR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"San Marino","adm0_a3":"SMR","geou_dif":0,"geounit":"San Marino","gu_a3":"SMR","su_dif":0,"subunit":"San Marino","su_a3":"SMR","brk_diff":0,"name":"San Marino","name_long":"San Marino","brk_a3":"SMR","brk_name":"San Marino","brk_group":null,"abbrev":"S.M.","postal":"RSM","formal_en":"Republic of San Marino","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"San Marino","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":1,"mapcolor13":6,"pop_est":30324,"gdp_md_est":1662,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SM","iso_a3":"SMR","iso_n3":"674","un_a3":"674","wb_a2":"SM","wb_a3":"SMR","woe_id":-99,"adm0_a3_is":"SMR","adm0_a3_us":"SMR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[-1134]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Somaliland","sov_a3":"SOL","adm0_dif":0,"level":2,"type":"Indeterminate","admin":"Somaliland","adm0_a3":"SOL","geou_dif":0,"geounit":"Somaliland","gu_a3":"SOL","su_dif":0,"subunit":"Somaliland","su_a3":"SOL","brk_diff":1,"name":"Somaliland","name_long":"Somaliland","brk_a3":"B30","brk_name":"Somaliland","brk_group":null,"abbrev":"Solnd.","postal":"SL","formal_en":"Republic of Somaliland","formal_fr":null,"note_adm0":"Self admin.","note_brk":"Self admin.; Claimed by Somalia","name_sort":"Somaliland","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":5,"mapcolor13":2,"pop_est":3500000,"gdp_md_est":12250,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"-99","iso_a3":"-99","iso_n3":"-99","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SOM","adm0_a3_us":"SOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[1732,-709,-639,1733]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Somalia","sov_a3":"SOM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Somalia","adm0_a3":"SOM","geou_dif":0,"geounit":"Somalia","gu_a3":"SOM","su_dif":0,"subunit":"Somalia","su_a3":"SOM","brk_diff":0,"name":"Somalia","name_long":"Somalia","brk_a3":"SOM","brk_name":"Somalia","brk_group":null,"abbrev":"Som.","postal":"SO","formal_en":"Federal Republic of Somalia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Somalia","name_alt":null,"mapcolor7":2,"mapcolor8":8,"mapcolor9":6,"mapcolor13":7,"pop_est":9832017,"gdp_md_est":5524,"pop_year":-99,"lastcensus":1987,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"SO","iso_a3":"SOM","iso_n3":"706","un_a3":"706","wb_a2":"SO","wb_a3":"SOM","woe_id":-99,"adm0_a3_is":"SOM","adm0_a3_us":"SOM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1185,-710,-1733,1734]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Saint Pierre and Miquelon","adm0_a3":"SPM","geou_dif":0,"geounit":"Saint Pierre and Miquelon","gu_a3":"SPM","su_dif":0,"subunit":"Saint Pierre and Miquelon","su_a3":"SPM","brk_diff":0,"name":"St. Pierre and Miquelon","name_long":"Saint Pierre and Miquelon","brk_a3":"SPM","brk_name":"St. Pierre and Miquelon","brk_group":null,"abbrev":"St. P.M.","postal":"PM","formal_en":"Saint Pierre and Miquelon","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"St. Pierre and Miquelon","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":7051,"gdp_md_est":48.3,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"PM","iso_a3":"SPM","iso_n3":"666","un_a3":"666","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"SPM","adm0_a3_us":"SPM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":23,"long_len":25,"abbrev_len":8,"tiny":3,"homepart":-99},"arcs":[[[1735]],[[1736]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Republic of Serbia","sov_a3":"SRB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Republic of Serbia","adm0_a3":"SRB","geou_dif":0,"geounit":"Republic of Serbia","gu_a3":"SRB","su_dif":0,"subunit":"Republic of Serbia","su_a3":"SRB","brk_diff":0,"name":"Serbia","name_long":"Serbia","brk_a3":"SRB","brk_name":"Serbia","brk_group":null,"abbrev":"Serb.","postal":"RS","formal_en":"Republic of Serbia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Serbia","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":2,"mapcolor13":10,"pop_est":7379339,"gdp_md_est":80340,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"RS","iso_a3":"SRB","iso_n3":"688","un_a3":"688","wb_a2":"YF","wb_a3":"SRB","woe_id":-99,"adm0_a3_is":"SRB","adm0_a3_us":"SRB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1583,-258,-1303,-1236,-1329,-276,-919,-928]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Sao Tome and Principe","sov_a3":"STP","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sao Tome and Principe","adm0_a3":"STP","geou_dif":0,"geounit":"Sao Tome and Principe","gu_a3":"STP","su_dif":0,"subunit":"Sao Tome and Principe","su_a3":"STP","brk_diff":0,"name":"São Tomé and Principe","name_long":"São Tomé and Principe","brk_a3":"STP","brk_name":"Sao Tome and Principe","brk_group":null,"abbrev":"S.T.P.","postal":"ST","formal_en":"Democratic Republic of São Tomé and Principe","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"São Tomé and Principe","name_alt":null,"mapcolor7":1,"mapcolor8":6,"mapcolor9":1,"mapcolor13":7,"pop_est":212679,"gdp_md_est":276.5,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ST","iso_a3":"STP","iso_n3":"678","un_a3":"678","wb_a2":"ST","wb_a3":"STP","woe_id":-99,"adm0_a3_is":"STP","adm0_a3_us":"STP","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":21,"long_len":21,"abbrev_len":6,"tiny":3,"homepart":1},"arcs":[[[1737]],[[1738]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Suriname","sov_a3":"SUR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Suriname","adm0_a3":"SUR","geou_dif":0,"geounit":"Suriname","gu_a3":"SUR","su_dif":0,"subunit":"Suriname","su_a3":"SUR","brk_diff":0,"name":"Suriname","name_long":"Suriname","brk_a3":"SUR","brk_name":"Suriname","brk_group":null,"abbrev":"Sur.","postal":"SR","formal_en":"Republic of Suriname","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Suriname","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":7,"mapcolor13":6,"pop_est":481267,"gdp_md_est":4254,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SR","iso_a3":"SUR","iso_n3":"740","un_a3":"740","wb_a2":"SR","wb_a3":"SUR","woe_id":-99,"adm0_a3_is":"SUR","adm0_a3_us":"SUR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-752,-313,-893,1739]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Slovakia","sov_a3":"SVK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Slovakia","adm0_a3":"SVK","geou_dif":0,"geounit":"Slovakia","gu_a3":"SVK","su_dif":0,"subunit":"Slovakia","su_a3":"SVK","brk_diff":0,"name":"Slovakia","name_long":"Slovakia","brk_a3":"SVK","brk_name":"Slovakia","brk_group":null,"abbrev":"Svk.","postal":"SK","formal_en":"Slovak Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Slovak Republic","name_alt":null,"mapcolor7":2,"mapcolor8":4,"mapcolor9":4,"mapcolor13":9,"pop_est":5463046,"gdp_md_est":119500,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SK","iso_a3":"SVK","iso_n3":"703","un_a3":"703","wb_a2":"SK","wb_a3":"SVK","woe_id":-99,"adm0_a3_is":"SVK","adm0_a3_us":"SVK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1740,-930,-210,-624,-1538]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Slovenia","sov_a3":"SVN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Slovenia","adm0_a3":"SVN","geou_dif":0,"geounit":"Slovenia","gu_a3":"SVN","su_dif":0,"subunit":"Slovenia","su_a3":"SVN","brk_diff":0,"name":"Slovenia","name_long":"Slovenia","brk_a3":"SVN","brk_name":"Slovenia","brk_group":null,"abbrev":"Slo.","postal":"SLO","formal_en":"Republic of Slovenia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Slovenia","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":2,"mapcolor13":12,"pop_est":2005692,"gdp_md_est":59340,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SI","iso_a3":"SVN","iso_n3":"705","un_a3":"705","wb_a2":"SI","wb_a3":"SVN","woe_id":-99,"adm0_a3_is":"SVN","adm0_a3_us":"SVN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Southern Europe","region_wb":"Europe & Central Asia","name_len":8,"long_len":8,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-921,1741,-1132,-212,-929]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Sweden","sov_a3":"SWE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Sweden","adm0_a3":"SWE","geou_dif":0,"geounit":"Sweden","gu_a3":"SWE","su_dif":0,"subunit":"Sweden","su_a3":"SWE","brk_diff":0,"name":"Sweden","name_long":"Sweden","brk_a3":"SWE","brk_name":"Sweden","brk_group":null,"abbrev":"Swe.","postal":"S","formal_en":"Kingdom of Sweden","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Sweden","name_alt":null,"mapcolor7":1,"mapcolor8":4,"mapcolor9":2,"mapcolor13":4,"pop_est":9059651,"gdp_md_est":344300,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"SE","iso_a3":"SWE","iso_n3":"752","un_a3":"752","wb_a2":"SE","wb_a3":"SWE","woe_id":-99,"adm0_a3_is":"SWE","adm0_a3_us":"SWE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Northern Europe","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1742]],[[1743]],[[1744]],[[1745]],[[1746]],[[1747,-1418,-723]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Swaziland","sov_a3":"SWZ","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Swaziland","adm0_a3":"SWZ","geou_dif":0,"geounit":"Swaziland","gu_a3":"SWZ","su_dif":0,"subunit":"Swaziland","su_a3":"SWZ","brk_diff":0,"name":"Swaziland","name_long":"Swaziland","brk_a3":"SWZ","brk_name":"Swaziland","brk_group":null,"abbrev":"Swz.","postal":"SW","formal_en":"Kingdom of Swaziland","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Swaziland","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":1123913,"gdp_md_est":5702,"pop_year":-99,"lastcensus":2007,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SZ","iso_a3":"SWZ","iso_n3":"748","un_a3":"748","wb_a2":"SZ","wb_a3":"SWZ","woe_id":-99,"adm0_a3_is":"SWZ","adm0_a3_us":"SWZ","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1339,1748]]},{"type":"Polygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Netherlands","sov_a3":"NL1","adm0_dif":1,"level":2,"type":"Country","admin":"Sint Maarten","adm0_a3":"SXM","geou_dif":0,"geounit":"Sint Maarten","gu_a3":"SXM","su_dif":0,"subunit":"Sint Maarten","su_a3":"SXM","brk_diff":0,"name":"Sint Maarten","name_long":"Sint Maarten","brk_a3":"SXM","brk_name":"Sint Maarten","brk_group":null,"abbrev":"St. M.","postal":"SX","formal_en":"Sint Maarten (Dutch part)","formal_fr":null,"note_adm0":"Neth.","note_brk":null,"name_sort":"St. Maarten (Dutch part)","name_alt":null,"mapcolor7":4,"mapcolor8":2,"mapcolor9":2,"mapcolor13":9,"pop_est":37429,"gdp_md_est":400,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"SX","iso_a3":"SXM","iso_n3":"534","un_a3":"534","wb_a2":"SX","wb_a3":"SXM","woe_id":-99,"adm0_a3_is":"SXM","adm0_a3_us":"SXM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":12,"long_len":12,"abbrev_len":6,"tiny":4,"homepart":-99},"arcs":[[-1268,1749]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Seychelles","sov_a3":"SYC","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Seychelles","adm0_a3":"SYC","geou_dif":0,"geounit":"Seychelles","gu_a3":"SYC","su_dif":0,"subunit":"Seychelles","su_a3":"SYC","brk_diff":0,"name":"Seychelles","name_long":"Seychelles","brk_a3":"SYC","brk_name":"Seychelles","brk_group":null,"abbrev":"Syc.","postal":"SC","formal_en":"Republic of Seychelles","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Seychelles","name_alt":null,"mapcolor7":5,"mapcolor8":8,"mapcolor9":3,"mapcolor13":1,"pop_est":87476,"gdp_md_est":1715,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SC","iso_a3":"SYC","iso_n3":"690","un_a3":"690","wb_a2":"SC","wb_a3":"SYC","woe_id":-99,"adm0_a3_is":"SYC","adm0_a3_us":"SYC","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Seven seas (open ocean)","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":10,"long_len":10,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[1750]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Syria","sov_a3":"SYR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Syria","adm0_a3":"SYR","geou_dif":0,"geounit":"Syria","gu_a3":"SYR","su_dif":0,"subunit":"Syria","su_a3":"SYR","brk_diff":0,"name":"Syria","name_long":"Syria","brk_a3":"SYR","brk_name":"Syria","brk_group":null,"abbrev":"Syria","postal":"SYR","formal_en":"Syrian Arab Republic","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Syrian Arab Republic","name_alt":null,"mapcolor7":2,"mapcolor8":6,"mapcolor9":2,"mapcolor13":6,"pop_est":20178485,"gdp_md_est":98830,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"SY","iso_a3":"SYR","iso_n3":"760","un_a3":"760","wb_a2":"SY","wb_a3":"SYR","woe_id":-99,"adm0_a3_is":"SYR","adm0_a3_us":"SYR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1114,-1140,-1124,-1246,1751,1752]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Turks and Caicos Islands","adm0_a3":"TCA","geou_dif":0,"geounit":"Turks and Caicos Islands","gu_a3":"TCA","su_dif":0,"subunit":"Turks and Caicos Islands","su_a3":"TCA","brk_diff":0,"name":"Turks and Caicos Is.","name_long":"Turks and Caicos Islands","brk_a3":"TCA","brk_name":"Turks and Caicos Is.","brk_group":null,"abbrev":"T.C. Is.","postal":"TC","formal_en":"Turks and Caicos Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"Turks and Caicos Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":22942,"gdp_md_est":216,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TC","iso_a3":"TCA","iso_n3":"796","un_a3":"796","wb_a2":"TC","wb_a3":"TCA","woe_id":-99,"adm0_a3_is":"TCA","adm0_a3_us":"TCA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":20,"long_len":24,"abbrev_len":8,"tiny":-99,"homepart":-99},"arcs":[[[1753]],[[1754]],[[1755]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Chad","sov_a3":"TCD","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Chad","adm0_a3":"TCD","geou_dif":0,"geounit":"Chad","gu_a3":"TCD","su_dif":0,"subunit":"Chad","su_a3":"TCD","brk_diff":0,"name":"Chad","name_long":"Chad","brk_a3":"TCD","brk_name":"Chad","brk_group":null,"abbrev":"Chad","postal":"TD","formal_en":"Republic of Chad","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Chad","name_alt":null,"mapcolor7":6,"mapcolor8":1,"mapcolor9":8,"mapcolor13":6,"pop_est":10329208,"gdp_md_est":15860,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TD","iso_a3":"TCD","iso_n3":"148","un_a3":"148","wb_a2":"TD","wb_a3":"TCD","woe_id":-99,"adm0_a3_is":"TCD","adm0_a3_us":"TCD","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Middle Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1700,-337,-576,-1380,-1376,-1250]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Togo","sov_a3":"TGO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Togo","adm0_a3":"TGO","geou_dif":0,"geounit":"Togo","gu_a3":"TGO","su_dif":0,"subunit":"Togo","su_a3":"TGO","brk_diff":0,"name":"Togo","name_long":"Togo","brk_a3":"TGO","brk_name":"Togo","brk_group":null,"abbrev":"Togo","postal":"TG","formal_en":"Togolese Republic","formal_fr":"République Togolaise","note_adm0":null,"note_brk":null,"name_sort":"Togo","name_alt":null,"mapcolor7":3,"mapcolor8":1,"mapcolor9":3,"mapcolor13":5,"pop_est":6019877,"gdp_md_est":5118,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TG","iso_a3":"TGO","iso_n3":"768","un_a3":"768","wb_a2":"TG","wb_a3":"TGO","woe_id":-99,"adm0_a3_is":"TGO","adm0_a3_us":"TGO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Western Africa","region_wb":"Sub-Saharan Africa","name_len":4,"long_len":4,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-237,1756,-806,-241]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Thailand","sov_a3":"THA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Thailand","adm0_a3":"THA","geou_dif":0,"geounit":"Thailand","gu_a3":"THA","su_dif":0,"subunit":"Thailand","su_a3":"THA","brk_diff":0,"name":"Thailand","name_long":"Thailand","brk_a3":"THA","brk_name":"Thailand","brk_group":null,"abbrev":"Thai.","postal":"TH","formal_en":"Kingdom of Thailand","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Thailand","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":8,"mapcolor13":1,"pop_est":65905410,"gdp_md_est":547400,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TH","iso_a3":"THA","iso_n3":"764","un_a3":"764","wb_a2":"TH","wb_a3":"THA","woe_id":-99,"adm0_a3_is":"THA","adm0_a3_us":"THA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1757]],[[1758]],[[1759]],[[1760]],[[1761]],[[1762]],[[1763]],[[1764]],[[1765]],[[-1243,-1198,1766,-1363,1767,-1327]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Tajikistan","sov_a3":"TJK","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tajikistan","adm0_a3":"TJK","geou_dif":0,"geounit":"Tajikistan","gu_a3":"TJK","su_dif":0,"subunit":"Tajikistan","su_a3":"TJK","brk_diff":0,"name":"Tajikistan","name_long":"Tajikistan","brk_a3":"TJK","brk_name":"Tajikistan","brk_group":null,"abbrev":"Tjk.","postal":"TJ","formal_en":"Republic of Tajikistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tajikistan","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":7349145,"gdp_md_est":13160,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TJ","iso_a3":"TJK","iso_n3":"762","un_a3":"762","wb_a2":"TJ","wb_a3":"TJK","woe_id":-99,"adm0_a3_is":"TJK","adm0_a3_us":"TJK","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[-1192]],[[1768]],[[-1190,-558,-8,1769]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Turkmenistan","sov_a3":"TKM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Turkmenistan","adm0_a3":"TKM","geou_dif":0,"geounit":"Turkmenistan","gu_a3":"TKM","su_dif":0,"subunit":"Turkmenistan","su_a3":"TKM","brk_diff":0,"name":"Turkmenistan","name_long":"Turkmenistan","brk_a3":"TKM","brk_name":"Turkmenistan","brk_group":null,"abbrev":"Turkm.","postal":"TM","formal_en":"Turkmenistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Turkmenistan","name_alt":null,"mapcolor7":3,"mapcolor8":2,"mapcolor9":1,"mapcolor13":9,"pop_est":4884887,"gdp_md_est":29780,"pop_year":-99,"lastcensus":1995,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TM","iso_a3":"TKM","iso_n3":"795","un_a3":"795","wb_a2":"TM","wb_a3":"TKM","woe_id":-99,"adm0_a3_is":"TKM","adm0_a3_us":"TKM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":12,"long_len":12,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1770]],[[-6,-1104,1771,-1181,1772]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"East Timor","sov_a3":"TLS","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"East Timor","adm0_a3":"TLS","geou_dif":0,"geounit":"East Timor","gu_a3":"TLS","su_dif":0,"subunit":"East Timor","su_a3":"TLS","brk_diff":0,"name":"Timor-Leste","name_long":"Timor-Leste","brk_a3":"TLS","brk_name":"Timor-Leste","brk_group":null,"abbrev":"T.L.","postal":"TL","formal_en":"Democratic Republic of Timor-Leste","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Timor-Leste","name_alt":"East Timor","mapcolor7":2,"mapcolor8":2,"mapcolor9":4,"mapcolor13":3,"pop_est":1131612,"gdp_md_est":2520,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TL","iso_a3":"TLS","iso_n3":"626","un_a3":"626","wb_a2":"TP","wb_a3":"TMP","woe_id":-99,"adm0_a3_is":"TLS","adm0_a3_us":"TLS","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":11,"long_len":11,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1773,-936]],[[-938,1774]],[[1775]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Tonga","sov_a3":"TON","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tonga","adm0_a3":"TON","geou_dif":0,"geounit":"Tonga","gu_a3":"TON","su_dif":0,"subunit":"Tonga","su_a3":"TON","brk_diff":0,"name":"Tonga","name_long":"Tonga","brk_a3":"TON","brk_name":"Tonga","brk_group":null,"abbrev":"Tongo","postal":"TO","formal_en":"Kingdom of Tonga","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tonga","name_alt":null,"mapcolor7":2,"mapcolor8":1,"mapcolor9":1,"mapcolor13":8,"pop_est":120898,"gdp_md_est":549,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TO","iso_a3":"TON","iso_n3":"776","un_a3":"776","wb_a2":"TO","wb_a3":"TON","woe_id":-99,"adm0_a3_is":"TON","adm0_a3_us":"TON","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":3,"homepart":1},"arcs":[[[1776]],[[1777]],[[1778]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":5,"sovereignt":"Trinidad and Tobago","sov_a3":"TTO","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Trinidad and Tobago","adm0_a3":"TTO","geou_dif":0,"geounit":"Trinidad and Tobago","gu_a3":"TTO","su_dif":0,"subunit":"Trinidad and Tobago","su_a3":"TTO","brk_diff":0,"name":"Trinidad and Tobago","name_long":"Trinidad and Tobago","brk_a3":"TTO","brk_name":"Trinidad and Tobago","brk_group":null,"abbrev":"Tr.T.","postal":"TT","formal_en":"Republic of Trinidad and Tobago","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Trinidad and Tobago","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":2,"mapcolor13":5,"pop_est":1310000,"gdp_md_est":29010,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TT","iso_a3":"TTO","iso_n3":"780","un_a3":"780","wb_a2":"TT","wb_a3":"TTO","woe_id":-99,"adm0_a3_is":"TTO","adm0_a3_us":"TTO","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":19,"long_len":19,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1779]],[[1780]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Tunisia","sov_a3":"TUN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Tunisia","adm0_a3":"TUN","geou_dif":0,"geounit":"Tunisia","gu_a3":"TUN","su_dif":0,"subunit":"Tunisia","su_a3":"TUN","brk_diff":0,"name":"Tunisia","name_long":"Tunisia","brk_a3":"TUN","brk_name":"Tunisia","brk_group":null,"abbrev":"Tun.","postal":"TN","formal_en":"Republic of Tunisia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tunisia","name_alt":null,"mapcolor7":4,"mapcolor8":3,"mapcolor9":3,"mapcolor13":2,"pop_est":10486339,"gdp_md_est":81710,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TN","iso_a3":"TUN","iso_n3":"788","un_a3":"788","wb_a2":"TN","wb_a3":"TUN","woe_id":-99,"adm0_a3_is":"TUN","adm0_a3_us":"TUN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Northern Africa","region_wb":"Middle East & North Africa","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1781]],[[1782]],[[-1252,-658,1783]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Turkey","sov_a3":"TUR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Turkey","adm0_a3":"TUR","geou_dif":0,"geounit":"Turkey","gu_a3":"TUR","su_dif":0,"subunit":"Turkey","su_a3":"TUR","brk_diff":0,"name":"Turkey","name_long":"Turkey","brk_a3":"TUR","brk_name":"Turkey","brk_group":null,"abbrev":"Tur.","postal":"TR","formal_en":"Republic of Turkey","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Turkey","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":8,"mapcolor13":4,"pop_est":76805524,"gdp_md_est":902700,"pop_year":-99,"lastcensus":2000,"gdp_year":-99,"economy":"4. Emerging region: MIKT","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"TR","iso_a3":"TUR","iso_n3":"792","un_a3":"792","wb_a2":"TR","wb_a3":"TUR","woe_id":-99,"adm0_a3_is":"TUR","adm0_a3_us":"TUR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Europe & Central Asia","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1784]],[[-802,-50,-220,-1109,-1115,-1753,1785]],[[1786,-868,-255]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Taiwan","sov_a3":"TWN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Taiwan","adm0_a3":"TWN","geou_dif":0,"geounit":"Taiwan","gu_a3":"TWN","su_dif":0,"subunit":"Taiwan","su_a3":"TWN","brk_diff":1,"name":"Taiwan","name_long":"Taiwan","brk_a3":"B77","brk_name":"Taiwan","brk_group":null,"abbrev":"Taiwan","postal":"TW","formal_en":null,"formal_fr":null,"note_adm0":null,"note_brk":"Self admin.; Claimed by China","name_sort":"Taiwan","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":7,"mapcolor13":2,"pop_est":22974347,"gdp_md_est":712000,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"TW","iso_a3":"TWN","iso_n3":"158","un_a3":"-099","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"TWN","adm0_a3_us":"TWN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Eastern Asia","region_wb":"East Asia & Pacific","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1787]],[[1788]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"United Republic of Tanzania","sov_a3":"TZA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"United Republic of Tanzania","adm0_a3":"TZA","geou_dif":0,"geounit":"Tanzania","gu_a3":"TZA","su_dif":0,"subunit":"Tanzania","su_a3":"TZA","brk_diff":0,"name":"Tanzania","name_long":"Tanzania","brk_a3":"TZA","brk_name":"Tanzania","brk_group":null,"abbrev":"Tanz.","postal":"TZ","formal_en":"United Republic of Tanzania","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Tanzania","name_alt":null,"mapcolor7":3,"mapcolor8":6,"mapcolor9":2,"mapcolor13":2,"pop_est":41048532,"gdp_md_est":54250,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"TZ","iso_a3":"TZA","iso_n3":"834","un_a3":"834","wb_a2":"TZ","wb_a3":"TZA","woe_id":-99,"adm0_a3_is":"TZA","adm0_a3_us":"TZA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1789]],[[1790]],[[1791]],[[-1187,1792,-1344,-1355,1793,-580,-225,-1688,1794]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Uganda","sov_a3":"UGA","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uganda","adm0_a3":"UGA","geou_dif":0,"geounit":"Uganda","gu_a3":"UGA","su_dif":0,"subunit":"Uganda","su_a3":"UGA","brk_diff":0,"name":"Uganda","name_long":"Uganda","brk_a3":"UGA","brk_name":"Uganda","brk_group":null,"abbrev":"Uga.","postal":"UG","formal_en":"Republic of Uganda","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uganda","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":6,"mapcolor13":4,"pop_est":32369558,"gdp_md_est":39380,"pop_year":-99,"lastcensus":2002,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"UG","iso_a3":"UGA","iso_n3":"800","un_a3":"800","wb_a2":"UG","wb_a3":"UGA","woe_id":-99,"adm0_a3_is":"UGA","adm0_a3_us":"UGA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[-1795,-1689,-578,-1701,-1188]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Ukraine","sov_a3":"UKR","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Ukraine","adm0_a3":"UKR","geou_dif":0,"geounit":"Ukraine","gu_a3":"UKR","su_dif":0,"subunit":"Ukraine","su_a3":"UKR","brk_diff":0,"name":"Ukraine","name_long":"Ukraine","brk_a3":"UKR","brk_name":"Ukraine","brk_group":null,"abbrev":"Ukr.","postal":"UA","formal_en":"Ukraine","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Ukraine","name_alt":null,"mapcolor7":5,"mapcolor8":1,"mapcolor9":6,"mapcolor13":3,"pop_est":45700395,"gdp_md_est":339800,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UA","iso_a3":"UKR","iso_n3":"804","un_a3":"804","wb_a2":"UA","wb_a3":"UKR","woe_id":-99,"adm0_a3_is":"UKR","adm0_a3_us":"UKR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Europe","region_un":"Europe","subregion":"Eastern Europe","region_wb":"Europe & Central Asia","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1795]],[[1796,-1581,-1274,-1584,-926,-1741,-1537,-283,-1655]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Uruguay","sov_a3":"URY","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uruguay","adm0_a3":"URY","geou_dif":0,"geounit":"Uruguay","gu_a3":"URY","su_dif":0,"subunit":"Uruguay","su_a3":"URY","brk_diff":0,"name":"Uruguay","name_long":"Uruguay","brk_a3":"URY","brk_name":"Uruguay","brk_group":null,"abbrev":"Ury.","postal":"UY","formal_en":"Oriental Republic of Uruguay","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uruguay","name_alt":null,"mapcolor7":1,"mapcolor8":2,"mapcolor9":2,"mapcolor13":10,"pop_est":3494382,"gdp_md_est":43160,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UY","iso_a3":"URY","iso_n3":"858","un_a3":"858","wb_a2":"UY","wb_a3":"URY","woe_id":-99,"adm0_a3_is":"URY","adm0_a3_us":"URY","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":7,"long_len":7,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[1797,-43,-316]]}, + + { + "type": "MultiPolygon", + "properties": { "custom":"US-cont", "name":"Continental United States" }, + "arcs": [[[1842]], [[-354, 1856, -1297, 1857, -440]]] + }, + + {"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Country","admin":"United States of America","adm0_a3":"USA","geou_dif":0,"geounit":"United States of America","gu_a3":"USA","su_dif":0,"subunit":"United States of America","su_a3":"USA","brk_diff":0,"name":"United States","name_long":"United States","brk_a3":"USA","brk_name":"United States","brk_group":null,"abbrev":"U.S.A.","postal":"US","formal_en":"United States of America","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"United States of America","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":313973000,"gdp_md_est":15094000,"pop_year":0,"lastcensus":2010,"gdp_year":0,"economy":"1. Developed region: G7","income_grp":"1. High income: OECD","wikipedia":0,"fips_10":null,"iso_a2":"US","iso_a3":"USA","iso_n3":"840","un_a3":"840","wb_a2":"US","wb_a3":"USA","woe_id":-99,"adm0_a3_is":"USA","adm0_a3_us":"USA","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Northern America","region_wb":"North America","name_len":13,"long_len":13,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[[1798]],[[1799]],[[1800]],[[1801]],[[1802]],[[1803]],[[1804]],[[1805]],[[1806]],[[1807]],[[1808]],[[1809]],[[1810]],[[1811]],[[1812]],[[1813]],[[1814]],[[1815]],[[1816]],[[1817]],[[1818]],[[1819]],[[1820]],[[1821]],[[1822]],[[1823]],[[1824]],[[1825]],[[1826]],[[1827]],[[1828]],[[1829]],[[1830]],[[1831]],[[1832]],[[1833]],[[1834]],[[1835]],[[1836]],[[1837]],[[1838]],[[1839]],[[1840]],[[1841]],[[1842]],[[1843]],[[1844]],[[1845]],[[1846]],[[1847]],[[1848]],[[1849]],[[1850]],[[1851]],[[1852]],[[1853]],[[1854]],[[1855]],[[-354,1856,-1297,1857,-440]],[[1858]],[[1859]],[[1860]],[[1861]],[[1862]],[[1863]],[[1864]],[[1865]],[[1866]],[[1867]],[[1868]],[[1869]],[[1870]],[[1871]],[[1872]],[[1873]],[[1874]],[[1875]],[[1876]],[[1877]],[[1878]],[[1879]],[[1880]],[[1881]],[[1882]],[[1883]],[[1884]],[[1885]],[[1886]],[[1887]],[[1888]],[[1889]],[[1890]],[[1891]],[[1892]],[[1893]],[[1894]],[[1895]],[[1896]],[[1897]],[[1898]],[[1899]],[[1900]],[[1901]],[[1902]],[[1903]],[[1904]],[[1905]],[[1906]],[[1907]],[[1908]],[[1909]],[[1910]],[[1911]],[[1912]],[[1913]],[[1914]],[[1915]],[[1916]],[[1917]],[[1918]],[[1919]],[[1920]],[[1921]],[[1922]],[[1923]],[[1924]],[[-442,1925,-382,1926]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Uzbekistan","sov_a3":"UZB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Uzbekistan","adm0_a3":"UZB","geou_dif":0,"geounit":"Uzbekistan","gu_a3":"UZB","su_dif":0,"subunit":"Uzbekistan","su_a3":"UZB","brk_diff":0,"name":"Uzbekistan","name_long":"Uzbekistan","brk_a3":"UZB","brk_name":"Uzbekistan","brk_group":null,"abbrev":"Uzb.","postal":"UZ","formal_en":"Republic of Uzbekistan","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Uzbekistan","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":5,"mapcolor13":4,"pop_est":27606007,"gdp_md_est":71670,"pop_year":-99,"lastcensus":1989,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"UZ","iso_a3":"UZB","iso_n3":"860","un_a3":"860","wb_a2":"UZ","wb_a3":"UZB","woe_id":-99,"adm0_a3_is":"UZB","adm0_a3_us":"UZB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Central Asia","region_wb":"Europe & Central Asia","name_len":10,"long_len":10,"abbrev_len":4,"tiny":5,"homepart":1},"arcs":[[[-1193]],[[-1194]],[[-1191,-1770,-7,-1773,-1180],[-1769]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"Saint Vincent and the Grenadines","sov_a3":"VCT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Saint Vincent and the Grenadines","adm0_a3":"VCT","geou_dif":0,"geounit":"Saint Vincent and the Grenadines","gu_a3":"VCT","su_dif":0,"subunit":"Saint Vincent and the Grenadines","su_a3":"VCT","brk_diff":0,"name":"St. Vin. and Gren.","name_long":"Saint Vincent and the Grenadines","brk_a3":"VCT","brk_name":"St. Vin. and Gren.","brk_group":null,"abbrev":"St.V.G.","postal":"VC","formal_en":"Saint Vincent and the Grenadines","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"St. Vincent and the Grenadines","name_alt":null,"mapcolor7":1,"mapcolor8":1,"mapcolor9":5,"mapcolor13":7,"pop_est":104574,"gdp_md_est":1070,"pop_year":-99,"lastcensus":2011,"gdp_year":-99,"economy":"6. Developing region","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VC","iso_a3":"VCT","iso_n3":"670","un_a3":"670","wb_a2":"VC","wb_a3":"VCT","woe_id":-99,"adm0_a3_is":"VCT","adm0_a3_us":"VCT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":18,"long_len":32,"abbrev_len":7,"tiny":-99,"homepart":1},"arcs":[[[1927]],[[1928]],[[1929]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Venezuela","sov_a3":"VEN","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Venezuela","adm0_a3":"VEN","geou_dif":0,"geounit":"Venezuela","gu_a3":"VEN","su_dif":0,"subunit":"Venezuela","su_a3":"VEN","brk_diff":0,"name":"Venezuela","name_long":"Venezuela","brk_a3":"VEN","brk_name":"Venezuela","brk_group":null,"abbrev":"Ven.","postal":"VE","formal_en":"Bolivarian Republic of Venezuela","formal_fr":"República Bolivariana de Venezuela","note_adm0":null,"note_brk":null,"name_sort":"Venezuela, RB","name_alt":null,"mapcolor7":1,"mapcolor8":3,"mapcolor9":1,"mapcolor13":4,"pop_est":26814843,"gdp_md_est":357400,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VE","iso_a3":"VEN","iso_n3":"862","un_a3":"862","wb_a2":"VE","wb_a3":"VEN","woe_id":-99,"adm0_a3_is":"VEN","adm0_a3_us":"VEN","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"South America","region_un":"Americas","subregion":"South America","region_wb":"Latin America & Caribbean","name_len":9,"long_len":9,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1930]],[[1931]],[[1932]],[[1933]],[[-894,-320,-588,1934]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United Kingdom","sov_a3":"GB1","adm0_dif":1,"level":2,"type":"Dependency","admin":"British Virgin Islands","adm0_a3":"VGB","geou_dif":0,"geounit":"British Virgin Islands","gu_a3":"VGB","su_dif":0,"subunit":"British Virgin Islands","su_a3":"VGB","brk_diff":0,"name":"British Virgin Is.","name_long":"British Virgin Islands","brk_a3":"VGB","brk_name":"British Virgin Is.","brk_group":null,"abbrev":"V.I. (Br.)","postal":"VG","formal_en":"British Virgin Islands","formal_fr":null,"note_adm0":"U.K.","note_brk":null,"name_sort":"British Virgin Islands","name_alt":null,"mapcolor7":6,"mapcolor8":6,"mapcolor9":6,"mapcolor13":3,"pop_est":24491,"gdp_md_est":853.4,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"2. Developed region: nonG7","income_grp":"1. High income: OECD","wikipedia":-99,"fips_10":null,"iso_a2":"VG","iso_a3":"VGB","iso_n3":"092","un_a3":"092","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"VGB","adm0_a3_us":"VGB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":18,"long_len":22,"abbrev_len":10,"tiny":3,"homepart":-99},"arcs":[[[1935]],[[1936]],[[1937]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":6,"sovereignt":"United States of America","sov_a3":"US1","adm0_dif":1,"level":2,"type":"Dependency","admin":"United States Virgin Islands","adm0_a3":"VIR","geou_dif":0,"geounit":"United States Virgin Islands","gu_a3":"VIR","su_dif":0,"subunit":"United States Virgin Islands","su_a3":"VIR","brk_diff":0,"name":"U.S. Virgin Is.","name_long":"United States Virgin Islands","brk_a3":"VIR","brk_name":"U.S. Virgin Is.","brk_group":null,"abbrev":"V.I. (U.S.)","postal":"VI","formal_en":"Virgin Islands of the United States","formal_fr":null,"note_adm0":"U.S.A.","note_brk":null,"name_sort":"Virgin Islands (U.S.)","name_alt":null,"mapcolor7":4,"mapcolor8":5,"mapcolor9":1,"mapcolor13":1,"pop_est":109825,"gdp_md_est":1577,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"6. Developing region","income_grp":"2. High income: nonOECD","wikipedia":-99,"fips_10":null,"iso_a2":"VI","iso_a3":"VIR","iso_n3":"850","un_a3":"850","wb_a2":"VI","wb_a3":"VIR","woe_id":-99,"adm0_a3_is":"VIR","adm0_a3_us":"VIR","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"North America","region_un":"Americas","subregion":"Caribbean","region_wb":"Latin America & Caribbean","name_len":15,"long_len":28,"abbrev_len":11,"tiny":3,"homepart":-99},"arcs":[[[1938]],[[1939]],[[1940]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"Vietnam","sov_a3":"VNM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Vietnam","adm0_a3":"VNM","geou_dif":0,"geounit":"Vietnam","gu_a3":"VNM","su_dif":0,"subunit":"Vietnam","su_a3":"VNM","brk_diff":0,"name":"Vietnam","name_long":"Vietnam","brk_a3":"VNM","brk_name":"Vietnam","brk_group":null,"abbrev":"Viet.","postal":"VN","formal_en":"Socialist Republic of Vietnam","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Vietnam","name_alt":null,"mapcolor7":5,"mapcolor8":6,"mapcolor9":5,"mapcolor13":4,"pop_est":86967524,"gdp_md_est":241700,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VN","iso_a3":"VNM","iso_n3":"704","un_a3":"704","wb_a2":"VN","wb_a3":"VNM","woe_id":-99,"adm0_a3_is":"VNM","adm0_a3_us":"VNM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"South-Eastern Asia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":5,"tiny":2,"homepart":1},"arcs":[[[1941]],[[1942]],[[1943]],[[1944]],[[1945]],[[1946]],[[1947]],[[1948,-1200,-1242,1949,-1240,-538]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Vanuatu","sov_a3":"VUT","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Vanuatu","adm0_a3":"VUT","geou_dif":0,"geounit":"Vanuatu","gu_a3":"VUT","su_dif":0,"subunit":"Vanuatu","su_a3":"VUT","brk_diff":0,"name":"Vanuatu","name_long":"Vanuatu","brk_a3":"VUT","brk_name":"Vanuatu","brk_group":null,"abbrev":"Van.","postal":"VU","formal_en":"Republic of Vanuatu","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Vanuatu","name_alt":null,"mapcolor7":6,"mapcolor8":3,"mapcolor9":7,"mapcolor13":3,"pop_est":218519,"gdp_md_est":988.5,"pop_year":-99,"lastcensus":2009,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"VU","iso_a3":"VUT","iso_n3":"548","un_a3":"548","wb_a2":"VU","wb_a3":"VUT","woe_id":-99,"adm0_a3_is":"VUT","adm0_a3_us":"VUT","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Melanesia","region_wb":"East Asia & Pacific","name_len":7,"long_len":7,"abbrev_len":4,"tiny":2,"homepart":1},"arcs":[[[1950]],[[1951]],[[1952]],[[1953]],[[1954]],[[1955]],[[1956]],[[1957]],[[1958]],[[1959]],[[1960]],[[1961]],[[1962]],[[1963]]]},{"type":"MultiPolygon","properties":{"scalerank":3,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"France","sov_a3":"FR1","adm0_dif":1,"level":2,"type":"Dependency","admin":"Wallis and Futuna","adm0_a3":"WLF","geou_dif":0,"geounit":"Wallis and Futuna","gu_a3":"WLF","su_dif":0,"subunit":"Wallis and Futuna","su_a3":"WLF","brk_diff":0,"name":"Wallis and Futuna Is.","name_long":"Wallis and Futuna Islands","brk_a3":"WLF","brk_name":"Wallis and Futuna Islands","brk_group":null,"abbrev":"Wlf.","postal":"WF","formal_en":"Wallis and Futuna Islands","formal_fr":null,"note_adm0":"Fr.","note_brk":null,"name_sort":"Wallis and Futuna","name_alt":null,"mapcolor7":7,"mapcolor8":5,"mapcolor9":9,"mapcolor13":11,"pop_est":15289,"gdp_md_est":60,"pop_year":-99,"lastcensus":-99,"gdp_year":-99,"economy":"6. Developing region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"WF","iso_a3":"WLF","iso_n3":"876","un_a3":"876","wb_a2":"-99","wb_a3":"-99","woe_id":-99,"adm0_a3_is":"WLF","adm0_a3_us":"WLF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":21,"long_len":25,"abbrev_len":4,"tiny":3,"homepart":-99},"arcs":[[[1964]],[[1965]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":4,"sovereignt":"Samoa","sov_a3":"WSM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Samoa","adm0_a3":"WSM","geou_dif":0,"geounit":"Samoa","gu_a3":"WSM","su_dif":0,"subunit":"Samoa","su_a3":"WSM","brk_diff":0,"name":"Samoa","name_long":"Samoa","brk_a3":"WSM","brk_name":"Samoa","brk_group":null,"abbrev":"Samoa","postal":"WS","formal_en":"Independent State of Samoa","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Samoa","name_alt":null,"mapcolor7":3,"mapcolor8":3,"mapcolor9":4,"mapcolor13":6,"pop_est":219998,"gdp_md_est":1049,"pop_year":-99,"lastcensus":2006,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"WS","iso_a3":"WSM","iso_n3":"882","un_a3":"882","wb_a2":"WS","wb_a3":"WSM","woe_id":-99,"adm0_a3_is":"WSM","adm0_a3_us":"WSM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Oceania","region_un":"Oceania","subregion":"Polynesia","region_wb":"East Asia & Pacific","name_len":5,"long_len":5,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1966]],[[1967]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Yemen","sov_a3":"YEM","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Yemen","adm0_a3":"YEM","geou_dif":0,"geounit":"Yemen","gu_a3":"YEM","su_dif":0,"subunit":"Yemen","su_a3":"YEM","brk_diff":0,"name":"Yemen","name_long":"Yemen","brk_a3":"YEM","brk_name":"Yemen","brk_group":null,"abbrev":"Yem.","postal":"YE","formal_en":"Republic of Yemen","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Yemen, Rep.","name_alt":null,"mapcolor7":5,"mapcolor8":3,"mapcolor9":3,"mapcolor13":11,"pop_est":23822783,"gdp_md_est":55280,"pop_year":-99,"lastcensus":2004,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"YE","iso_a3":"YEM","iso_n3":"887","un_a3":"887","wb_a2":"RY","wb_a3":"YEM","woe_id":-99,"adm0_a3_is":"YEM","adm0_a3_us":"YEM","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Asia","region_un":"Asia","subregion":"Western Asia","region_wb":"Middle East & North Africa","name_len":5,"long_len":5,"abbrev_len":4,"tiny":-99,"homepart":1},"arcs":[[[1968]],[[1969]],[[1970]],[[1971]],[[1972,-1696,-1447]]]},{"type":"MultiPolygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":2,"sovereignt":"South Africa","sov_a3":"ZAF","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"South Africa","adm0_a3":"ZAF","geou_dif":0,"geounit":"South Africa","gu_a3":"ZAF","su_dif":0,"subunit":"South Africa","su_a3":"ZAF","brk_diff":0,"name":"South Africa","name_long":"South Africa","brk_a3":"ZAF","brk_name":"South Africa","brk_group":null,"abbrev":"S.Af.","postal":"ZA","formal_en":"Republic of South Africa","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"South Africa","name_alt":null,"mapcolor7":2,"mapcolor8":3,"mapcolor9":4,"mapcolor13":2,"pop_est":49052489,"gdp_md_est":491000,"pop_year":-99,"lastcensus":2001,"gdp_year":-99,"economy":"5. Emerging region: G20","income_grp":"3. Upper middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ZA","iso_a3":"ZAF","iso_n3":"710","un_a3":"710","wb_a2":"ZA","wb_a3":"ZAF","woe_id":-99,"adm0_a3_is":"ZAF","adm0_a3_us":"ZAF","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Southern Africa","region_wb":"Sub-Saharan Africa","name_len":12,"long_len":12,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[[1973]],[[-1340,-1749,-1338,1974,-1368,-330,1975],[-1258]]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Zambia","sov_a3":"ZMB","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Zambia","adm0_a3":"ZMB","geou_dif":0,"geounit":"Zambia","gu_a3":"ZMB","su_dif":0,"subunit":"Zambia","su_a3":"ZMB","brk_diff":0,"name":"Zambia","name_long":"Zambia","brk_a3":"ZMB","brk_name":"Zambia","brk_group":null,"abbrev":"Zambia","postal":"ZM","formal_en":"Republic of Zambia","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Zambia","name_alt":null,"mapcolor7":5,"mapcolor8":8,"mapcolor9":5,"mapcolor13":13,"pop_est":11862740,"gdp_md_est":17500,"pop_year":-99,"lastcensus":2010,"gdp_year":-99,"economy":"7. Least developed region","income_grp":"4. Lower middle income","wikipedia":-99,"fips_10":null,"iso_a2":"ZM","iso_a3":"ZMB","iso_n3":"894","un_a3":"894","wb_a2":"ZM","wb_a3":"ZMB","woe_id":-99,"adm0_a3_is":"ZMB","adm0_a3_us":"ZMB","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":6,"long_len":6,"abbrev_len":6,"tiny":-99,"homepart":1},"arcs":[[-1354,-1342,1976,-1367,-9,-581,-1794]]},{"type":"Polygon","properties":{"scalerank":1,"featurecla":"Admin-0 country","labelrank":3,"sovereignt":"Zimbabwe","sov_a3":"ZWE","adm0_dif":0,"level":2,"type":"Sovereign country","admin":"Zimbabwe","adm0_a3":"ZWE","geou_dif":0,"geounit":"Zimbabwe","gu_a3":"ZWE","su_dif":0,"subunit":"Zimbabwe","su_a3":"ZWE","brk_diff":0,"name":"Zimbabwe","name_long":"Zimbabwe","brk_a3":"ZWE","brk_name":"Zimbabwe","brk_group":null,"abbrev":"Zimb.","postal":"ZW","formal_en":"Republic of Zimbabwe","formal_fr":null,"note_adm0":null,"note_brk":null,"name_sort":"Zimbabwe","name_alt":null,"mapcolor7":1,"mapcolor8":5,"mapcolor9":3,"mapcolor13":9,"pop_est":12619600,"gdp_md_est":9323,"pop_year":0,"lastcensus":2002,"gdp_year":0,"economy":"5. Emerging region: G20","income_grp":"5. Low income","wikipedia":-99,"fips_10":null,"iso_a2":"ZW","iso_a3":"ZWE","iso_n3":"716","un_a3":"716","wb_a2":"ZW","wb_a3":"ZWE","woe_id":-99,"adm0_a3_is":"ZWE","adm0_a3_us":"ZWE","adm0_a3_un":-99,"adm0_a3_wb":-99,"continent":"Africa","region_un":"Africa","subregion":"Eastern Africa","region_wb":"Sub-Saharan Africa","name_len":8,"long_len":8,"abbrev_len":5,"tiny":-99,"homepart":1},"arcs":[[-1976,-329,-1977,-1341]]}]}},"arcs":[[[3058,5901],[0,-2],[-1,1],[-2,4],[-2,2],[1,3],[0,1],[2,-2],[2,-5],[0,-2]],[[7080,7328],[-2,0],[-2,1],[-1,2],[0,1],[-2,-2],[-3,-1],[-5,-5],[0,-1],[4,-5],[0,-1],[1,-1]],[[7070,7316],[-3,-2],[-7,-5],[-4,-4],[-1,0],[-3,1],[-4,3],[-1,-1],[-9,0],[-8,-1],[-3,-1],[-6,-1],[-4,0],[-3,-1],[-3,-3],[-3,-1],[-2,0],[-2,-2],[-2,-4],[-5,-6],[-3,-3],[-1,-3],[-2,0],[-2,0],[-2,-3],[-3,-5],[-4,-7],[-2,-3],[-1,-4],[1,-3],[3,-3],[2,-4],[0,-2],[2,-7],[1,-7],[1,-3],[1,-5],[0,-3],[-1,-2],[0,-2],[0,-3],[1,-2],[0,-2],[1,-2],[-1,-2],[-1,-2],[-1,-3],[-2,-5],[-3,-3],[-1,-3],[-2,-5],[-3,-6],[-2,-4],[-1,-3],[-1,-1],[0,-3],[1,-3],[2,-4],[0,-5],[0,-4],[0,-5],[-1,-4],[-6,-4],[-5,-2],[-7,0],[-2,1],[-2,1],[-7,4],[-3,-2],[-1,-7],[5,-10],[2,-6],[3,-9],[2,-5],[-1,-5],[-5,-5],[-4,-5],[-6,-1],[-4,-2],[-2,-2],[-1,-11],[-2,-4],[0,-5],[-1,-5],[-2,-3],[-1,-6],[0,-11],[1,-18],[-3,-5],[-3,-6],[-3,-4],[-3,-2],[-2,1],[-2,3],[-1,3],[-2,3],[-2,-1],[-2,-2],[-4,1],[-3,2],[-1,0],[-1,-3],[-3,-5],[-8,-7],[-3,-1],[-2,-1],[1,-4],[1,-2],[3,-2],[0,-2],[-2,-2],[-2,-2],[-4,-2],[-5,-1],[-4,1],[-3,4],[-3,0],[-2,-2],[-3,-4],[-3,-9],[-1,-1],[-1,-2],[-2,-2],[-2,-3],[-2,-6],[-1,-11],[0,-6],[0,-11],[-1,-7],[-1,-5],[1,-4],[1,-4],[0,-3],[-2,-3],[-1,-2],[-6,-3],[-9,-4],[-5,-3],[-8,-5],[-2,-1],[-5,0],[-3,1],[-3,0],[-5,0],[-4,-1],[-4,-3],[-2,-2],[-2,-3],[0,-1],[-4,2],[-11,4],[-30,-5],[-3,1],[-10,6],[-14,7],[-8,5],[-11,7]],[[6689,6904],[8,15]],[[6697,6919],[6,14],[6,13],[7,14],[0,4],[0,10],[-1,12],[-3,5],[-9,3],[-6,1],[-7,2],[-1,1],[-1,9],[0,5],[0,8],[0,6],[1,11],[0,4],[-3,21],[-2,11],[-2,11],[0,4],[0,4],[4,11],[1,3],[3,5],[1,3],[0,2],[-3,1],[-4,0],[-2,1],[-2,3],[0,5],[1,7],[-2,15],[3,7],[2,5],[7,1],[-3,5],[-1,4],[-1,0],[0,2],[1,2],[1,0],[1,2],[2,3],[1,1],[1,3],[1,2],[1,3],[1,3],[0,4],[1,5],[0,3],[1,2],[-1,4],[0,3],[0,3],[1,1],[1,2],[0,3],[1,3],[1,3],[1,2],[0,3],[-1,3]],[[6701,7235],[2,1],[1,-2],[1,-3],[4,-5],[2,-1],[3,-1],[3,1],[3,1],[1,-1],[3,-3],[3,-6],[2,-2],[0,-3],[1,-1],[2,3],[2,1],[2,0],[3,-1],[2,1],[1,1],[3,5],[4,3],[2,2],[1,7],[1,4],[1,3],[0,3],[-1,2],[-1,3],[1,1],[1,1],[4,0],[6,3],[5,3],[4,3],[2,0],[2,0],[1,1],[1,2],[1,3],[2,2],[5,4],[4,7],[2,5],[1,7],[2,12],[2,12],[1,5],[1,5],[4,3],[3,3],[6,0],[7,0],[2,7],[1,6],[1,3],[2,2],[0,1],[4,-4],[6,-5],[6,-3],[4,-1],[1,0]],[[6847,7335],[9,1],[6,-2],[4,-6],[3,-1],[4,3],[2,0],[1,-1],[1,-1],[3,0],[1,-2],[1,-1]],[[6882,7325],[0,-2],[2,-4],[3,-6],[3,-1],[4,4],[1,0],[1,1],[1,3],[2,3],[4,3],[3,2],[1,2],[1,0],[2,0],[1,1],[0,1],[1,1],[1,1],[1,0],[1,0],[2,-4],[4,-6],[2,-3],[1,1],[2,2],[1,3],[1,5],[-1,6],[1,5],[2,4],[3,2],[6,1],[3,0],[1,-2],[2,-2],[2,0],[2,2],[2,5],[0,6],[-2,7],[1,2],[0,1],[2,3],[3,5],[3,7],[3,8],[3,5],[4,2],[5,-2],[6,-7],[2,-8],[-2,-9],[0,-5],[1,-1],[2,0],[3,2],[2,0],[1,-2],[0,-2],[-1,-4],[-1,-11],[-1,-10],[-1,-9],[0,-9],[1,-6],[1,-10],[2,-6],[2,-3],[2,0],[2,0],[4,4],[6,8],[5,5],[9,3],[2,8],[4,5],[9,8],[5,4],[2,0],[4,-1],[1,-1],[2,-1],[0,-2],[0,-3],[-2,-2],[0,-2],[0,-1],[3,-1],[5,3],[4,2],[2,1],[2,2],[1,3],[3,0],[2,-1],[2,-1],[4,1],[2,-2],[3,-5],[1,-2],[1,-1]],[[5665,4558],[1,-8],[0,-10],[1,-8],[0,-3],[0,-2],[0,-2],[0,-5],[-1,-4],[-1,-2],[1,-6],[-1,-7],[0,-8],[0,-7],[1,-14],[0,-4],[-1,-7],[-1,-5],[-1,-6],[0,-3],[2,-9],[0,-2],[-2,-1],[-1,0],[-6,0],[-8,0],[-9,0],[-8,0],[-7,0],[-8,0],[-6,0],[0,-9],[0,-18],[0,-19],[0,-18],[0,-19],[0,-18],[0,-19],[0,-18],[0,-19],[0,-13],[2,-18],[3,-19],[1,-2],[3,-3],[4,-8],[3,-5],[5,-10],[6,-12],[6,-11],[6,-9]],[[5649,4168],[-9,-4],[-12,-4],[-8,-4],[-11,-4],[-6,-2],[-9,-3],[-1,0],[-2,2],[-5,1],[-6,-3],[-4,-1],[-4,1],[-3,3],[-3,4],[-6,1],[-7,-1],[-8,1],[-7,2],[-6,1],[-3,0],[-3,0],[-4,2],[-3,4],[-3,8],[-3,7],[-1,1],[-1,1],[-1,1],[-8,0],[-7,0],[-4,0],[-11,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-6,0],[-5,0],[-6,-1],[-1,0],[-1,1],[-1,2],[-3,4],[-3,3],[-4,5],[-2,6],[-2,2],[-4,1],[-2,1],[-3,0],[-3,-2],[-3,-3],[-2,-3],[-4,-3],[-3,-3],[-5,1],[-1,-1],[-3,1],[-3,2],[-3,0],[-3,-3],[-4,-2]],[[5326,4190],[1,22],[1,10],[0,11],[-1,30],[-1,4],[0,5],[3,4],[1,2],[2,5],[1,7],[2,16],[6,35],[2,34],[4,17],[1,18],[10,23],[2,15],[5,7],[7,8],[5,13],[3,9],[2,18],[0,19],[2,25],[0,7],[-3,10],[0,7],[-3,7],[-2,6],[-2,9],[-4,15],[-1,10],[-3,7],[0,9],[-1,9],[-2,9],[-2,11],[0,3],[1,4],[1,1],[0,-2],[-1,-2],[0,-2],[9,18],[0,4],[0,4],[0,5],[0,6],[-8,34],[-6,31],[-1,16],[-9,21],[-3,14],[-2,9],[-1,4],[0,2],[2,0],[5,3],[7,2],[6,6],[1,2]],[[5362,4846],[4,0],[3,-1],[1,1],[1,0],[8,0],[3,1],[6,-1],[4,0],[2,-1],[5,-1],[8,1],[2,0],[10,0],[9,1],[8,0],[10,0],[7,0],[3,-2],[3,-4],[1,-3],[1,-2],[1,-3],[1,-3],[1,-5],[-1,-6],[1,-7],[1,-8],[1,-9],[3,-10],[2,-7],[-1,-5],[1,-6],[2,-6],[2,-4],[1,-2],[2,-9],[5,-15],[4,-11],[1,-2],[2,1],[3,1],[4,0],[3,-2],[1,0],[4,5],[4,1],[4,2],[2,2],[3,0],[6,-4],[2,0],[5,0],[6,2],[1,15],[0,3],[1,6],[2,4],[0,5],[0,7],[1,7],[4,6],[6,3],[3,1],[5,2],[8,1],[3,0],[1,-1],[-2,-10],[0,-4],[1,-3],[1,-2],[8,-1],[8,0],[9,0],[7,-1],[0,-1],[1,0],[1,-6],[0,-10],[-2,-15],[1,-14],[3,-14],[0,-20],[-1,-12],[-1,-15],[-1,-18],[2,-7],[2,-7],[4,-8],[3,-11],[2,-12],[1,-8],[-1,-3],[0,-6],[1,-8],[-1,-5],[-2,-3],[-1,-4],[2,-7],[0,-6],[1,-2],[0,-2],[1,0],[2,2],[3,4],[2,2],[3,0],[4,-1],[7,-1],[3,1],[6,6],[2,0],[3,-1],[4,-1],[3,-1],[2,2],[1,2],[0,3],[1,2]],[[5339,4852],[-1,2],[-1,5],[1,6],[1,4],[-1,8],[-2,7],[-2,10],[-1,2]],[[5333,4896],[2,3],[2,6],[1,4],[3,0],[1,3],[1,4],[0,2],[4,2],[4,3],[2,3],[2,3],[1,0],[1,-1],[3,-6],[2,-4],[1,-1]],[[5363,4917],[-1,-1],[-3,-3],[-3,-2],[-4,-10],[-3,-4],[0,-1],[-2,-2],[-2,-2],[0,-1],[1,-2],[1,-2],[0,-16],[0,-15],[-1,-2],[-2,0],[-4,-1],[-1,-1]],[[3250,6233],[-5,-3],[0,2],[4,4],[1,0],[0,-3]],[[5557,7634],[1,-1],[2,-6],[2,-5],[3,-1],[1,-2],[2,-3],[2,-3],[1,-9],[0,-6],[0,-2]],[[5571,7596],[-1,-1],[-1,-9],[0,-5],[0,-3],[-1,-1],[-1,-2],[2,-7],[0,-3],[0,-4],[2,-8],[1,-3],[1,-1],[2,-8],[1,-1],[3,1],[2,-1],[1,-2],[0,-1]],[[5582,7537],[0,-5],[0,-3],[2,-3],[0,-2],[-1,-4],[-2,-4],[-2,-1],[-2,-2],[-1,-3],[0,-3],[-1,-2],[-1,-3],[-1,-6],[0,-2],[-1,-2],[-2,0],[-2,0],[-2,-1],[0,-2],[-2,-2],[0,-2],[1,-4],[1,-2],[0,-3],[-1,0],[-1,0],[-1,-1],[0,-2],[0,-2],[-1,-2],[-1,-1],[-2,0],[-2,2],[-1,1],[-1,0]],[[5555,7471],[0,5],[-1,4],[-3,10],[-10,10],[-3,4],[-1,4],[-1,3],[1,0],[1,-1],[1,-1],[1,2],[-1,4],[-2,9],[0,2],[1,7],[2,8],[0,10],[1,8],[-1,5],[-1,6],[2,8],[1,2],[1,2],[0,9],[-3,4],[-3,0]],[[5537,7595],[0,3],[0,5],[0,1],[0,3],[-1,3],[-1,3],[1,4],[2,6],[2,4],[2,4],[2,5],[1,3],[2,1],[0,-1],[1,-1],[0,-5],[0,-1],[1,-2],[2,1],[2,1],[3,3],[1,-1]],[[5572,8642],[0,-1],[-3,-1],[0,2],[-3,-1],[0,1],[1,1],[2,1],[2,0],[1,-2]],[[5546,8650],[0,-1],[-1,1],[-1,-1],[-1,-2],[-1,1],[0,2],[1,4],[2,0],[1,-4]],[[5555,8660],[1,0],[1,0],[3,-2],[0,-1],[2,-1],[0,-1],[-2,-4],[-1,0],[-1,0],[-1,0],[-1,-1],[0,-2],[0,-3],[-7,-1],[-1,1],[-2,8],[0,2],[2,1],[1,0],[0,-4],[2,0],[0,3],[0,2],[0,1],[-1,1],[-1,1],[1,2],[2,1],[1,-3],[2,0]],[[5047,7632],[-1,0],[-2,-3],[-2,-1],[-1,0],[-1,0],[-1,2],[0,2],[0,2],[0,1],[0,2]],[[5039,7637],[1,2],[1,1],[2,0],[4,-2],[1,-2],[0,-1],[-1,-2],[0,-1]],[[6497,6576],[0,-2],[-2,1],[-1,-1],[-3,1],[-2,1],[2,2],[4,3],[1,-2],[1,-3]],[[6461,6583],[-1,-1],[0,3],[0,1],[1,2],[1,-3],[-1,-2]],[[6481,6581],[-2,0],[-2,2],[4,3],[1,1],[1,3],[1,-2],[-1,-4],[-1,-2],[-1,-1]],[[6512,6592],[0,-1],[-1,0],[-2,1],[0,1],[1,2],[1,-2],[1,-1]],[[6563,6661],[2,-4],[0,-32],[1,-2]],[[6566,6623],[-1,-1],[-1,-2],[-2,-4],[-1,-2],[-2,-2],[-1,-3],[-1,0],[-2,3],[-1,4],[1,1],[0,1],[0,3],[-1,1],[-1,0],[-2,-1],[-1,-2],[-1,-3],[0,-5],[0,-5],[0,-3],[0,-4],[-1,-5],[1,-3],[0,-3],[1,-2],[-2,-6],[1,-1],[4,0],[1,-5],[1,-2],[-1,-2],[-2,-1],[-3,-2],[-3,1],[-4,-2],[-2,-3],[1,-2],[1,-1],[0,-4],[-1,-6],[-1,-5],[-1,-7],[-2,-7],[-2,-11],[-2,-9],[-1,-7],[1,-4],[-1,-8]],[[6532,6492],[-2,-5],[-2,0],[-1,1],[-2,0],[-3,1],[-5,1],[-5,1],[-5,2],[-6,1],[-6,2],[-6,1],[-6,2],[-6,1],[-5,1],[-4,2],[-4,0],[-2,1],[-3,1],[-1,3],[-2,4],[-1,3],[-2,4],[-1,4],[-2,4],[-1,3],[-2,4],[-1,4],[-2,4],[-1,4],[-2,3],[-1,4],[-2,4],[-1,4],[-2,3],[-1,4],[-2,3],[0,3],[0,7],[0,2]],[[6432,6583],[1,3],[0,-2],[1,-3],[2,0],[1,0],[1,-11],[1,-3],[2,-2],[6,-1],[4,2],[7,7],[4,2],[10,0],[9,-3],[13,-2],[2,1],[7,5],[5,5],[2,1],[2,5],[1,6],[1,4],[1,2],[2,3],[1,5],[2,6],[10,13],[6,11],[0,4],[3,5],[3,6],[11,17],[3,8],[1,7],[0,1]],[[6557,6685],[1,0],[2,-1],[0,-6],[-1,-5],[0,-6],[0,-3],[1,-3],[2,-1],[1,0],[0,1]],[[6561,6636],[1,0],[1,1],[0,3],[0,1],[-2,0],[0,-2],[0,-3]],[[3207,2032],[3,-1],[6,1],[3,0],[1,-1],[1,0],[4,1],[2,0],[0,-3],[-4,-2],[-2,1],[-8,0],[-4,-3],[-1,0],[-4,-3],[-2,2],[-1,2],[2,3],[2,0],[1,1],[1,2]],[[3093,2024],[0,13],[0,18],[0,15],[0,16],[0,15],[0,16],[0,17],[0,17]],[[3093,2151],[2,-2],[6,-12],[2,-5],[1,-6],[-2,4],[-3,-2],[-2,-3],[-1,-4],[0,-3],[1,-2],[3,-2],[6,-1],[1,0],[4,-14],[1,-4],[3,-2],[5,-7],[5,-8],[5,-7],[7,-6],[5,-4],[6,-6],[6,-7],[6,-5],[7,-4],[6,-3],[11,1],[3,0],[2,-3],[-2,-6],[-2,-5],[-4,-2],[-4,-1],[-3,0],[-3,1],[-3,0],[-3,-3],[-3,-1],[-4,0],[-3,-2],[-3,-1],[-3,1],[-8,5],[-6,1],[-18,2],[-6,2],[-6,1],[-3,0],[-5,-1],[-3,0],[-1,-1]],[[3281,2928],[0,-4],[-1,0],[-4,4],[-1,3],[0,1],[3,-1],[2,-1],[1,-2]],[[3259,3903],[1,-1],[0,-2],[2,-4],[5,-5],[5,-10],[4,-14],[3,-11],[4,-7],[3,-5],[3,-3],[2,-3],[0,-2],[3,-3],[5,-6],[4,-6],[1,-5],[6,-6],[9,-6],[7,-3],[4,0],[6,-5],[8,-10],[5,-7],[1,-4],[6,-6],[12,-13],[6,-3],[3,-3],[1,-4],[2,-1],[2,2],[3,-2],[5,-4],[4,-5],[4,-11],[2,-4],[1,-4],[-1,-4],[-1,-4],[-3,-4],[-1,-1],[0,-2],[0,-3],[-3,-7],[0,-4],[0,-2],[-2,-3],[-4,-5],[-1,-2],[0,-3],[0,-1],[-1,-1],[0,-2],[-1,-5],[0,-5],[0,-7],[0,-2],[-1,-1],[0,-2],[0,-3],[-1,-2],[-1,-2],[-1,-1],[1,-2],[-1,-2],[-3,-2],[-1,-3],[0,-3],[-2,-3],[-2,-3],[0,-4],[1,-6],[12,2],[10,-3],[11,-6],[8,-2],[4,2],[3,-1],[2,-2],[2,-1],[3,2],[3,-1],[2,-4],[2,1],[1,5],[2,5],[3,2],[2,1],[3,-1],[3,-2],[2,-3],[2,0],[2,3],[1,4],[0,5],[1,3],[2,2],[1,3],[1,3],[2,2],[4,1],[2,2],[0,2],[1,3],[3,2],[1,3],[1,3],[1,2],[2,1],[2,7],[2,12],[1,18],[1,25]],[[3483,3711],[2,0],[1,-2],[1,-1],[2,2],[1,1],[3,0],[1,2],[1,1],[1,-2],[1,-1],[2,0],[2,-4],[2,-2],[0,-4],[2,-12],[2,-8],[2,-8],[0,-3],[-1,-4],[-1,-5],[0,-13],[0,-5],[0,-3],[1,-5],[-2,-5],[-2,-8],[-2,-3],[-1,0],[-2,-4],[-3,-2],[-1,1],[-1,-2],[-2,-5],[-1,-3],[-4,-1],[-1,-1],[-2,0],[-1,-1],[-2,-3],[-1,-1],[-2,1],[-1,-1],[-2,-3],[0,-3],[-1,-3],[-1,-2],[-2,-2],[-1,-1],[0,-3],[-1,-1],[-4,-2],[-3,-3],[-2,-5],[-1,-3],[-3,-2],[-4,-5],[-1,-3],[2,-2],[0,-3],[0,-2],[-1,0],[-3,1],[-1,1],[-1,-1],[0,-2],[0,-2],[-1,-2],[-1,-1],[-1,-2],[-1,-3],[-2,-4],[-3,-5],[-3,-7],[-2,-8],[-2,-6],[-3,-3],[-2,-3],[-1,-5],[-2,-8],[-5,-10],[-4,-7],[-4,-4],[-2,-4],[0,-5],[-3,-5],[-4,-6],[-2,-3]],[[3399,3445],[-1,-2],[0,-4],[-1,-5],[-4,-7],[-1,-5],[2,-7],[0,-9],[-1,-3],[-1,-1],[-1,-2],[1,-4],[0,-4],[0,-5],[-2,-6],[-2,-7],[-1,-4],[1,-3],[1,-2],[0,-2],[-1,-4],[-1,-5],[-1,-4],[-2,-2],[-1,-3],[1,-4],[0,-3],[0,-4],[0,-4],[1,-4],[0,-4],[-2,-9]],[[3383,3313],[-1,-5],[2,-23],[-1,-3],[-1,-3],[-2,-1],[-2,1],[-1,-2],[-1,-10],[-3,-22],[1,-5],[2,-9],[1,-5],[0,-4],[1,-8],[-2,-3],[-1,-1],[-1,-2],[2,-9],[1,-4],[4,-9],[14,-12],[6,-7],[7,-10],[4,-10],[0,-8],[-5,-13],[-1,-10],[1,-7],[2,-7],[5,-9],[4,-3],[5,0],[1,-2],[1,-2],[1,-18],[-1,-7],[-1,-6],[-10,-28],[-9,-17],[-3,-10],[-1,-10],[-3,-5],[-14,-15],[-23,-14],[-19,-7],[-4,-2],[-30,-8],[-6,-1],[-7,1],[-7,-1],[-6,2],[-6,2],[-4,6],[-4,1],[-1,-3],[2,-8],[-1,-9],[1,-6],[3,-1],[2,-2],[2,-4],[-4,0],[2,-3],[1,-2],[0,-6],[-1,-15],[-4,-3],[-1,-1],[-1,-3],[-2,-14],[0,-10],[1,-6],[4,-12],[-2,-8],[-3,-4],[-11,-9],[-4,-4],[-7,-3],[-12,0],[-4,1],[-10,8],[-7,5],[-6,4],[-7,2],[1,1],[1,2],[-2,1],[-2,1],[-4,-5],[-2,-4],[0,-4],[0,-9],[1,-7],[3,-19],[0,-11],[-2,-13],[3,-7],[2,-4],[5,-3],[3,-2],[2,0],[1,-1],[-1,-2],[-1,-3],[0,-3],[4,-1],[5,0],[4,2],[1,2],[0,5],[-5,1],[1,2],[4,2],[5,3],[3,1],[1,-2],[2,-2],[1,-6],[1,-7],[0,-8],[0,-8],[-1,-3],[-2,-4],[-9,-4],[-3,1],[-2,6],[-1,6],[-2,5],[-5,3],[-4,-1],[-5,-6],[-4,-2],[-2,-5],[11,-9],[6,-2],[1,0],[2,-1],[-2,-3],[-1,-2],[-8,-5],[-3,-3],[-4,-6],[-6,-13],[-2,-3],[-1,-3],[0,-9],[2,-15],[-2,-7],[1,-7],[-1,-4],[-2,-7],[-8,-11],[-1,-7],[2,-5],[0,-4],[-1,-4],[-3,0],[-12,3],[-4,-4],[-4,-5],[-1,-2],[-2,-2],[-8,-2],[-2,-2],[-9,-18],[-3,-12],[-5,-11],[-1,-5],[0,-6],[0,-6],[1,-5],[2,-5],[3,-7],[17,-26],[3,-2],[18,-3],[4,-3],[3,-6],[1,-5],[-1,-13],[-1,-4],[-2,-4],[-5,-4],[-5,-3],[2,-2],[2,1],[4,1],[2,-1],[2,-6],[-3,-2],[-1,-2],[-2,-4],[-11,-15],[-5,-4],[-5,-6],[-7,-6],[-3,-4],[-4,-7],[-5,-8],[-6,-17],[-1,-3],[1,-2],[-3,-30],[-1,-3],[-3,-4],[-6,-6],[-3,-1],[-4,3],[-3,4],[-2,7],[-3,6],[0,-2],[1,-4],[-1,-4],[-7,-2],[-1,-2],[6,1],[4,-2],[2,-1],[2,-3],[1,-4],[-1,-2],[-4,-2],[-4,-3],[-5,-6],[-3,-7],[-1,-5],[-2,-9],[0,-7],[-3,-5],[-3,-4],[0,-1],[3,2],[1,1],[2,-6],[2,-12],[1,-8],[0,-3],[-1,-3],[-4,-1],[-4,0],[-3,-1],[2,-2],[2,1],[4,-4],[4,2],[2,-3],[1,-2],[7,-17],[5,-11],[3,-6],[-2,-3]],[[3098,2168],[0,4],[-4,1],[-3,1],[-6,3],[-8,4],[-8,0],[-6,3],[-7,4],[-14,1],[-13,0],[-13,0],[-8,0],[-6,0],[-1,2],[0,5],[-2,3],[-3,4],[-4,3],[-2,5],[-2,4],[2,4],[1,10],[0,4],[-1,3],[-1,5],[1,2],[1,1],[1,7],[-1,7],[-1,7],[-1,2],[-2,2],[-1,0],[-4,-2],[-5,0],[-1,-1],[-3,-2],[-3,-4],[-2,1],[-1,4],[-1,4],[-1,3],[-1,5],[-1,6],[-2,8],[-3,6],[0,5],[-1,7],[2,7],[-1,5],[-2,7],[1,7],[1,4],[1,4],[9,1],[0,7],[1,5],[2,5],[1,2],[4,2],[3,2],[3,4],[1,2],[0,4],[0,4],[0,8],[1,3],[2,3],[4,3],[2,8],[-1,7],[-3,5],[-2,3],[-1,5],[2,6],[1,5],[2,7],[0,4],[2,3],[5,6],[2,6],[1,1],[2,1],[0,3],[-1,4],[0,4],[0,4],[0,6],[3,3],[3,5],[1,3],[0,4],[-1,9],[-1,6],[0,2],[-2,4],[-1,3],[2,3],[3,4],[2,5],[-1,4],[-2,3],[-1,6],[1,9],[1,2],[5,1],[1,5],[4,6],[0,6],[-3,3],[-2,6],[-2,5],[-6,3],[-6,1],[-1,5],[0,3],[3,-1],[5,1],[3,0],[3,1],[3,0],[3,-2],[2,2],[1,7],[2,4],[0,4],[-1,3],[-4,1],[-13,2],[-1,3],[0,6],[1,5],[0,2],[1,3],[2,4],[1,4],[-1,4],[-3,6],[2,2],[0,4],[0,3],[-3,4],[-2,5],[0,5],[3,1],[1,2],[1,3],[-1,4],[-3,2],[-5,2],[-1,2],[-1,5],[1,12],[-1,7],[0,4],[1,4],[1,2],[0,7],[-2,3],[1,3],[1,3],[1,3],[1,1],[1,-2],[3,1],[2,3],[1,3],[-1,4],[-2,12],[-2,7],[1,2],[0,3],[0,10],[0,5],[0,18],[0,5],[-2,6],[1,6],[1,4],[1,6],[1,5],[1,2],[2,1],[0,3],[-1,2],[-2,3],[0,4],[0,3],[1,1],[2,0],[1,5],[1,5],[0,2],[-1,3],[-1,8],[-1,4],[1,2],[1,0],[2,-1],[1,1],[1,2],[0,2],[0,2],[2,5],[1,7],[0,5],[0,12],[0,3],[2,3],[2,2],[2,2],[3,3],[4,2],[1,3],[1,4],[1,4],[-2,2],[-2,3],[-1,8],[0,7],[0,9],[-2,7],[-2,9],[-1,7],[1,4],[1,7],[-1,3],[-1,5],[1,5],[1,6],[0,3],[-1,8],[-1,5],[1,4],[1,5],[2,2],[-1,4],[1,3],[2,2],[2,4],[2,1],[1,0],[1,1],[1,3],[0,3],[3,4],[2,4],[3,1],[1,4],[0,5],[0,5],[1,6],[-1,10],[0,5],[-1,4],[0,4],[-1,3],[-2,1],[0,4],[1,1],[1,2],[2,2],[2,13],[1,4],[0,5],[0,2],[1,4],[1,5],[2,5],[1,4],[2,4],[0,3],[1,2],[2,0],[2,1],[0,2],[0,2],[0,6],[0,8],[-1,12],[1,7],[1,8],[1,4],[0,3],[-1,4],[-2,2],[-2,-2],[-1,0],[-2,4],[-1,5],[1,6],[1,3],[1,5],[-1,1],[-2,3],[-2,11],[1,8],[-2,3],[-1,7],[-2,2],[0,5],[-1,6],[0,2],[2,1],[1,4],[-1,2],[-1,3],[-2,-1],[-1,3],[-2,10],[-2,5],[1,9],[0,6],[1,5],[0,5],[1,2],[1,-1],[1,0],[2,4],[1,2],[0,2],[-1,2],[0,3],[0,4],[2,9],[2,10],[1,3],[0,4],[0,1],[1,-2],[4,2],[2,5],[0,4],[2,2],[-1,3],[-2,1],[-1,1],[1,4],[0,8],[0,6],[-1,13],[-1,13],[0,4],[3,6],[2,3],[0,3],[2,15],[1,8],[1,5],[1,8],[3,8],[1,4],[2,1],[1,2],[2,5],[2,6],[2,2],[1,5],[1,6],[2,10],[1,7],[2,2],[1,9],[1,6],[2,2],[2,1],[2,-3],[1,1],[2,3],[4,2],[1,1],[1,3],[0,6],[-2,4],[-3,8],[-2,8],[-1,3],[0,3],[1,4],[1,4],[3,7],[0,5],[-2,19],[-1,5],[-2,10],[0,4],[2,10],[1,4],[2,1],[1,2],[0,2],[-1,2],[-1,3],[0,4],[-2,2],[-1,3],[0,5],[2,7],[1,2],[1,3],[2,3],[1,2],[2,4],[5,5],[5,3],[9,8],[6,4],[0,4],[1,2],[2,18],[4,22],[2,14],[-5,10]],[[3133,3869],[1,3],[3,7],[1,6],[1,2],[5,6],[1,4],[1,4],[1,3],[2,1],[3,3],[4,2],[1,4],[2,6],[0,6],[1,2],[2,0],[2,-2],[1,-2],[5,-9],[3,-4],[2,-1],[5,1],[1,0],[12,0],[1,-1],[4,-2],[3,-1],[1,-1],[3,-3],[2,-8],[2,-6],[1,-6],[2,-10],[1,-4],[0,2],[2,11],[1,6],[2,8],[5,16],[1,3],[2,1],[1,0],[1,-1],[2,0],[1,1],[11,1],[12,0],[1,-3],[2,-7],[2,-3],[0,-1]],[[6265,7523],[-1,-1],[-1,1],[0,2],[0,1],[1,0],[1,-1],[0,-2]],[[6291,7425],[-5,0],[-4,-2],[-2,0]],[[6280,7423],[-1,5],[-1,3],[-2,9],[1,4],[-2,2],[-3,4],[-1,2],[0,2],[1,4],[-1,4],[-1,1],[-2,0],[-2,-1],[-4,-3],[-3,2],[-2,2],[-1,1],[-2,-1],[0,1],[0,4],[-1,2],[-1,3],[-2,1],[-4,-2],[-3,-1]],[[6243,7471],[-1,2],[-5,8],[-4,6],[-3,3],[-3,0],[-5,-1],[-2,0],[-4,3],[-4,3],[1,1],[1,1],[-1,5],[-2,6],[0,2],[-1,3],[0,3],[2,5],[2,4],[0,4],[-1,4],[-2,8],[-1,3],[-2,2],[-2,3],[0,3]],[[6206,7552],[1,0],[5,0],[4,1],[3,1],[5,2],[2,1],[2,1],[7,-2],[2,1],[8,1],[-1,2],[5,1],[0,1]],[[6249,7562],[1,-3],[2,-2],[2,-2],[1,-1],[0,-1],[-4,-2],[0,-1],[1,-1],[5,-3],[3,0],[1,-1],[1,-3],[2,-3],[2,-2],[0,-1],[-1,-2],[-4,-6],[-1,-1],[0,-3],[2,-6],[3,-6],[5,-5],[6,-6],[0,-3],[-1,-4],[-1,-3],[0,-2],[-1,-1],[-6,1],[-1,-1],[0,-1],[-1,-1],[3,-1],[3,-4],[2,-4],[2,-2],[3,-3],[2,-4],[3,-4],[3,2],[5,-4],[0,-2],[-1,-2],[-2,-3],[-1,-1],[0,-1],[1,-1],[1,-2],[2,-3],[2,-4],[-1,-1],[-2,0],[-1,0],[-1,-1],[0,-1],[2,-3],[1,-3],[0,-4],[0,-5]],[[6249,7547],[0,-1],[1,1],[0,1],[0,2],[-1,0],[-1,0],[0,-2],[1,-1]],[[258,4357],[-2,0],[-1,2],[3,3],[1,1],[3,-1],[-2,-1],[-2,-4]],[[500,396],[-9,-1],[-20,3],[-6,2],[-2,2],[-6,2],[-2,1],[0,2],[0,2],[-2,1],[-1,1],[-2,1],[28,-1],[11,-2],[2,-1],[19,-6],[-5,-1],[-5,-5]],[[611,455],[-2,-1],[-2,3],[-11,7],[-6,4],[-5,3],[-1,2],[2,0],[15,-7],[3,-2],[12,-5],[-5,-4]],[[543,484],[-3,0],[-75,7],[-14,2],[-4,1],[-1,1],[0,1],[0,2],[2,2],[19,2],[20,-2],[25,-5],[17,-3],[9,-4],[4,-2],[1,-2]],[[724,574],[-5,0],[-7,0],[-5,2],[-11,2],[-3,4],[-13,3],[-6,1],[2,3],[14,-4],[17,-5],[14,-3],[3,-3]],[[3340,556],[-1,-12],[0,-6],[-1,-4],[-3,-3],[-5,-3],[-4,-3],[-9,-4],[-40,4],[-18,3],[-8,4],[-1,2],[-2,6],[-2,2],[-16,-2],[-10,-2],[-2,-1],[-2,-3],[-2,-1],[-26,8],[-27,9],[-11,5],[-4,3],[-1,1],[2,2],[3,1],[3,1],[3,0],[2,-1],[2,-1],[2,-5],[1,-1],[4,-1],[96,0],[8,1],[17,1],[9,2],[3,3],[-8,1],[-3,2],[-3,4],[-1,4],[1,3],[11,1],[1,1],[-2,2],[0,3],[6,2],[2,3],[13,4],[20,-2],[4,-6],[-1,-4],[-1,-3],[0,-6],[8,-1],[2,-2],[3,-2],[-3,0],[-3,-1],[-2,-3],[-2,-3],[-2,-2]],[[4135,588],[4,-2],[4,3],[-1,3],[3,4],[3,-5],[22,-5],[7,-5],[-3,-1],[-2,0],[-7,0],[-10,-5],[-12,4],[-21,3],[-6,3],[-5,6],[9,6],[2,-1],[13,-8]],[[4101,595],[-5,-1],[-1,2],[2,3],[3,4],[7,0],[6,-2],[-1,-2],[-1,0],[-10,-4]],[[3162,571],[-3,0],[-2,1],[-1,1],[-1,4],[-14,4],[-1,2],[-1,5],[-3,2],[-17,8],[-2,2],[-1,2],[3,1],[7,-2],[13,0],[3,-1],[3,-1],[14,-1],[7,0],[4,-7],[8,-2],[1,-4],[1,-6],[-11,-5],[-2,-1],[-5,-2]],[[3131,607],[-4,-2],[-21,1],[-7,1],[-3,1],[3,6],[3,2],[2,1],[6,3],[9,1],[6,0],[12,-3],[-3,-2],[-2,-1],[-2,-4],[1,-4]],[[4057,615],[-3,-2],[-68,4],[-3,0],[1,4],[9,1],[5,1],[7,2],[6,3],[2,0],[31,-7],[11,-4],[2,-1],[0,-1]],[[582,587],[-35,-2],[-14,2],[-29,6],[-41,11],[-11,4],[-7,3],[-7,4],[-1,4],[1,7],[1,5],[2,3],[9,4],[4,4],[9,4],[2,4],[4,0],[7,-1],[7,-1],[6,-1],[6,-2],[15,-6],[10,-6],[14,-7],[15,-8],[8,-3],[7,-5],[8,-6],[1,-2],[3,-3],[2,-2],[2,-2],[2,-1],[1,-3],[0,-2],[-1,-2]],[[3046,594],[-6,0],[-12,1],[-12,2],[-3,1],[-5,3],[-1,2],[-1,2],[0,3],[3,11],[6,7],[5,4],[18,9],[2,1],[16,5],[6,2],[10,5],[53,18],[13,3],[5,-2],[3,-2],[-2,-2],[-7,-5],[-3,-4],[-9,-6],[-19,-11],[-13,-8],[-17,-12],[-4,-4],[-8,-9],[1,-4],[-2,-6],[-11,-3],[-6,-1]],[[9656,683],[-4,-4],[-4,-2],[-12,1],[-8,-3],[-10,-2],[-4,2],[-2,4],[-1,5],[0,1],[2,1],[13,-3],[5,-3],[3,0],[8,4],[6,4],[2,3],[2,1],[2,-2],[2,-5],[0,-2]],[[3743,644],[4,0],[15,1],[14,0],[9,-1],[3,-2],[2,-3],[3,-5],[2,-5],[3,-5],[1,-8],[3,-3],[4,-7],[1,-6],[-2,-13],[-2,-5],[-5,-5],[-7,1],[-2,-1],[-3,-1],[-1,0],[-1,-1],[8,-5],[0,-1],[1,-2],[-1,-1],[-1,-1],[-158,-26],[-6,-1],[-6,-3],[-2,-2],[-2,-2],[-122,-5],[-1,0],[-1,1],[-3,5],[-1,8],[1,3],[6,3],[2,2],[11,12],[5,5],[2,5],[2,-1],[5,-2],[3,-1],[7,1],[6,3],[3,2],[3,-1],[1,-2],[1,-1],[16,9],[15,9],[14,11],[8,7],[1,2],[2,3],[-1,3],[-2,2],[-1,1],[-1,0],[-8,2],[3,3],[2,4],[1,4],[1,4],[-1,3],[1,1],[3,2],[2,2],[2,3],[-3,1],[-1,2],[3,5],[2,5],[2,3],[5,6],[17,13],[6,8],[1,2],[39,12],[6,2],[12,1],[6,0],[16,-1],[7,-1],[13,-3],[19,-6],[7,-3],[7,-3],[7,-5],[6,-5],[2,-1],[0,-3],[1,-3],[-1,-3],[-1,-5],[-3,-4],[-31,-4],[-4,-1],[-3,-3],[-1,-3],[3,-2]],[[855,729],[8,-3],[-14,1],[-6,4],[4,2],[4,0],[3,-2],[1,-2]],[[822,727],[-2,0],[-24,5],[-5,1],[8,3],[6,0],[14,-7],[4,0],[-1,-2]],[[9640,730],[11,-4],[27,0],[23,-3],[2,-4],[-6,-3],[-10,-5],[-7,-2],[-5,0],[-12,3],[-14,-1],[-3,-3],[-7,-3],[-9,-5],[-2,4],[-3,4],[-8,9],[-1,2],[5,1],[2,3],[5,4],[-1,2],[-4,3],[-1,2],[2,4],[6,1],[8,-1],[3,-5],[-1,-2],[0,-1]],[[872,748],[-11,0],[-7,1],[-1,5],[1,0],[15,-2],[6,-1],[2,-1],[-1,-1],[-4,-1]],[[855,742],[-2,-1],[-12,0],[-3,1],[-1,1],[-17,1],[-7,4],[-2,2],[3,2],[6,1],[2,2],[15,1],[2,-1],[1,-2],[7,-4],[2,-3],[0,-2],[4,-1],[2,-1]],[[928,751],[-11,-3],[-3,1],[1,4],[-1,2],[-1,1],[1,2],[6,0],[18,-3],[2,-3],[-12,-1]],[[852,765],[11,-1],[7,1],[8,-2],[2,-1],[-1,-1],[-9,-1],[-4,-2],[-5,0],[-7,1],[-6,4],[4,2]],[[827,762],[-12,-1],[-5,1],[-1,2],[1,1],[18,2],[2,-2],[1,-1],[-4,-2]],[[900,769],[1,-1],[-5,1],[-6,3],[-1,1],[3,1],[3,-1],[4,-2],[1,-2]],[[922,770],[-3,-5],[-9,3],[-3,3],[2,3],[4,2],[5,-2],[2,0],[2,-4]],[[925,792],[-5,-1],[-8,4],[-5,3],[-2,2],[0,1],[0,1],[2,1],[11,-2],[7,-9]],[[9526,831],[-5,-7],[-4,0],[-2,1],[4,5],[3,1],[3,1],[1,-1]],[[966,823],[-4,0],[-5,1],[-14,5],[-3,2],[2,2],[5,2],[4,-1],[10,-4],[2,-3],[2,-2],[1,-2]],[[9554,874],[-4,0],[-2,1],[-1,4],[0,2],[8,4],[5,2],[-3,-8],[-1,-1],[-2,-4]],[[1322,896],[-4,-3],[-9,2],[1,2],[8,2],[5,-1],[-1,-2]],[[1359,888],[-3,-1],[-12,3],[-6,0],[-3,2],[-2,1],[-1,2],[-3,2],[6,4],[5,2],[4,0],[1,-3],[9,-2],[8,0],[0,-3],[0,-3],[-3,-4]],[[1462,886],[-4,-1],[-9,3],[-2,2],[-3,3],[-2,1],[0,1],[-1,8],[2,1],[5,-2],[11,-4],[7,-1],[2,-3],[-2,-6],[-4,-2]],[[1757,912],[-14,-2],[-3,2],[-1,2],[0,3],[28,12],[5,-1],[1,-1],[-8,-7],[-4,-2],[2,-1],[0,-1],[-1,-2],[-5,-2]],[[1679,915],[-6,-1],[-2,1],[-1,1],[-1,1],[3,3],[3,1],[1,1],[-4,10],[4,1],[4,1],[8,0],[7,-2],[2,-1],[1,-2],[-3,-6],[-2,-1],[-11,-5],[-3,-2]],[[1651,936],[5,-6],[2,-4],[1,-4],[-20,-10],[-1,0],[-1,-5],[1,-2],[1,0],[0,-2],[-2,-1],[-34,-4],[-16,4],[-2,2],[-1,4],[2,0],[4,1],[-1,2],[-2,2],[-1,3],[5,6],[3,2],[-9,5],[-2,1],[-1,1],[-4,-1],[-4,1],[1,2],[1,4],[4,3],[3,0],[3,0],[13,0],[13,-2],[13,-1],[21,-1],[5,0]],[[4427,928],[-1,-13],[0,-2],[1,-3],[5,-7],[1,-5],[-1,-2],[-2,-3],[-6,1],[-3,1],[0,1],[-4,13],[-2,2],[-3,3],[-13,2],[-12,-1],[3,3],[18,4],[5,3],[3,3],[1,6],[3,6],[5,3],[3,0],[2,-5],[0,-5],[-3,-5]],[[9717,944],[-4,-1],[-5,4],[-1,1],[5,7],[-1,2],[1,2],[2,2],[1,-1],[3,-7],[2,-4],[-3,-3],[0,-2]],[[1491,963],[7,-2],[3,-2],[3,-2],[3,-1],[3,-3],[2,-5],[2,-1],[5,-3],[1,-3],[0,-2],[-9,-1],[-3,1],[-3,-1],[-1,-2],[0,-2],[1,-1],[4,-1],[3,0],[7,1],[2,0],[4,-1],[3,-1],[8,5],[2,1],[2,0],[12,-6],[2,-3],[-1,-1],[-2,-2],[1,-2],[5,-2],[3,-3],[1,-1],[0,-2],[-1,-3],[0,-3],[-3,-2],[-1,0],[-6,2],[-19,1],[-6,1],[-9,6],[-4,1],[-3,1],[-6,5],[-10,4],[-6,4],[0,4],[-1,3],[-1,1],[-1,1],[-4,0],[-3,0],[-2,-1],[-3,-3],[-3,0],[-3,0],[0,1],[0,7],[-3,1],[-2,3],[-1,4],[1,4],[4,5],[4,0],[4,-1],[4,1],[6,1],[8,0]],[[2948,959],[-3,-2],[-2,1],[-3,3],[0,2],[2,2],[1,1],[6,7],[4,0],[4,-1],[-4,-6],[-1,-4],[-4,-3]],[[2096,970],[-3,-3],[-7,1],[-4,4],[-2,6],[-1,2],[2,1],[3,2],[12,-13]],[[2934,973],[-4,-7],[0,-1],[-4,-2],[1,-2],[1,-1],[1,-2],[2,-3],[3,-3],[-2,-5],[-4,-3],[-37,16],[-2,3],[-2,1],[-1,3],[0,3],[1,3],[1,1],[3,2],[4,0],[7,-3],[1,0],[2,3],[4,0],[1,3],[-6,0],[-4,3],[-3,2],[-1,2],[10,3],[25,-4],[4,-1],[1,-2],[2,-3],[-4,-6]],[[2394,984],[-4,0],[-4,2],[0,1],[1,2],[2,0],[5,-3],[1,-2],[-1,0]],[[2468,969],[-6,-2],[-4,1],[1,13],[3,3],[-1,3],[-4,6],[-4,8],[2,2],[9,2],[9,0],[4,-3],[2,-5],[-1,-2],[-3,-6],[3,-1],[1,-4],[-1,-4],[-3,-6],[-3,-3],[-4,-2]],[[2360,998],[-5,0],[-2,1],[2,3],[13,5],[5,3],[1,-1],[0,-1],[3,-5],[0,-2],[-17,-3]],[[4552,998],[-2,-2],[-4,0],[-3,3],[-2,4],[0,3],[1,3],[3,1],[2,-1],[3,-7],[2,-4]],[[6901,1019],[-1,0],[0,3],[4,4],[3,5],[1,1],[4,-5],[-1,-3],[-4,-3],[-6,-2]],[[4652,1027],[-2,-2],[-4,1],[-4,3],[-2,2],[-1,2],[2,3],[1,1],[2,-1],[5,-3],[2,-4],[1,-2]],[[6941,1041],[-3,-7],[-1,0],[-2,5],[1,2],[2,2],[3,-1],[0,-1]],[[2275,1042],[-2,-6],[0,-6],[7,0],[3,11],[6,2],[3,-6],[-3,-6],[2,-3],[2,-2],[3,0],[3,3],[1,2],[1,3],[2,6],[6,5],[13,1],[8,-3],[-5,-9],[-12,-5],[-7,-5],[2,-2],[3,0],[2,0],[7,3],[16,5],[6,3],[2,0],[0,-6],[2,-5],[-1,-9],[-7,-2],[-7,0],[2,-5],[-1,-1],[0,-2],[-18,2],[-3,0],[-3,-2],[-3,1],[-7,3],[-3,0],[-6,-2],[-7,0],[-9,0],[-7,0],[-6,4],[-7,0],[-7,1],[-8,3],[-7,2],[-9,4],[-3,1],[-2,1],[-5,0],[-34,6],[-6,-1],[-3,0],[-3,0],[-7,3],[-1,3],[0,3],[2,1],[3,2],[48,6],[5,2],[4,0],[2,-6],[5,-6],[1,0],[1,1],[5,5],[9,-2],[4,3],[4,4],[9,5],[7,-1],[5,-2],[3,-5]],[[4917,1082],[-3,-1],[-3,0],[-3,2],[-3,3],[0,1],[0,3],[0,1],[4,0],[1,-1],[1,-1],[6,-7]],[[3318,1091],[-3,0],[-4,1],[-3,2],[-1,2],[1,2],[3,1],[5,0],[2,-3],[1,-2],[-1,-2],[0,-1]],[[4929,1108],[3,-2],[5,0],[4,-1],[0,-2],[-3,-3],[-2,-6],[-2,-2],[-7,-6],[-5,-1],[-1,3],[0,3],[1,2],[0,2],[-5,3],[0,3],[-1,2],[-13,7],[-3,1],[1,2],[14,0],[8,-1],[6,-4]],[[2952,1115],[5,-5],[-4,-4],[-15,-7],[-8,-3],[-8,-2],[-38,-7],[-3,0],[-3,1],[-1,1],[-3,6],[1,3],[3,2],[4,2],[6,2],[23,3],[2,2],[2,2],[0,3],[1,3],[2,1],[1,0],[3,-2],[6,-10],[2,2],[1,2],[0,8],[2,1],[5,-2],[3,-3],[0,5],[2,1],[2,0],[3,-1],[4,-4]],[[3312,1111],[-2,0],[-2,1],[-2,4],[0,1],[1,4],[1,1],[10,1],[2,-2],[1,-4],[-2,-2],[-7,-4]],[[4836,1120],[-7,-3],[-1,1],[-3,2],[-4,6],[5,0],[5,3],[3,-1],[0,-1],[2,-7]],[[5084,1118],[-10,-2],[-2,2],[-1,3],[2,2],[12,7],[3,-1],[1,0],[1,-3],[-1,-4],[-1,-2],[-4,-2]],[[4908,1121],[-4,0],[-1,2],[-1,1],[6,8],[3,2],[7,2],[4,-1],[2,-2],[1,-3],[0,-5],[-2,-2],[-15,-2]],[[3008,1137],[1,-2],[6,2],[3,-2],[0,-1],[-3,-5],[-3,-2],[-4,-1],[-2,8],[-1,1],[3,2]],[[6999,1115],[-2,0],[-2,1],[-3,4],[-2,3],[-1,3],[0,7],[2,3],[3,1],[1,-3],[0,-3],[1,-2],[3,-3],[2,-3],[0,-1],[1,-3],[-1,-2],[-2,-2]],[[5125,1124],[-4,-1],[-5,3],[-2,2],[-1,5],[0,2],[1,2],[4,1],[6,-1],[3,-2],[1,-4],[-1,-4],[-2,-3]],[[5745,1130],[-1,-2],[-5,0],[-4,-2],[-3,1],[-10,3],[-1,5],[-1,2],[1,3],[9,8],[3,0],[5,-1],[3,-2],[1,-4],[4,-8],[-1,-3]],[[5036,1137],[-3,-7],[-1,0],[-2,4],[-3,5],[-1,3],[0,4],[2,3],[8,2],[3,-1],[1,-6],[-4,-7]],[[3301,1153],[-4,0],[-2,2],[-1,1],[0,2],[2,2],[5,-1],[1,-5],[-1,-1]],[[2917,1168],[5,-2],[7,-6],[2,-3],[1,-2],[-1,-1],[-3,-2],[-3,-8],[-4,-2],[-12,1],[-13,3],[-1,1],[-1,3],[0,3],[1,4],[2,2],[10,2],[1,1],[1,4],[2,1],[2,0],[4,1]],[[5450,1151],[-2,-3],[-8,5],[-5,1],[-2,1],[-1,4],[0,1],[1,2],[3,3],[5,3],[10,1],[9,-1],[1,-2],[-8,-5],[-3,-10]],[[3000,1169],[-6,-2],[-4,2],[-12,3],[-5,7],[1,4],[2,2],[4,1],[7,-3],[4,-2],[9,-12]],[[3278,1168],[-3,-1],[-2,6],[-2,8],[-7,12],[-2,6],[1,2],[2,0],[6,-2],[3,-2],[4,-5],[5,-4],[0,-4],[0,-4],[-3,-1],[0,-3],[-2,-6],[0,-2]],[[3054,1199],[-1,-7],[5,2],[1,0],[4,-3],[8,-15],[2,-5],[4,-14],[3,-10],[11,-19],[4,-10],[3,-5],[0,-8],[3,-2],[1,-4],[1,-10],[1,-13],[0,-23],[0,-6],[-4,-9],[-2,-6],[-2,-4],[-3,-3],[-14,-13],[-2,-6],[-23,-5],[-14,-3],[-5,3],[-5,0],[-7,0],[-19,-1],[-15,-2],[-1,1],[-2,2],[-1,2],[-4,-1],[-3,1],[-3,2],[-3,4],[-2,2],[0,2],[6,6],[3,2],[4,0],[6,-1],[7,-2],[15,-2],[20,0],[6,0],[6,2],[7,6],[-3,2],[-4,1],[-3,0],[-3,0],[-8,-3],[-6,-2],[-7,-2],[-7,2],[-6,6],[0,2],[22,4],[2,1],[4,2],[1,3],[0,2],[-14,4],[-3,0],[-3,-1],[-7,2],[-7,5],[-5,5],[-3,1],[-2,-2],[-14,-15],[-1,0],[-6,1],[-6,3],[-7,1],[-4,-1],[-1,-1],[4,-3],[3,-3],[1,-3],[-10,-7],[-3,-1],[-4,1],[-2,1],[-3,4],[-3,1],[-6,-1],[-4,0],[-3,2],[-3,2],[-3,2],[-4,3],[-2,2],[-1,3],[0,2],[1,2],[0,2],[0,2],[0,2],[1,2],[6,3],[6,1],[6,-4],[5,-2],[2,0],[0,1],[1,1],[0,2],[-2,4],[0,3],[2,2],[2,1],[2,1],[1,0],[4,-1],[3,-2],[6,-4],[5,-4],[2,0],[1,1],[1,2],[-6,5],[0,2],[0,3],[4,2],[2,0],[10,-3],[6,-1],[5,0],[12,3],[-6,3],[-13,3],[-3,3],[-2,3],[10,3],[10,0],[18,-4],[5,2],[6,6],[3,1],[13,0],[10,2],[1,0],[2,-1],[10,-9],[1,0],[1,2],[0,3],[0,4],[0,3],[-1,2],[-2,0],[-2,-1],[-2,1],[-3,2],[-3,1],[-10,1],[-7,2],[-4,1],[-3,3],[-1,3],[4,7],[14,8],[6,2],[7,1],[3,-1],[8,-3],[1,0],[1,1],[-7,5],[-7,4],[-3,4],[-3,1],[-11,1],[-5,-3],[-3,-1],[-3,1],[-16,7],[-1,1],[-2,3],[-1,2],[-1,3],[0,4],[1,2],[2,9],[2,7],[-1,6],[-3,3],[-3,3],[-4,3],[0,3],[-1,2],[0,4],[1,3],[1,3],[2,2],[3,2],[14,4],[27,5],[3,-3],[4,-5],[1,-2],[2,-11],[0,-2]],[[2485,1221],[-1,0],[-1,0],[-1,0],[0,1],[0,1],[0,1],[0,1],[0,1],[1,0],[1,0],[1,0],[0,-1],[0,-1],[0,-1],[0,-1],[0,-1]],[[3315,1223],[-1,-2],[-4,1],[-2,1],[-3,3],[2,2],[3,-1],[3,-1],[2,-3]],[[3129,1281],[-6,-2],[-4,2],[0,4],[-1,1],[0,1],[5,3],[4,1],[5,-1],[2,-1],[0,-2],[-3,-3],[-1,-2],[-1,-1]],[[9578,1294],[-3,-2],[-1,0],[-2,4],[2,5],[-1,7],[1,2],[4,-4],[0,-2],[2,-3],[0,-2],[-1,-3],[-1,-2]],[[3129,1331],[-2,-1],[-3,1],[-2,1],[3,4],[-1,3],[3,1],[2,-1],[2,-4],[0,-1],[-2,-3]],[[7383,1327],[-5,-1],[0,1],[0,1],[-8,5],[-1,5],[1,3],[6,-1],[7,-2],[3,-7],[-3,-4]],[[6348,1337],[-5,-1],[-2,0],[0,2],[0,1],[0,2],[2,1],[7,0],[4,-1],[0,-1],[1,-2],[-1,-1],[-6,0]],[[9535,1335],[0,-3],[-2,0],[-2,3],[-2,7],[2,1],[2,-2],[1,-3],[1,-2],[0,-1]],[[7403,1338],[-3,-1],[-2,0],[-3,3],[1,2],[3,1],[4,0],[1,-1],[2,-1],[-3,-3]],[[3111,1297],[-3,-3],[-2,-1],[-2,1],[-2,0],[-2,-1],[-1,-6],[-2,-3],[-2,-2],[-1,1],[-2,0],[-2,-1],[-2,-1],[-2,1],[-2,4],[-4,4],[0,1],[-1,4],[0,4],[2,2],[7,10],[2,5],[3,5],[2,4],[4,8],[2,3],[12,8],[3,2],[3,0],[1,-5],[-2,-2],[-5,-5],[-1,-8],[0,-3],[0,-1],[2,-1],[2,-1],[1,-2],[2,-2],[-4,-4],[-3,-2],[-2,-3],[-4,-2],[-2,-2],[3,0],[4,-2],[1,-2],[-1,-2]],[[7370,1347],[-3,-2],[-3,1],[-1,1],[-1,2],[2,3],[1,0],[1,-2],[4,-3]],[[7745,1355],[-3,0],[-2,1],[-2,3],[0,1],[4,1],[6,-3],[-3,-3]],[[9516,1355],[-1,-3],[-2,0],[-6,7],[1,3],[-1,3],[0,2],[1,1],[7,-11],[1,-2]],[[7784,1370],[-3,-1],[-2,2],[3,4],[3,1],[0,-4],[-1,-2]],[[3150,1371],[-6,-7],[-1,1],[-1,0],[0,1],[2,3],[1,7],[4,2],[1,0],[-1,-3],[1,-3],[0,-1]],[[7683,1380],[3,-1],[6,0],[2,-2],[0,-3],[0,-1],[-2,-2],[-15,-2],[-3,3],[3,6],[3,2],[3,0]],[[7572,1393],[-4,0],[-4,0],[-2,3],[0,1],[1,2],[6,0],[3,-1],[1,-2],[0,-1],[-1,-2]],[[3171,1391],[-6,-2],[-4,1],[0,2],[1,3],[3,2],[-1,5],[2,1],[1,4],[4,3],[5,-2],[0,-4],[0,-2],[-4,-1],[0,-1],[-1,-3],[0,-4],[0,-2]],[[7804,1401],[-12,-1],[-1,1],[-4,0],[-2,1],[0,3],[1,5],[2,3],[4,3],[2,1],[8,1],[5,-1],[4,-4],[1,-3],[-1,-3],[-7,-6]],[[7871,1414],[-1,-1],[-5,1],[-1,1],[0,5],[-1,2],[-1,1],[-8,3],[0,4],[1,2],[2,0],[7,-3],[2,-3],[-1,-4],[0,-1],[3,-3],[3,-3],[0,-1]],[[3241,1448],[-4,-3],[-3,0],[3,7],[2,0],[5,3],[1,0],[-2,-3],[-2,-4]],[[3410,1465],[-3,0],[-3,1],[0,3],[0,2],[2,1],[2,0],[8,5],[3,1],[-1,-2],[0,-3],[-1,-2],[-7,-6]],[[3245,1470],[-3,-6],[4,1],[3,2],[3,1],[2,-3],[-5,-3],[-5,-4],[-2,-2],[-2,-1],[-3,1],[-3,-1],[-2,-4],[-3,-2],[-1,2],[-1,1],[-5,1],[-3,2],[-2,2],[-3,0],[2,4],[1,3],[9,4],[-1,1],[-1,2],[7,2],[0,2],[0,3],[2,1],[2,3],[1,0],[4,0],[3,-3],[-1,-3],[3,-6]],[[3268,1473],[-2,-2],[-1,-1],[-2,1],[-2,-3],[-4,1],[-1,1],[1,0],[0,2],[3,3],[3,8],[1,2],[-3,4],[-1,2],[1,2],[1,2],[3,2],[3,0],[2,-2],[0,-3],[6,-2],[-1,-6],[-2,-4],[-1,-4],[-3,-2],[-1,-1]],[[3279,1493],[-3,0],[1,3],[2,2],[4,1],[-2,-3],[-1,-2],[-1,-1]],[[3393,1494],[1,0],[1,0],[1,1],[1,2],[3,2],[3,1],[-1,-3],[7,-5],[0,-4],[1,-3],[-3,-1],[-2,-4],[2,-1],[1,-3],[-2,0],[-6,1],[-3,0],[1,3],[-1,1],[-4,-1],[-1,-6],[-1,0],[-1,1],[1,3],[-2,1],[-1,0],[-4,-3],[-1,0],[-3,3],[8,5],[-3,2],[-1,2],[0,4],[-2,-1],[-3,-1],[-1,0],[-2,1],[1,3],[2,4],[2,4],[4,3],[2,1],[2,1],[2,2],[2,0],[2,-4],[0,-2],[-2,-3],[0,-6]],[[3406,1509],[0,-1],[6,0],[1,-1],[-3,-2],[-1,0],[-2,-1],[-8,2],[-2,2],[7,2],[2,-1]],[[3315,1505],[-4,-2],[-2,1],[-3,2],[5,1],[0,7],[2,3],[4,-2],[-2,-4],[-1,-2],[1,-3],[0,-1]],[[3448,1524],[-3,-2],[-6,4],[-1,2],[0,2],[10,2],[3,-1],[1,-4],[-4,-3]],[[0,325],[45,1],[9,-1],[9,-2],[21,0],[19,-2],[5,-3],[7,-2],[13,2],[11,1],[9,0],[82,-5],[85,-8],[17,-2],[15,-6],[17,0],[95,-4],[15,0],[59,-5],[102,-12],[9,0],[10,0],[-5,6],[-10,6],[-13,4],[9,1],[18,0],[-4,3],[-10,2],[-36,2],[-147,14],[-3,1],[-2,1],[-4,1],[-6,2],[-22,1],[-6,1],[-3,2],[1,0],[2,0],[34,1],[4,2],[0,1],[-2,1],[-5,1],[-14,5],[-5,2],[3,3],[2,1],[11,1],[3,3],[-2,4],[-24,8],[-16,3],[-11,-2],[-20,0],[-25,-2],[-7,2],[-7,3],[-8,5],[-5,2],[-7,5],[-11,4],[-56,11],[-10,3],[-70,18],[-3,3],[-2,3],[32,-7],[7,0],[7,2],[5,-1],[8,2],[8,1],[22,-6],[44,-8],[12,-4],[6,-2],[6,0],[5,-2],[6,1],[4,-1],[9,1],[42,1],[16,-1],[20,-5],[8,-7],[5,-3],[11,3],[9,3],[17,2],[6,-1],[9,-4],[10,-6],[45,2],[19,0],[13,-3],[48,9],[8,2],[11,7],[-9,2],[-7,0],[-2,4],[4,1],[14,2],[28,3],[16,2],[8,7],[37,11],[12,5],[11,8],[-25,16],[-23,13],[8,4],[7,4],[3,2],[3,4],[-7,4],[-7,4],[-12,3],[-44,8],[-15,3],[6,5],[8,4],[17,2],[108,6],[108,7],[3,4],[-14,4],[-13,1],[-4,2],[-2,2],[0,4],[-1,1],[-5,0],[-19,5],[-5,1],[-6,4],[-2,4],[4,8],[6,3],[11,2],[7,1],[23,0],[8,1],[4,1],[-1,4],[-2,2],[0,2],[4,1],[4,0],[2,3],[-3,5],[-7,2],[-17,5],[-40,6],[-16,5],[-9,4],[-7,4],[-8,2],[-5,3],[1,2],[-2,5],[-3,1],[-13,-2],[-22,1],[-28,4],[-19,5],[-26,12],[-9,7],[7,4],[8,3],[33,6],[5,2],[7,6],[-11,3],[-10,-1],[-8,2],[-34,0],[-20,0],[-16,7],[-12,7],[-3,4],[-3,6],[4,9],[4,7],[-1,8],[1,12],[6,3],[4,1],[11,-9],[9,0],[13,1],[8,5],[5,2],[8,0],[15,-2],[8,1],[8,-1],[25,-5],[5,-3],[3,-2],[1,-3],[3,-3],[11,-2],[30,2],[8,-1],[21,-8],[18,-9],[6,-3],[10,-1],[4,1],[3,4],[10,4],[21,5],[5,5],[-2,3],[-9,3],[-5,1],[-3,3],[1,5],[1,5],[6,1],[10,-6],[13,-6],[5,-1],[3,0],[7,2],[8,2],[15,-12],[8,-1],[11,0],[2,1],[-1,4],[-2,3],[-2,1],[0,3],[5,3],[3,1],[-2,2],[-5,4],[-3,0],[-3,2],[1,2],[4,1],[5,3],[-2,4],[0,5],[-2,3],[-11,5],[-17,9],[-16,4],[-35,-3],[-12,2],[-8,2],[-9,3],[10,3],[11,3],[3,2],[4,4],[5,3],[4,0],[13,-1],[29,-11],[6,-1],[20,-5],[5,0],[7,1],[-6,5],[-6,3],[-14,10],[1,4],[10,8],[24,0],[11,3],[14,6],[18,9],[15,2],[19,3],[7,-3],[16,-9],[10,-3],[4,0],[4,0],[-10,11],[6,2],[8,1],[7,3],[5,3],[17,11],[15,3],[42,5],[15,-5],[12,0],[3,1],[2,6],[7,11],[5,4],[19,5],[14,0],[11,-5],[9,-3],[9,-2],[9,0],[14,3],[17,1],[9,1],[9,-2],[24,-1],[18,-4],[12,0],[15,4],[8,0],[30,6],[24,1],[17,-2],[29,1],[29,-1],[11,-2],[66,1],[51,6],[8,2],[11,6],[6,5],[4,2],[9,1],[14,-2],[21,-4],[18,2],[33,-3],[3,2],[4,11],[5,16],[5,5],[8,-1],[23,-10],[0,-4],[-2,-2],[-4,-2],[-1,-8],[3,-2],[5,1],[4,-4],[-8,-6],[-5,-3],[-3,-2],[-2,-11],[-4,-4],[0,-4],[5,0],[5,2],[4,0],[14,3],[26,4],[8,1],[5,1],[3,2],[-4,6],[-1,5],[2,3],[-1,7],[-2,7],[5,5],[5,-1],[7,1],[5,-3],[7,-2],[6,-1],[7,-5],[2,-9],[-2,-10],[-7,-8],[-12,-6],[-13,-11],[3,-5],[7,2],[31,-1],[19,1],[13,-1],[16,-3],[12,-4],[15,0],[9,1],[9,-2],[34,9],[14,4],[8,-2],[12,2],[8,-2],[13,3],[8,0],[10,-1],[30,0],[2,-6],[9,-8],[7,-3],[9,1],[7,3],[11,-1],[15,3],[15,-1],[7,1],[3,2],[2,5],[-5,3],[-13,3],[-12,8],[-6,1],[-9,-1],[-4,2],[-4,2],[6,3],[7,9],[-3,9],[-4,2],[-8,-1],[-9,-3],[-4,2],[-7,2],[-2,7],[-7,15],[-4,4],[-10,4],[-10,2],[-9,2],[-3,6],[2,8],[11,2],[10,-1],[6,-2],[7,0],[8,-2],[5,-2],[4,-1],[7,-1],[26,3],[4,1],[3,3],[5,1],[5,-1],[8,2],[-9,2],[-9,5],[-14,5],[-11,3],[-21,2],[-11,-1],[-6,1],[-24,0],[-7,2],[-4,5],[-7,14],[-2,8],[5,2],[3,3],[7,0],[10,-1],[3,-1],[3,-4],[-3,-5],[-3,-2],[2,-2],[11,-1],[5,-1],[4,-1],[10,2],[14,1],[7,-2],[9,-1],[12,2],[45,-1],[5,-1],[6,-4],[4,-2],[5,1],[15,-5],[7,-3],[8,-2],[7,-1],[7,1],[10,3],[8,1],[6,-1],[12,0],[10,-4],[7,2],[8,4],[24,3],[17,-1],[29,-8],[7,0],[14,4],[4,7],[0,8],[4,2],[3,-1],[6,6],[8,0],[5,-2],[3,4],[3,8],[10,0],[7,-1],[9,-5],[0,-4],[-4,-4],[-6,-11],[4,-6],[6,0],[7,-1],[9,3],[6,0],[10,-9],[7,-1],[5,1],[17,8],[5,1],[6,-4],[9,-9],[8,-5],[12,-3],[9,-1],[12,-4],[6,-4],[15,0],[6,-1],[18,-7],[16,3],[8,4],[4,6],[-2,9],[-1,9],[3,4],[4,1],[19,-11],[-1,6],[-2,5],[-5,8],[1,6],[4,2],[8,-3],[10,-2],[8,-3],[15,-13],[5,-11],[11,-3],[7,1],[8,1],[11,2],[9,0],[8,2],[2,-7],[-7,-8],[-3,-6],[2,-2],[5,2],[4,2],[13,-1],[10,4],[9,1],[8,4],[7,0],[5,-1],[8,-3],[7,2],[4,-1],[5,0],[30,14],[7,0],[8,1],[11,3],[8,2],[7,0],[12,5],[19,-1],[10,3],[19,3],[13,4],[23,10],[9,6],[10,13],[6,12],[7,18],[-3,11],[-4,5],[-3,5],[-7,11],[-2,14],[1,13],[-3,12],[-3,9],[-5,16],[-7,10],[-7,13],[0,12],[-2,9],[-5,7],[-2,6],[4,1],[3,1],[9,2],[21,-3],[2,5],[6,4],[3,5],[-1,8],[-5,3],[-5,7],[2,5],[5,0],[2,5],[-2,6],[2,7],[5,9],[2,3],[-5,6],[-5,7],[2,5],[2,6],[3,8],[4,6],[3,1],[-1,2],[-6,2],[-6,1],[-10,-4],[-2,1],[0,2],[-1,4],[1,9],[2,9],[1,1],[4,2],[4,6],[4,1],[2,-2],[1,-10],[1,-2],[-1,-4],[2,-2],[2,3],[4,2],[2,-3],[2,-2],[0,3],[0,7],[-1,3],[0,5],[0,2],[1,4],[-1,8],[0,3],[4,4],[2,1],[3,0],[7,-3],[3,0],[2,1],[1,3],[1,10],[-2,4],[0,3],[1,2],[3,7],[4,0],[4,-1],[4,2],[-1,2],[-1,5],[4,2],[3,0],[8,-2],[3,-2],[3,4],[-1,3],[-3,2],[-1,3],[1,4],[5,-2],[1,1],[1,3],[-1,2],[0,2],[6,0],[1,1],[1,3],[2,1],[6,0],[1,1],[1,3],[-4,1],[-4,3],[0,8],[1,6],[3,5],[5,3],[7,-3],[6,1],[3,-3],[3,-1],[1,3],[-2,3],[-1,5],[10,6],[3,-1],[4,1],[-2,5],[2,6],[3,0],[2,-4],[3,-2],[3,2],[7,5],[3,1],[4,1],[3,3],[1,4],[2,3],[6,4],[3,2],[5,10],[-1,2],[2,2],[16,9],[8,1],[14,5],[8,6],[5,2],[4,7],[6,1],[13,5],[9,8],[14,5],[6,0],[2,-2],[2,-6],[2,-8],[4,-4],[-1,-3],[-4,0],[-4,-1],[-1,4],[2,3],[-2,3],[-4,-1],[-4,-1],[-4,-2],[-4,-4],[-3,-3],[-12,-6],[-7,-9],[-6,-9],[-3,-6],[-4,-1],[-2,-2],[2,-2],[2,-1],[3,0],[0,-3],[-3,-1],[1,-2],[2,-3],[1,-5],[-3,0],[-5,5],[-5,0],[-3,2],[-3,4],[-2,-1],[-2,-5],[1,-5],[-2,-3],[-3,1],[0,7],[-3,1],[-3,0],[-8,-7],[-2,0],[-2,-4],[-4,-3],[-3,-3],[-7,-11],[-4,-4],[-8,-2],[-3,0],[-2,1],[-3,1],[-2,0],[-1,-3],[4,-9],[-2,-3],[-6,0],[-2,3],[-2,-2],[-2,-3],[-2,-3],[3,-7],[4,-4],[3,0],[1,-3],[-6,-1],[-5,-6],[-2,-5],[-2,-4],[0,-4],[4,-7],[4,-4],[5,-1],[6,2],[1,1],[6,1],[3,4],[2,1],[1,-1],[3,0],[2,3],[2,1],[2,-1],[6,0],[1,-3],[-1,-3],[-4,-4],[-3,3],[-3,-1],[-1,-2],[3,-5],[-1,-4],[-3,-4],[-2,3],[-1,4],[-4,3],[-4,1],[-2,-5],[-5,-1],[0,-5],[-2,-5],[-2,1],[-1,6],[-7,5],[-3,1],[-7,-1],[-3,0],[-2,-1],[-3,-5],[3,-3],[1,-4],[0,-3],[0,-1],[-1,-3],[3,-3],[1,-5],[-3,0],[-2,1],[-8,13],[-5,6],[-2,5],[-6,1],[-4,0],[-4,-2],[2,-2],[1,-4],[-3,-1],[-4,-6],[-2,-5],[-2,-1],[-1,-2],[7,-7],[1,-2],[1,-4],[-3,-2],[-5,-1],[-10,4],[-4,0],[-2,3],[-2,0],[-2,-5],[-1,-5],[-2,-3],[0,-4],[2,-1],[-1,-2],[-4,-2],[-2,-2],[5,-1],[1,-2],[0,-2],[-7,-2],[-5,0],[-3,2],[-2,-1],[-2,-3],[0,-4],[0,-5],[1,-3],[1,-1],[1,-3],[-5,-8],[0,-1],[-1,-4],[2,-3],[2,-4],[-2,-3],[-3,-4],[3,-1],[4,-1],[5,1],[7,4],[2,1],[1,-2],[1,-2],[-2,-3],[-13,-6],[-2,-3],[3,-2],[7,0],[2,-2],[-1,-3],[-3,-2],[-3,-5],[3,-2],[7,-4],[13,-4],[10,-1],[-2,5],[-1,6],[7,4],[4,2],[16,3],[4,0],[4,-1],[-2,-3],[-4,1],[-6,-2],[-10,-5],[-2,-2],[1,-4],[8,-4],[3,-3],[-4,-8],[1,-5],[4,-6],[6,-6],[3,-4],[4,-3],[7,-6],[4,-6],[1,-14],[6,-12],[7,-5],[0,-5],[-2,-4],[-6,2],[-3,-2],[-1,-5],[4,-4],[6,-4],[14,1],[1,-5],[-4,-3],[-2,-3],[-3,-2],[-5,-1],[-2,-4],[3,-6],[7,3],[5,0],[6,-1],[1,-8],[7,-9],[1,-5],[-1,-4],[-4,-1],[-2,-4],[-4,-3],[-4,-1],[-8,-8],[-3,-1],[-1,-2],[6,0],[5,-1],[9,7],[4,-2],[2,-4],[2,-5],[-3,-4],[-17,-2],[-8,-3],[-9,-6],[10,-3],[8,1],[4,-1],[5,-3],[5,1],[5,3],[3,0],[3,-1],[0,-5],[1,-7],[1,-5],[-2,-4],[-9,-2],[-7,0],[0,-8],[10,-6],[6,3],[5,-1],[0,-9],[4,-10],[4,-1],[3,5],[4,0],[1,-6],[-1,-9],[-3,-5],[-8,2],[-5,2],[-3,-3],[-6,-3],[-5,-1],[-4,5],[-6,3],[-8,2],[-8,1],[3,-4],[3,-3],[2,-7],[3,-7],[6,2],[9,-4],[6,-4],[2,-6],[-3,-9],[-5,-3],[-3,-2],[-6,4],[-4,0],[-4,-2],[-1,-4],[-3,-2],[14,-1],[5,-1],[3,-4],[-5,-4],[-10,0],[-4,-2],[-3,-3],[14,-2],[6,1],[9,4],[2,-4],[-3,-4],[-5,-6],[-10,-2],[-8,0],[-9,2],[-3,1],[-4,1],[0,-4],[3,-2],[6,-10],[1,-3],[-2,-5],[-5,-4],[-7,-1],[-5,3],[-4,9],[-5,3],[-5,0],[-3,0],[0,-5],[1,-4],[-2,-4],[-4,2],[-6,-2],[-5,-2],[-5,-3],[10,-2],[6,0],[5,-5],[-2,-2],[-9,-1],[-8,-2],[-12,-5],[9,-2],[8,0],[5,0],[5,-1],[2,-3],[-3,-3],[-20,-7],[-20,-10],[-7,-2],[-8,-2],[-18,-8],[-11,-3],[-32,-6],[-49,-14],[-17,-10],[-5,-7],[-4,-2],[-9,-2],[-10,-1],[-25,-1],[-25,4],[-21,0],[-12,-1],[-38,7],[-5,0],[-6,-2],[-5,0],[-3,1],[-8,1],[-26,-3],[-3,-4],[3,-8],[10,-9],[16,-16],[8,-4],[6,-3],[10,-5],[22,0],[31,-3],[17,-3],[-1,-6],[-10,-12],[-7,-4],[-15,-8],[-21,-4],[-17,1],[-29,7],[-36,6],[-54,5],[-11,3],[-14,2],[-8,-2],[-6,-3],[-13,0],[3,-2],[54,-16],[46,-11],[5,-3],[7,-2],[-1,-7],[-2,-6],[-9,-5],[-24,0],[-29,-4],[-15,0],[-14,4],[-31,11],[-19,8],[-13,10],[-9,8],[-10,7],[0,-5],[2,-4],[5,-6],[7,-6],[1,-3],[-4,0],[-5,3],[-4,-3],[-2,-3],[2,-5],[3,-4],[9,-9],[8,-3],[11,-6],[25,-10],[5,-4],[8,-8],[1,-6],[8,-5],[5,-1],[5,0],[1,5],[0,6],[2,2],[7,1],[20,-2],[82,-1],[8,-4],[3,-4],[2,-10],[-9,-11],[-6,-5],[-10,-2],[-8,-3],[-14,-1],[-27,1],[-27,0],[21,-5],[20,-5],[28,1],[12,1],[9,2],[4,-3],[8,-8],[5,-3],[3,-2],[4,-9],[2,-5],[4,-5],[3,-5],[4,-4],[8,-1],[8,3],[16,1],[15,-5],[10,-1],[13,4],[11,5],[22,5],[4,2],[6,1],[9,0],[4,-1],[4,-5],[5,-7],[6,-4],[7,-2],[3,-1],[13,-2],[16,2],[8,-2],[1,-4],[4,-3],[5,-1],[66,-18],[23,-4],[35,-2],[28,0],[4,-1],[5,-3],[-11,-3],[-11,0],[-17,1],[-6,-1],[-13,1],[-6,0],[-6,1],[-9,-3],[-17,-2],[4,-2],[6,-1],[12,-1],[18,1],[1,-5],[-16,-1],[-33,-1],[-4,0],[-2,-3],[5,-1],[3,-1],[1,-3],[-3,-8],[5,-5],[4,-1],[4,1],[7,-3],[7,-3],[15,0],[17,4],[9,0],[23,3],[20,-1],[29,5],[5,0],[4,-1],[-8,-4],[-35,-11],[-13,-2],[-5,-2],[3,-5],[5,-6],[9,-6],[6,-9],[6,-1],[11,4],[2,-3],[1,-7],[-3,-4],[-4,-3],[-3,-3],[-1,-4],[4,-3],[13,-1],[16,-1],[15,0],[9,-1],[35,19],[13,10],[7,3],[6,3],[28,12],[7,4],[8,5],[14,1],[19,9],[17,6],[7,1],[5,1],[6,1],[15,0],[11,1],[19,4],[14,3],[16,2],[17,1],[46,4],[13,-2],[15,-5],[10,1],[12,1],[9,2],[4,-6],[2,-6],[-5,-7],[-7,-4],[-1,-6],[9,-4],[11,1],[20,4],[17,4],[4,2],[7,0],[11,3],[13,15],[17,14],[15,10],[9,11],[8,6],[8,5],[6,2],[13,1],[19,7],[28,9],[21,-4],[22,-6],[11,5],[9,1],[7,2],[8,2],[5,4],[7,4],[5,5],[27,3],[29,4],[4,1],[3,-1],[10,1],[13,3],[17,1],[9,0],[8,8],[16,2],[18,3],[7,2],[6,1],[141,6],[6,3],[13,3],[4,6],[-19,3],[-5,2],[-7,1],[-4,-1],[-16,1],[-130,9],[-3,1],[-5,6],[1,10],[-4,8],[-9,2],[-9,0],[-12,-1],[-31,-4],[-13,-1],[-33,7],[-22,8],[-15,2],[-10,6],[-10,4],[-1,9],[3,8],[18,25],[12,12],[8,0],[7,6],[7,12],[6,5],[14,7],[5,2],[22,8],[5,0],[10,-1],[11,7],[33,15],[7,6],[9,4],[27,13],[24,6],[11,2],[15,4],[16,6],[14,6],[49,11],[30,3],[21,3],[14,-2],[14,1],[13,2],[5,3],[8,6],[28,-3],[18,4],[7,0],[8,2],[-3,2],[-3,0],[-3,3],[-3,6],[3,7],[3,4],[8,4],[5,7],[4,9],[13,19],[4,2],[9,1],[7,0],[8,0],[21,-5],[4,2],[7,5],[5,7],[12,10],[3,3],[-1,5],[-18,-2],[-14,-3],[-13,1],[-2,3],[3,2],[5,1],[2,3],[-5,3],[-8,2],[-3,2],[0,5],[2,8],[4,2],[4,3],[10,10],[5,4],[17,2],[19,-4],[4,1],[5,6],[-5,9],[-4,4],[0,2],[10,-1],[10,-2],[11,0],[12,9],[19,8],[8,3],[8,2],[4,7],[7,15],[4,7],[0,5],[-1,4],[-5,-1],[-4,-1],[-10,4],[-13,6],[-4,7],[-2,6],[4,3],[4,2],[4,1],[8,-3],[9,-6],[5,-2],[5,-5],[4,0],[4,7],[4,8],[3,3],[5,3],[6,4],[-3,4],[-5,2],[-1,2],[2,3],[5,1],[6,-6],[8,-4],[5,-1],[5,-4],[7,-10],[9,-18],[4,-1],[8,2],[9,1],[5,5],[1,13],[3,5],[-1,6],[-4,6],[-3,5],[0,3],[3,2],[4,1],[6,3],[10,-3],[6,-1],[8,2],[8,3],[9,3],[6,-2],[3,-6],[-3,-7],[-5,-5],[-5,-6],[-2,-6],[1,-3],[4,-1],[42,0],[5,0],[8,0],[7,-2],[14,1],[11,2],[6,0],[10,-2],[7,-5],[14,2],[4,1],[4,6],[4,1],[5,-5],[1,-11],[2,-5],[6,-5],[6,4],[4,5],[10,9],[10,8],[9,4],[20,7],[10,4],[19,6],[25,3],[45,11],[14,1],[24,3],[13,3],[12,2],[8,8],[17,-6],[6,0],[8,4],[9,12],[14,-5],[7,-7],[9,-6],[21,-11],[7,-2],[14,-2],[3,1],[7,7],[6,10],[5,5],[6,3],[7,6],[-2,3],[-4,1],[-4,1],[1,3],[12,1],[7,-10],[6,-4],[8,-3],[19,3],[16,0],[14,-2],[7,0],[6,8],[9,3],[6,-4],[4,-11],[12,-3],[27,-5],[3,1],[3,6],[2,7],[6,1],[7,4],[3,0],[6,-5],[-2,-11],[-3,-11],[3,-8],[4,-5],[4,-1],[6,0],[8,0],[6,0],[26,4],[3,10],[4,10],[10,14],[4,-1],[4,-1],[7,-7],[4,-3],[1,-5],[-5,-5],[1,-3],[5,-3],[15,-4],[4,1],[8,4],[7,9],[4,10],[6,-1],[6,-2],[4,-5],[0,-10],[5,-6],[5,-4],[12,-5],[13,-1],[9,-3],[15,1],[7,3],[4,1],[8,2],[9,6],[5,2],[19,6],[15,5],[15,11],[15,6],[23,3],[6,1],[9,0],[22,7],[8,4],[5,2],[5,5],[3,10],[2,7],[-1,6],[-2,8],[-4,7],[-5,10],[2,12],[4,5],[9,5],[10,1],[11,0],[9,-1],[1,-5],[-4,-6],[-5,-5],[-3,-3],[1,-4],[6,-1],[15,1],[5,-4],[10,-19],[3,-8],[4,-3],[5,1],[13,0],[9,2],[7,0],[3,-1],[4,-4],[7,-5],[8,3],[5,2],[6,0],[10,-6],[10,-13],[11,-7],[0,4],[-1,6],[4,4],[6,8],[7,10],[6,11],[2,15],[3,11],[5,6],[4,4],[8,4],[9,0],[9,9],[6,3],[13,5],[16,5],[12,13],[4,2],[6,2],[10,0],[18,5],[5,0],[9,4],[8,7],[6,3],[10,-1],[9,5],[7,0],[7,2],[1,5],[-3,3],[0,5],[4,5],[3,2],[9,0],[7,-5],[6,0],[1,-3],[-5,-3],[-3,-6],[6,-6],[5,-3],[5,0],[8,4],[7,-3],[3,-5],[0,-7],[1,-4],[5,3],[3,8],[-1,10],[0,6],[12,9],[5,8],[-9,1],[-5,-1],[-4,3],[-3,7],[10,6],[11,0],[7,-5],[14,-8],[8,0],[8,-1],[1,2],[-3,12],[1,7],[-6,4],[-2,9],[2,9],[8,5],[9,2],[21,14],[6,3],[13,3],[16,1],[20,5],[36,-3],[9,-2],[6,-3],[6,-4],[7,-8],[11,-9],[14,-3],[4,-3],[5,-8],[-6,-5],[-4,-1],[-9,3],[-6,4],[-4,-2],[4,-5],[4,-4],[1,-4],[-2,-7],[-17,-13],[10,-4],[6,3],[6,6],[5,2],[4,1],[13,1],[7,2],[6,-2],[5,-3],[8,-4],[12,-4],[14,-14],[11,1],[6,3],[17,2],[15,-7],[8,-2],[24,-2],[15,-5],[9,5],[6,2],[13,1],[6,-1],[18,-5],[32,-6],[21,-2],[19,-1],[9,-2],[17,-2],[6,-3],[16,2],[8,2],[7,5],[4,-1],[2,-6],[-1,-10],[3,-7],[2,-7],[3,-6],[2,-5],[-1,-4],[-5,-3],[-6,-8],[0,-7],[3,-5],[-3,-5],[2,-7],[0,-5],[-2,-3],[-5,-3],[-8,0],[-5,-2],[0,-6],[2,-4],[5,-2],[1,-4],[-1,-7],[-2,-5],[-4,-3],[-5,-1],[-9,2],[-7,3],[-4,-3],[-3,-3],[-10,-8],[-4,-5],[-4,-6],[11,-3],[8,-5],[17,0],[5,3],[8,2],[3,0],[3,-6],[-2,-9],[0,-7],[-9,-19],[-2,-3],[-4,-5],[-5,-4],[-4,-2],[-8,-6],[-4,-11],[-5,-9],[-8,-15],[-4,-17],[-2,-10],[-2,-10],[-7,-18],[-4,-3],[-7,-7],[2,-5],[6,0],[7,-2],[8,-3],[12,7],[6,5],[2,10],[-2,9],[4,6],[9,8],[20,6],[5,0],[6,2],[6,7],[6,7],[9,5],[8,7],[1,5],[3,1],[10,5],[2,4],[3,2],[2,7],[1,12],[2,8],[5,12],[4,9],[4,5],[10,3],[4,3],[6,8],[3,4],[0,9],[2,8],[6,5],[8,10],[10,1],[7,5],[8,-4],[10,-4],[16,1],[7,-2],[6,3],[5,7],[2,8],[7,5],[6,0],[12,9],[12,8],[9,1],[8,7],[5,10],[6,8],[8,7],[2,13],[4,7],[9,6],[7,3],[30,10],[22,7],[24,8],[7,0],[9,4],[15,1],[4,0],[6,9],[11,9],[7,3],[9,7],[7,1],[11,-2],[8,-2],[8,0],[11,7],[18,1],[5,3],[4,2],[25,9],[9,-2],[14,2],[8,-1],[7,-1],[10,0],[16,3],[7,2],[14,8],[14,1],[7,2],[8,2],[6,-3],[5,-3],[3,0],[4,-1],[10,3],[8,0],[10,-4],[6,-2],[4,0],[6,2],[8,6],[7,2],[6,-1],[5,-3],[8,-3],[13,1],[12,1],[10,3],[8,3],[8,-5],[10,-2],[15,8],[5,-1],[4,-2],[3,-2],[4,-6],[15,1],[12,6],[11,4],[10,3],[9,4],[12,15],[0,4],[1,3],[3,1],[19,0],[6,1],[8,4],[14,-3],[13,-5],[4,1],[5,0],[9,-3],[11,-6],[9,-1],[38,-14],[22,-4],[11,-5],[3,-1],[3,-5],[6,0],[5,1],[6,-7],[14,-5],[16,-3],[10,4],[17,13],[5,5],[-1,12],[9,14],[15,7],[19,3],[12,3],[15,3],[7,-3],[4,-2],[6,-3],[7,-7],[10,-17],[8,-7],[7,0],[6,-1],[6,-4],[9,-12],[-5,-11],[-5,-4],[-19,-5],[-9,-3],[-7,-2],[-3,-9],[4,-5],[8,2],[9,1],[8,2],[6,3],[6,4],[14,2],[9,3],[9,2],[5,4],[6,0],[6,-4],[4,0],[13,-1],[6,3],[5,0],[5,-2],[5,-3],[6,0],[7,1],[10,5],[12,4],[12,2],[3,0],[2,-1],[-12,-6],[-18,-7],[-10,-7],[5,-3],[36,8],[16,6],[14,2],[3,2],[12,9],[4,3],[13,3],[16,3],[12,4],[9,4],[6,1],[5,-3],[6,-3],[6,0],[8,3],[5,8],[3,5],[6,2],[7,1],[6,-1],[10,-4],[7,-2],[5,-15],[14,-14],[5,-3],[12,1],[13,-5],[5,1],[5,1],[5,-1],[7,3],[7,17],[7,16],[7,7],[4,4],[5,1],[7,3],[11,1],[7,-1],[17,-1],[14,4],[15,-1],[8,5],[8,1],[11,-5],[3,-2],[6,-5],[2,-4],[1,-7],[3,0],[11,7],[5,1],[11,12],[6,-3],[12,-5],[5,-2],[10,-8],[5,2],[5,4],[12,-1],[12,-3],[4,-3],[6,-5],[4,-1],[3,1],[24,-2],[10,-3],[8,-5],[28,-2],[11,-5],[6,3],[13,-1],[5,-4],[5,-4],[10,-4],[5,1],[8,3],[8,4],[8,0],[3,-4],[2,-9],[5,1],[7,4],[5,-1],[2,-6],[-3,-9],[-7,-11],[-3,-9],[-6,-9],[1,-4],[6,-2],[6,6],[14,4],[6,6],[12,2],[12,-2],[8,-8],[16,-12],[0,-4],[2,-5],[-1,-4],[-2,-5],[8,-5],[7,-1],[6,1],[25,-6],[12,2],[10,0],[13,1],[10,0],[7,-1],[9,2],[8,2],[3,-1],[2,-14],[0,-8],[5,-3],[4,3],[3,4],[20,-2],[7,0],[8,-2],[7,-5],[8,2],[4,3],[6,2],[1,5],[1,9],[0,8],[3,1],[4,-1],[4,-4],[11,-12],[8,-8],[3,-4],[5,-3],[10,-8],[14,-3],[13,-6],[15,0],[13,-7],[8,6],[4,1],[6,-2],[8,-5],[6,-1],[20,-8],[12,-4],[4,-6],[5,-6],[0,-6],[2,-8],[13,-6],[4,-6],[6,-7],[11,-30],[6,-5],[8,1],[7,-8],[3,1],[0,3],[-7,20],[0,11],[5,6],[13,1],[10,-11],[9,-7],[6,-1],[12,0],[11,8],[8,-3],[14,-1],[18,-4],[8,0],[14,-1],[16,-7],[10,-2],[2,-2],[4,-4],[2,-5],[3,-5],[6,-5],[5,-1],[12,-5],[24,-13],[9,-4],[5,-3],[2,4],[1,7],[4,1],[5,-10],[5,-9],[2,-7],[-5,-5],[-7,1],[-6,0],[-5,-10],[-2,-16],[5,0],[3,1],[1,-6],[-2,-5],[-4,-2],[-8,4],[-9,3],[-11,1],[-9,5],[-4,0],[-4,0],[5,-6],[5,-4],[13,-4],[15,-6],[1,-4],[-4,-5],[-4,-10],[-15,-8],[-8,6],[-10,1],[-5,-3],[-9,0],[-20,-1],[-7,7],[-12,5],[0,-4],[10,-13],[11,-3],[11,-3],[3,-4],[-5,-3],[-7,1],[-8,-6],[-16,1],[-7,-1],[-5,-2],[-4,-1],[3,-2],[4,-6],[-5,-5],[-5,-3],[-5,1],[-6,-2],[-3,6],[0,12],[-3,11],[-3,1],[-6,-2],[-2,-9],[4,-16],[3,-5],[-2,-5],[-4,-1],[7,-14],[7,-9],[3,-3],[1,-5],[-3,-2],[-9,2],[-4,-1],[-4,1],[-8,2],[-7,0],[-6,-2],[-6,0],[-5,8],[-4,3],[-4,-3],[-3,-10],[-5,-3],[-6,-5],[-4,-5],[-2,-20],[-4,-4],[-5,0],[-4,-1],[-4,1],[-7,1],[-21,-6],[3,-4],[6,1],[18,-1],[8,-4],[2,-9],[3,-4],[6,-4],[5,-2],[2,-3],[-2,-6],[-3,-6],[-6,-6],[2,-3],[6,-1],[3,-13],[-4,-6],[2,-6],[0,-5],[-4,-4],[-3,-3],[-1,-5],[6,-3],[5,-1],[6,0],[5,-6],[6,-8],[4,-7],[0,-11],[4,-7],[8,-4],[0,-4],[5,-2],[5,0],[2,-4],[-1,-5],[-9,-6],[-4,-5],[9,0],[9,-5],[12,5],[6,6],[4,5],[3,-2],[0,-5],[4,-8],[15,-9],[8,-3],[8,-1],[8,0],[2,-5],[-3,-4],[-5,0],[-9,-1],[-7,4],[-5,3],[-41,-2],[-9,-1],[-11,-5],[-11,-3],[-17,-5],[-7,-3],[-19,12],[-6,9],[-2,0],[-5,-2],[0,-6],[9,-13],[4,-4],[0,-3],[-3,-2],[-3,0],[-6,3],[-9,2],[-9,-4],[-11,-9],[2,-6],[3,-3],[-1,-4],[-12,-7],[-4,-1],[-2,-1],[3,-3],[6,0],[1,-3],[-2,-3],[-11,-3],[1,-4],[6,-2],[7,1],[5,-3],[0,-5],[-5,-2],[-6,-2],[-39,-12],[-5,-3],[0,-4],[14,-2],[41,1],[2,-1],[-1,-3],[-2,-5],[2,-3],[6,-2],[1,-3],[-3,-1],[-7,-2],[-6,0],[0,-4],[9,-3],[3,0],[1,-12],[-1,-5],[-4,-3],[-2,-1],[0,-4],[12,-3],[18,-13],[5,0],[7,-2],[12,-7],[4,-4],[7,-2],[1,-3],[4,-2],[17,-9],[2,-4],[-35,-7],[-35,-6],[3,-4],[38,0],[10,-3],[5,1],[2,3],[21,4],[20,2],[7,-1],[28,-15],[13,-5],[8,-2],[6,0],[4,-2],[4,-5],[-1,-4],[2,-2],[3,-1],[6,-3],[6,1],[7,4],[5,-1],[10,-5],[-4,-3],[-2,-2],[-2,-3],[-3,-1],[-7,-1],[-4,0],[-4,1],[-1,-3],[5,-2],[8,-3],[48,-2],[13,-4],[14,2],[6,-1],[5,-1],[2,-5],[7,-1],[11,-4],[14,-2],[12,0],[15,-5],[7,0],[4,-3],[33,-1],[5,-2],[4,-4],[8,-2],[8,0],[47,-6],[17,-3],[4,0],[4,0],[13,-3],[12,-1],[6,-4],[-9988,-5]],[[3457,1545],[2,-1],[7,0],[2,-1],[1,-2],[1,-5],[-2,-1],[-13,1],[-4,2],[-2,0],[-5,-3],[-2,-2],[-8,-3],[-3,1],[-1,4],[0,1],[1,1],[0,1],[0,1],[2,3],[10,4],[13,2],[1,-2],[0,-1]],[[3442,1551],[-5,-6],[-3,0],[-5,4],[-2,3],[0,1],[4,3],[9,-1],[2,-1],[1,-2],[-1,-1]],[[3319,1557],[-1,-1],[-2,1],[0,-1],[1,-1],[-1,-1],[-2,1],[-2,3],[1,3],[2,0],[4,-4]],[[3260,1551],[-1,0],[1,2],[3,6],[6,3],[-1,-2],[-2,-3],[-6,-6]],[[3316,1580],[1,0],[12,1],[4,-4],[4,0],[-10,-7],[-3,2],[-1,2],[0,3],[-7,-1],[-2,1],[-3,-2],[-6,-1],[-2,0],[-2,2],[0,3],[5,0],[4,3],[1,3],[2,-1],[3,-4]],[[3350,1587],[-4,0],[-2,3],[-2,2],[5,0],[3,0],[1,-3],[-1,-2]],[[3365,1595],[-6,-2],[-3,2],[-1,1],[4,3],[2,-1],[1,0],[2,-1],[1,-2]],[[3389,1618],[4,-2],[3,1],[2,-1],[1,-3],[0,-1],[-5,0],[-4,-4],[-6,1],[0,-3],[1,-2],[-2,-1],[-4,3],[-3,-1],[-2,-5],[-1,-1],[-1,-1],[-1,2],[-3,0],[0,1],[-2,2],[-5,-2],[1,2],[7,7],[1,2],[7,4],[4,-1],[8,3]],[[3498,1653],[-2,0],[-1,2],[-1,1],[2,3],[2,3],[1,1],[0,-7],[-1,-3]],[[3467,1658],[-3,-2],[-2,2],[0,4],[-2,2],[1,2],[20,-2],[-1,-2],[-10,-1],[-3,-3]],[[3730,1698],[6,-2],[3,-2],[1,-2],[3,-1],[1,0],[0,-2],[1,-1],[0,-2],[-6,4],[-9,1],[-2,3],[-4,-2],[-1,1],[0,2],[1,3],[2,-1],[4,1]],[[6924,2358],[-2,0],[0,2],[0,2],[-1,2],[-1,2],[1,2],[2,0],[3,0],[1,-4],[-2,-4],[-1,-2]],[[6921,2355],[2,0],[2,0],[6,8],[1,0],[0,-6],[2,-2],[-2,-1],[-4,0],[-1,-3],[4,-4],[2,-1],[1,0],[3,1],[3,2],[3,3],[2,2],[5,0],[2,3],[1,1],[2,0],[2,-1],[1,-3],[1,-4],[0,-4],[-2,-3],[-2,-3],[0,-2],[-1,-2],[-1,0],[-1,1],[-2,3],[-2,2],[-4,0],[-3,-1],[0,-2],[-1,-2],[-1,-1],[-2,1],[0,-1],[1,-3],[2,-3],[3,-2],[3,0],[0,4],[2,0],[3,-1],[1,-3],[-1,-1],[-1,-2],[0,-2],[-3,-2],[-1,0],[-4,1],[-3,2],[-1,2],[-1,1],[-2,-3],[-2,0],[-4,2],[-3,3],[-2,1],[-4,1],[-2,-7],[-2,-3],[-4,0],[-1,0],[-1,3],[0,3],[1,3],[1,3],[0,3],[0,3],[-1,2],[1,4],[-2,3],[1,2],[2,2],[-1,1],[-1,1],[-1,2],[0,2],[0,4],[1,4],[0,4],[2,4],[2,5],[1,2],[2,0],[0,-1],[1,-3],[-1,-1],[1,-1],[1,-6],[-1,-2],[0,-2],[-2,-5],[0,-3],[4,-2]],[[6439,2509],[-2,-1],[-2,2],[-1,3],[3,2],[1,-1],[1,-2],[0,-3]],[[3285,6165],[-1,-2],[-3,1],[0,3],[0,2],[2,4],[2,-2],[1,-2],[0,-2],[0,-1],[-1,-1]],[[3284,6196],[0,-1],[-2,2],[-1,5],[0,2],[1,0],[0,-1],[2,0],[0,-2],[0,-5]],[[9412,2033],[-1,-3],[0,3],[2,11],[2,2],[-1,-6],[-2,-7]],[[9092,2684],[-1,-6],[-2,1],[-2,-1],[-2,4],[0,1],[2,-1],[1,2],[0,1],[1,1],[0,2],[1,3],[1,0],[1,-4],[0,-3]],[[9095,2693],[-2,0],[-1,1],[0,3],[-1,1],[0,1],[1,1],[0,2],[1,-2],[2,-7]],[[9113,2724],[-1,-1],[-1,0],[0,3],[0,2],[1,3],[2,-2],[1,-2],[-2,-2],[0,-1]],[[9028,2835],[3,-1],[2,2],[2,0],[2,-4],[2,-2],[1,1],[2,-1],[1,-2],[3,-2],[1,-2],[1,-2],[2,-1],[8,-6],[5,-2],[8,1],[2,2],[2,2],[1,-2],[2,-3],[0,3],[0,3],[2,2],[2,2],[3,0],[4,0],[1,2],[1,0],[2,-2],[2,-1],[1,2],[3,5],[1,2],[5,-1],[2,0],[2,5],[2,0],[5,-4],[2,-6],[0,-9],[0,-4],[1,-3],[0,-7],[-1,-7],[0,-5],[0,-5],[0,-10],[1,-6],[0,-5],[0,-2],[0,-2],[1,-2],[-1,-3],[1,-3],[-1,-2],[-1,0],[0,2],[0,3],[0,2],[-1,2],[-2,2],[1,1],[1,1],[-1,3],[-1,-2],[-1,-3],[1,-1],[-1,-1],[-2,-4],[-1,-5],[-1,-5],[0,-5],[-1,-4],[-1,-4],[0,-5],[0,-9],[1,-9],[1,-11],[-1,-1],[-3,-1],[-2,-2],[-2,6],[-2,6],[2,2],[2,-1],[1,1],[0,2],[0,1],[-3,3],[-4,2],[-1,-2],[1,-5],[-1,-2],[-2,-2],[-1,8],[-3,6],[0,-3],[1,-5],[0,-2],[-1,-3],[-1,-1],[0,-2],[0,-3],[-1,-5],[-2,-3],[-5,6],[0,-2],[0,-2],[3,-3],[-2,-2],[0,-3],[-2,-8],[-2,-6],[-1,-1],[-4,1],[-4,6],[-4,-1],[-6,1],[-4,-2],[-1,5],[-1,3],[1,1],[3,2],[3,0],[-1,2],[0,1],[-2,-1],[-4,2],[-3,-1],[-2,3],[-3,10],[-2,4],[-1,2],[-2,1],[-1,1],[-6,22],[-1,5],[-1,13],[5,-6],[2,-4],[1,-5],[2,6],[-1,2],[-4,8],[-1,2],[0,2],[-1,-2],[-2,-1],[1,5],[-1,6],[-5,11],[-3,10],[-4,13],[-1,2],[0,3],[-2,8],[0,7],[-1,5],[2,12],[0,6],[3,-3],[6,-3]],[[9117,2850],[-2,-4],[-1,3],[-1,1],[3,1],[1,-1]],[[9021,2851],[-1,-5],[-1,6],[1,1],[1,2],[0,-4]],[[9119,2862],[3,-3],[1,-4],[-2,-3],[-1,-1],[-1,4],[-3,-1],[-3,0],[-2,3],[-1,1],[2,1],[4,0],[3,3]],[[9110,2894],[5,-11],[3,-1],[0,-1],[0,-5],[-1,-2],[2,-2],[0,-2],[-3,-4],[-3,-1],[-1,1],[0,2],[-1,2],[-4,9],[1,3],[-1,3],[-2,0],[-1,2],[2,3],[2,6],[2,-2]],[[8997,2873],[-1,0],[0,3],[0,5],[-1,4],[0,5],[0,5],[1,2],[1,3],[1,4],[1,0],[3,-3],[0,-9],[0,-5],[1,-4],[-1,-4],[-2,-4],[-3,-2]],[[9036,2967],[1,-3],[0,-1],[-3,2],[-4,0],[3,4],[2,-1],[1,-1]],[[9040,2975],[-4,-4],[-1,2],[0,2],[0,2],[4,0],[1,-2]],[[8821,3125],[7,-1],[2,2],[4,-2],[2,-5],[-2,-3],[-1,0],[-5,2],[-5,-2],[-1,-2],[-1,-5],[-4,-3],[-2,3],[-4,2],[-2,-3],[-4,1],[-3,-1],[-4,0],[-5,6],[-1,3],[1,4],[2,4],[12,5],[7,4],[5,-1],[2,-1],[1,-2],[-1,-4],[0,-1]],[[9264,3604],[-2,-16],[-1,0],[-1,2],[0,10],[1,5],[3,-1]],[[9261,3610],[-1,5],[-1,6],[1,5],[1,1],[1,-1],[-1,-9],[0,-7]],[[8143,3683],[-1,-2],[-5,18],[-1,12],[1,2],[1,1],[3,-17],[1,-4],[0,-4],[0,-1],[1,-5]],[[9251,3701],[0,-2],[-2,3],[-1,10],[1,6],[2,5],[0,3],[-1,7],[4,7],[1,4],[1,4],[-2,5],[-1,2],[1,2],[1,2],[1,0],[1,0],[0,-10],[2,-4],[0,-5],[-6,-26],[-2,-9],[0,-4]],[[9198,3831],[1,-2],[1,0],[0,-4],[1,-4],[1,-3],[-1,-3],[-1,-1],[-1,2],[-5,12],[1,5],[3,-2]],[[9180,3898],[-1,0],[0,1],[0,2],[0,3],[1,-1],[1,-4],[-1,-1]],[[9164,3906],[-1,-2],[-1,4],[0,4],[1,2],[1,-6],[0,-2]],[[8206,3986],[-2,-4],[-2,1],[0,2],[1,4],[3,4],[0,-2],[0,-5]],[[9139,4015],[0,-1],[-1,0],[-2,1],[1,8],[1,-4],[1,-3],[0,-1]],[[9136,4023],[-1,1],[0,2],[1,2],[1,1],[0,-5],[-1,-1]],[[9062,4134],[1,-6],[1,-4],[0,-3],[-1,-2],[-2,2],[-1,5],[-2,4],[-1,3],[3,-1],[1,1],[1,1]],[[8873,4198],[-1,-1],[0,2],[1,3],[1,3],[2,-3],[0,-3],[-3,-1]],[[8874,4229],[-2,-5],[-1,1],[-1,-3],[-2,-1],[-1,0],[-2,-1],[-1,1],[1,5],[2,6],[1,3],[5,2],[4,2],[3,-6],[-4,-1],[-2,-3]],[[8807,4275],[-1,-3],[-1,3],[-1,3],[-1,1],[1,2],[0,1],[1,4],[1,-4],[1,-5],[0,-2]],[[8793,4284],[-1,-1],[-1,1],[0,2],[0,3],[2,0],[1,-1],[-1,-4]],[[8801,4284],[-1,0],[0,4],[1,3],[1,-5],[-1,-2]],[[8460,4297],[-1,-2],[-1,1],[0,2],[-1,2],[1,3],[0,1],[1,0],[0,-2],[1,-3],[0,-2]],[[8477,4344],[-2,-4],[-1,3],[1,6],[1,2],[1,-1],[0,-4],[0,-2]],[[8797,4389],[1,-3],[1,0],[1,6],[1,-1],[1,-1],[0,-3],[-2,-4],[-1,-2],[-1,-8],[0,-2],[1,-3],[2,-2],[2,1],[0,-4],[-1,-2],[-4,1],[-3,-1],[-5,3],[-3,0],[-1,1],[2,2],[1,3],[-1,7],[1,8],[3,4],[1,4],[2,3],[1,0],[0,-3],[1,-4]],[[8783,4388],[0,-1],[-3,1],[0,2],[1,2],[0,1],[2,4],[1,-3],[1,-5],[-2,-1]],[[8786,4516],[-4,-5],[2,6],[5,5],[1,1],[0,-2],[-3,-4],[-1,-1]],[[8623,4511],[2,-1],[1,-2],[1,-2],[0,-3],[-3,-1],[-5,4],[-5,-3],[-2,0],[-1,2],[1,6],[2,-1],[2,2],[-1,7],[-1,4],[3,6],[1,2],[2,0],[1,-5],[0,-5],[1,-5],[1,-5]],[[8627,4529],[4,-1],[5,4],[2,-1],[1,0],[3,4],[2,1],[1,3],[2,-3],[3,-4],[1,-4],[2,-2],[0,-1],[-2,-4],[0,-5],[-2,1],[-3,-8],[-9,-12],[-9,10],[-4,8],[-2,10],[-1,8],[-1,5],[1,1],[0,1],[1,0],[3,-6],[1,-1],[1,-4]],[[8794,4528],[-2,-3],[-1,3],[1,2],[3,8],[1,2],[1,1],[0,3],[0,5],[2,0],[-2,-10],[-3,-11]],[[8682,4533],[0,-1],[-2,9],[0,3],[-1,4],[2,1],[1,3],[0,-2],[0,-6],[1,-4],[-1,-7]],[[8976,4495],[0,-7],[-2,-5],[0,-3],[0,-5],[3,-3],[1,-2],[1,-6],[3,-8],[0,-6],[2,-7],[2,-13],[0,-12],[2,-9],[-1,-17],[1,-7],[1,-5],[2,-12],[1,-11],[2,-3],[4,-3],[4,4],[3,5],[3,1],[4,3],[3,-7],[2,-8],[8,-10],[4,-7],[3,-4],[3,-5],[0,-5],[-1,-4],[1,-6],[0,-7],[-1,-9],[3,-13],[0,-10],[3,-10],[-1,-10],[0,-4],[0,-6],[2,-7],[1,-6],[3,-6],[3,-8],[2,-2],[2,0],[0,-9],[4,-18],[2,-15],[-1,-20],[-2,-11],[1,-6],[5,-13],[3,-3],[-1,-6],[0,-10],[2,-8],[3,-6],[3,-4],[3,-2],[4,-3],[5,-1],[2,-5],[1,-3],[4,-1],[2,0],[2,2],[2,-3],[1,-3],[2,-8],[4,-9],[3,-1],[2,-5],[2,-1],[2,0],[3,-4],[5,-7],[5,-1],[2,-3],[4,-8],[2,-4],[2,-7],[-2,0],[-3,1],[-1,-7],[3,-9],[4,-6],[4,-7],[4,-9],[1,-7],[1,-3],[1,-10],[4,-6],[0,-11],[2,-15],[2,-13],[1,-4],[2,-7],[1,1],[2,2],[3,-6],[1,-3],[1,2],[-2,12],[1,7],[1,1],[2,0],[2,-6],[2,-6],[5,-5],[4,-6],[1,1],[-1,4],[1,6],[1,0],[1,-2],[3,-10],[0,-18],[1,-16],[1,-16],[3,-5],[1,-4],[3,-5],[2,-5],[2,-2],[7,-11],[3,-1],[3,-1],[4,-5],[2,-4],[4,-17],[2,-6],[4,-6],[2,-2],[3,-4],[1,-6],[0,-3],[2,-6],[2,-8],[4,-4],[4,-9],[0,-15],[2,-7],[1,-3],[3,-3],[1,-3],[-3,-19],[3,-39],[-2,-13],[3,-12],[5,-21],[1,-7],[1,-9],[3,-11],[0,-17],[1,-8],[0,-10],[-4,-11],[-3,-14],[0,-12],[-2,-23],[-2,-6],[-1,-10],[-4,-23],[0,-9],[0,-10],[0,-11],[-1,-7],[-1,-13],[-5,-20],[-6,-15],[-1,-11],[0,-5],[-2,-7],[-3,-6],[-3,-3],[-1,-4],[-2,0],[0,-2],[2,-1],[-1,-2],[-6,-4],[-4,-4],[-4,-12],[-2,-6],[-2,-5],[-1,-3],[-1,-3],[0,-7],[-3,-1],[-1,-2],[0,-7],[0,-8],[-1,-5],[-1,-4],[-1,2],[-1,-1],[-1,-2],[2,0],[1,-1],[-4,-8],[-4,-8],[0,-5],[-2,-6],[-1,-15],[-2,-8],[1,-6],[0,-1],[-1,0],[-2,-2],[0,-2],[0,-2],[1,-1],[0,-1],[-1,-1],[-2,0],[-1,-2],[-6,-22],[-2,-5],[-3,-9],[-1,-8],[-1,-9],[-1,-14],[-1,-10],[-2,-10],[0,-7],[-1,-14],[1,-10],[0,-6],[0,-5],[-1,-5],[-4,-1],[-2,-4],[-4,-6],[-3,-3],[-5,-2],[-10,1],[-19,-2],[-3,-2],[-7,-4],[-7,-7],[-7,-10],[-15,-25],[-11,-3],[-2,0],[-2,1],[-2,-2],[0,-3],[2,-3],[1,-3],[3,4],[1,-1],[0,-8],[0,-5],[-1,-3],[-1,-2],[-2,1],[0,3],[-2,7],[-3,5],[-2,2],[-2,-2],[-2,-2],[-2,7],[-2,7],[-3,0],[-2,0],[-2,3],[-4,4],[1,4],[1,3],[2,1],[-1,5],[-1,4],[-3,1],[-2,-1],[-1,-3],[-2,-5],[-6,-7],[-3,4],[-4,5],[2,0],[3,0],[3,5],[2,3],[1,7],[-2,4],[-2,4],[-2,3],[-10,-10],[-2,-2],[-2,-2],[3,-2],[2,1],[3,-3],[-4,-4],[-2,-1],[-4,-3],[-6,-7],[-8,-13],[-4,-4],[-4,-3],[-5,3],[-3,1],[-4,6],[-7,4],[-6,7],[-5,4],[-3,1],[-4,-2],[-8,7],[-5,0],[-4,-6],[-3,0],[-1,1],[-6,11],[-6,6],[-11,2],[-6,8],[-5,15],[-9,16],[-3,7],[-1,5],[0,5],[1,9],[2,9],[0,5],[-4,17],[-5,16],[-2,5],[-6,10],[-6,8],[-1,4],[-1,2],[3,-1],[1,4],[2,1],[2,-5],[1,0],[0,7],[1,3],[0,2],[-1,1],[-2,2],[-3,-3],[-2,-3],[-3,-2],[-1,-3],[-3,0],[-1,-1],[-6,-5],[-4,0],[-5,2],[1,7],[3,4],[2,5],[3,17],[-1,15],[-1,7],[-5,12],[-2,8],[-3,8],[-1,-5],[-1,-5],[-3,-7],[-1,-15],[-5,-24],[-4,-1],[-3,1],[-5,-2],[-3,-4],[-3,0],[-2,-1],[-3,1],[4,19],[3,-1],[4,1],[1,0],[3,0],[1,8],[1,10],[0,6],[-1,7],[1,7],[0,5],[5,18],[3,9],[5,7],[-1,6],[-1,9],[-1,6],[2,3],[2,4],[-2,18],[-1,6],[-3,5],[0,-7],[1,-7],[-3,-9],[-4,-6],[-3,-6],[-2,-14],[-4,-11],[-3,-4],[-2,-1],[-3,-2],[-4,-5],[-4,-4],[-3,-5],[-3,-2],[-9,-23],[-4,-8],[0,-3],[-2,-3],[0,-3],[2,-3],[1,-10],[-1,-2],[-1,1],[-4,6],[-2,-2],[-2,-3],[-5,11],[-1,2],[-3,4],[-2,4],[-2,0],[-1,0],[0,3],[1,2],[1,0],[2,-3],[3,-3],[1,0],[1,1],[-3,12],[-1,10],[-1,3],[-2,11],[-1,3],[-4,7],[-4,9],[-1,10],[-2,7],[-2,4],[-3,4],[-8,2],[-4,10],[-2,14],[2,0],[2,1],[0,4],[0,6],[-9,8],[-4,8],[-3,4],[-3,1],[-4,0],[-6,0],[-12,13],[-3,1],[-9,-5],[-3,1],[-14,18],[-9,9],[-3,1],[-4,2],[-3,-2],[-2,-2],[-5,-3],[-18,2],[-16,-3],[-10,-2],[-7,-2],[-11,-11],[-13,-10],[-11,-5],[-10,-7],[-7,-1],[-8,-1],[-18,3],[-6,-2],[-10,-12],[-3,-3],[-5,-4],[-14,-15],[-7,-3],[-4,-2],[-4,-3],[-3,-6],[-4,-19],[-3,-8],[-6,-14],[-4,-5],[-4,1],[-4,-5],[-4,5],[-3,1],[-5,0],[-18,-6],[-2,7],[-3,1],[-6,-1],[-9,2],[-17,-2],[-8,-3],[-3,-2],[-6,1],[-10,-2],[-3,-4],[-3,-3],[-5,-16],[-5,-5],[-5,0],[-5,-1],[-11,-15],[-10,-14],[-4,-2],[-4,-2],[-5,-1],[-3,-2],[-12,4],[-8,0],[-9,3],[-9,7],[-6,4],[-7,15],[-5,6],[-8,7],[-2,0],[-2,-2],[-3,5],[0,6],[-1,6],[0,14],[0,16],[3,-3],[3,-4],[5,0],[4,6],[2,10],[3,10],[-1,11],[-1,19],[1,4],[1,2],[1,10],[0,29],[-1,11],[-7,23],[-4,19],[-3,9],[-3,15],[-3,19],[0,10],[-1,19],[1,10],[-1,6],[-2,17],[-7,16],[-1,6],[0,6],[-1,7],[-5,14],[-6,12],[0,6],[-1,25],[-2,12],[-9,28],[-11,25],[-3,10],[-1,4],[1,0],[1,-1],[1,-3],[1,0],[1,2],[0,5],[0,3],[1,-2],[1,-5],[3,-14],[1,-7],[4,-2],[2,2],[1,3],[1,10],[-2,4],[-2,2],[-4,8],[-2,11],[-3,11],[0,4],[2,2],[2,-1],[2,-6],[3,-6],[-1,-10],[0,-3],[0,-2],[1,-2],[1,-2],[2,3],[1,5],[1,0],[1,-14],[2,-3],[2,-4],[3,3],[1,3],[0,9],[0,9],[0,7],[-6,17],[-6,22],[-3,11],[-3,17],[-2,5],[-2,9],[0,11],[0,7],[2,15],[1,8],[6,18],[0,8],[0,6],[1,9],[0,6],[-1,6],[-2,10],[3,18],[5,22],[1,3],[3,4],[1,-5],[-2,-16],[2,-8],[0,-9],[2,1],[2,2],[2,5],[1,5],[6,18],[3,7],[4,5],[8,6],[8,8],[4,8],[5,6],[3,8],[4,4],[16,19],[3,3],[4,1],[4,-1],[4,1],[4,-4],[3,-1],[8,5],[4,4],[7,9],[3,2],[8,3],[8,4],[10,15],[7,-1],[6,-1],[5,4],[12,3],[7,4],[12,10],[3,4],[5,7],[5,9],[4,12],[3,11],[1,6],[2,9],[2,7],[1,4],[5,4],[7,14],[3,3],[0,4],[-1,2],[-2,2],[-2,14],[-1,10],[0,7],[1,7],[2,10],[2,4],[3,5],[3,2],[2,4],[3,5],[1,4],[3,9],[2,7],[1,0],[3,-16],[2,-8],[3,-10],[3,-15],[3,-7],[1,-4],[1,-2],[1,2],[-1,4],[2,11],[-1,8],[0,3],[1,1],[1,-1],[3,-4],[1,-2],[1,1],[0,7],[1,4],[0,3],[-3,0],[0,4],[-2,5],[-2,3],[-3,7],[-1,3],[1,1],[2,0],[1,3],[1,4],[-1,7],[1,3],[2,-1],[4,-11],[1,1],[2,5],[2,1],[2,-1],[2,-3],[3,-3],[4,0],[2,-1],[5,1],[2,-1],[0,2],[-3,2],[-3,0],[-3,0],[-1,2],[-1,6],[1,4],[1,1],[2,0],[2,0],[0,5],[1,5],[1,4],[0,3],[-2,-1],[-2,-8],[-2,7],[-2,5],[1,8],[1,7],[2,1],[1,-1],[3,5],[1,3],[-1,3],[1,2],[1,-1],[7,-6],[1,-4],[1,1],[1,4],[-1,4],[-1,0],[-3,0],[-1,2],[0,2],[-1,5],[2,2],[2,1],[1,2],[0,2],[0,2],[1,-2],[4,-1],[3,-3],[1,-1],[1,2],[0,4],[-4,4],[0,4],[-2,5],[0,4],[3,4],[0,4],[2,1],[2,0],[2,3],[2,2],[1,7],[0,4],[1,2],[2,-2],[-1,-6],[0,-5],[0,-3],[1,0],[0,1],[1,4],[2,-2],[1,-3],[0,-4],[1,-1],[2,5],[2,2],[0,7],[0,5],[1,4],[1,2],[0,4],[-1,3],[0,5],[1,1],[2,-3],[1,-6],[1,-3],[1,2],[1,4],[2,2],[3,-3],[2,-5],[3,4],[3,8],[-1,5],[1,5],[3,2],[3,-2],[3,-5],[5,-4],[5,-5],[2,-4],[4,-6],[2,-6],[4,-11],[8,-13],[0,-2],[-1,-4],[-1,-6],[-1,-9],[0,-14],[1,1],[1,5],[1,-1],[2,-3],[0,3],[-1,2],[-1,6],[0,3],[1,3],[2,3],[2,2],[1,2],[0,3],[2,2],[3,1],[1,-1],[12,-6],[3,-5],[0,-8],[1,-2],[1,4],[0,10],[1,2],[3,-1],[2,-2],[3,-7],[1,-3],[1,-2],[1,3],[-1,4],[-1,5],[1,4],[4,1],[2,1],[-1,1],[-2,1],[-2,4],[-2,4],[3,4],[0,1],[-3,0],[-3,4],[-3,6],[2,10],[5,10],[2,4],[0,3],[2,6],[0,6],[1,4],[1,4],[3,4],[3,2],[2,1],[2,4],[1,5],[-3,9],[0,5],[1,5],[4,5],[2,11],[2,2],[3,-1],[1,1],[0,9],[1,4],[1,1],[2,-1],[1,-4],[2,-4],[1,2],[0,4],[0,5],[2,2],[2,0],[0,4],[0,3],[0,2],[5,0],[1,4],[1,3],[1,-2],[1,-6],[2,-4],[8,0],[5,2],[2,-1],[3,-2],[3,4],[2,2],[3,-3],[1,-3],[1,6],[2,3],[2,1],[3,-1],[1,1],[-3,5],[0,4],[0,7],[1,6],[1,5],[-6,9],[-5,1],[-4,-2],[-2,2],[-4,7],[-3,3],[0,2],[4,5],[1,-1],[3,-5],[1,-2],[1,1],[1,3],[1,2],[2,-1],[6,-8],[4,-8],[2,2],[3,5],[2,-1],[2,-3],[3,-10],[2,-4],[4,-2],[3,-2],[2,-3],[4,0],[7,-1],[6,-6],[3,-4],[3,-1],[2,-1],[3,-1],[6,5],[2,-5],[1,-2],[5,-6],[5,-1],[4,5],[5,4],[4,6],[3,3],[3,5],[1,0],[-2,-5],[-1,-3],[2,-1],[0,-1],[-3,-4],[-2,-5],[0,-3],[1,-2],[1,1],[2,2],[2,2],[2,-2],[1,-8],[1,-6],[3,0],[2,0],[2,7],[-1,6],[-1,2],[0,2],[5,10],[3,0],[2,-10],[3,-5],[3,0],[2,-1],[1,-7],[-11,-25],[-1,-2],[2,-5],[0,-5],[-3,-13],[-2,-1],[-1,4],[-2,2],[-2,-1],[-1,-1],[-7,-8],[0,-18],[2,-11],[-1,-7],[-2,-12],[-2,-5],[-2,-3],[-6,-17],[-2,-4],[-2,-6],[1,-6],[1,-4],[2,-4],[8,-9],[4,-7],[7,-7],[1,-6],[1,-4],[5,-5],[3,-3],[1,1],[1,1],[1,0],[0,-1],[0,-3],[0,-3],[0,-2],[3,-4],[4,0],[2,1],[2,-3],[2,-3],[4,-5],[6,-5],[5,-4],[6,-14],[4,-8],[5,-6],[7,-4],[4,0],[5,-4],[6,-3],[2,-6],[1,-5],[1,-4],[2,-9],[5,-3],[7,-10],[6,-4],[2,-2],[2,-3],[5,0],[8,5],[4,4],[5,8],[2,13],[2,10],[7,21],[2,11],[2,13],[1,9],[0,10],[1,17],[4,24],[1,8],[0,11],[-3,22],[1,8],[1,11],[-1,7],[-2,6],[0,7],[2,14],[1,8],[2,9],[-1,18],[3,7],[2,3],[2,0],[1,-2],[1,4],[-1,3],[-1,4],[-1,2],[-1,1],[-1,2],[-2,2],[0,8],[3,16],[2,6],[1,-2],[1,-3],[1,5],[-1,5],[3,15],[2,20],[1,19],[5,4],[2,5],[1,5],[3,0],[1,-2],[-1,-4],[0,-4],[5,-7],[1,-6],[1,-6],[1,-5],[0,-8],[0,-11],[1,-11],[1,-4],[2,-2],[2,0],[3,-2]],[[8951,4567],[-2,-3],[-2,2],[0,3],[0,2],[2,3],[2,-7]],[[8953,4597],[-2,-4],[-1,1],[-1,2],[1,3],[2,1],[1,-3]],[[8948,4599],[-1,-2],[-1,4],[2,4],[1,-2],[-1,-4]],[[5470,7983],[0,-1],[0,-2],[-1,-2],[-1,-4],[0,-3],[3,-11],[3,-7],[0,-2],[2,-2]],[[5476,7949],[-2,-3],[0,-3],[-1,-2],[0,-2],[0,-2],[0,-2],[1,-3],[-3,-1],[-3,0],[-1,0],[-1,-1],[-1,0],[-3,3],[-2,1],[-1,0],[-1,-1],[-1,-2],[-1,-1],[0,-1],[6,-3],[1,-4],[-1,-4],[-1,-1],[-1,-2],[-2,-1],[-2,0],[0,-2],[1,-5],[-1,-2],[-1,-1],[1,-5],[1,0],[1,-1],[-1,-2],[0,-2],[0,-2],[-1,-1],[-3,0],[-2,-2],[-5,-6]],[[5446,7883],[-1,-1],[-2,-3],[0,-5],[0,-1],[0,-1],[-6,2],[-3,0],[-3,-3],[-3,-1],[-6,0],[-6,-1],[-1,0],[-2,-1],[-1,-1],[-1,-2],[-2,-3],[-2,-2],[-2,-2],[-1,-1],[0,-1],[-2,1],[-1,0],[-1,1],[-4,1],[-5,1],[-2,1],[-3,1],[-2,1],[-3,0],[-1,0]],[[5380,7863],[-6,2],[-4,0],[-5,1],[-10,3],[-3,2],[-3,0],[-3,1],[-2,2],[-2,3],[-2,4],[-3,6],[-1,3],[1,3],[1,1],[0,1],[0,1],[-6,-3],[-5,-3],[-3,0],[-2,1],[-2,0],[-3,-1],[-5,0],[-3,-3],[-2,-4],[-1,-4],[-1,-1],[-2,0],[-3,0],[-2,1],[-2,3],[-3,0],[-2,1],[-1,0]],[[5290,7883],[0,2],[-1,4],[-2,1],[-5,-7],[-1,-1],[-4,2],[-3,3],[-1,3],[0,1],[-3,2],[-3,1],[-1,0]],[[5266,7894],[0,1],[0,2],[0,2],[-1,1],[0,2],[0,1],[0,1],[-1,2],[0,1]],[[5264,7907],[2,6],[1,5],[-2,2],[-1,1]],[[5264,7921],[1,1],[3,-1],[1,2],[1,1],[3,-1],[3,-3],[2,-2],[1,-1],[0,-1],[0,-2],[1,-1],[2,-1],[1,0],[-1,-3],[0,-2],[2,0],[2,2],[2,3],[0,3],[1,7],[0,1],[2,-1],[5,0],[2,-1],[4,0],[-1,-1],[1,-2],[2,-2],[0,-2],[2,0],[3,0],[1,1],[1,0],[2,0],[2,2],[1,2],[2,1],[3,3],[4,2],[13,2],[0,1],[0,4],[1,0],[1,-1],[3,0],[2,-2],[1,-1],[1,0],[2,1],[3,0],[2,-1],[1,-2],[0,-1],[0,-2],[0,-1],[2,-2],[3,-2],[1,0],[0,2],[1,4],[0,5],[0,2],[-2,1],[-1,0],[-1,1],[0,1],[1,3],[0,5],[-3,6],[-2,5],[0,2],[1,3],[3,2],[5,4],[1,1],[3,1],[3,2],[1,1],[1,2],[1,10],[1,0],[0,1],[5,-3],[1,0],[1,1],[1,2],[1,2],[0,4],[0,4],[0,1]],[[5383,7993],[1,-1],[2,-2],[2,-2],[2,-5],[4,-1],[5,0],[1,2],[2,1],[2,-1],[4,-1],[0,4],[2,5],[1,1],[3,0],[1,3],[0,9],[1,1],[2,0],[2,-2],[1,-1],[1,0],[1,1],[2,1],[2,-1],[6,-4],[3,-2],[1,0],[2,0],[6,-6],[5,-1],[4,0],[1,2],[2,2],[2,-1],[2,0],[3,-3],[1,-1],[2,0],[1,-1],[2,-5],[0,-1]],[[6280,7423],[-5,2],[-10,4],[-2,1],[-3,6],[-1,2],[-3,3],[-1,2],[-2,2],[0,3],[-2,3],[-2,4],[-4,11],[-1,2]],[[6244,7468],[-1,2],[0,1]],[[6349,7594],[2,-3],[5,-9],[6,-15],[1,-4],[1,-5],[1,-6],[2,-5],[6,-13],[3,-5],[4,-6],[2,-2],[2,0],[4,0],[4,-2],[1,-2],[2,-3],[2,-3],[1,-7],[-6,2],[-6,0],[-4,-2],[-3,-2],[-3,-3],[-2,-6],[-2,-14],[-3,-14],[1,-6],[1,-6],[0,-3],[-2,-1],[-1,-2],[-2,-13],[-1,-2],[-1,-2],[-1,2],[1,3],[-3,3],[-2,-3],[-1,-7],[-2,-7],[0,-1],[1,-22]],[[6357,7398],[-1,0],[-6,-2],[-1,0],[-5,10],[-1,1],[-2,1],[-1,2],[-1,2],[-1,2],[-5,6],[0,2],[0,1],[0,2],[1,1],[3,2],[2,1],[1,1],[1,1],[0,3],[-1,2],[-4,4],[0,2],[0,2],[0,2],[0,2],[4,3],[2,2],[-1,3],[-4,6],[-4,8],[-3,0],[-4,-3],[-5,-6],[-3,-2],[-4,-4],[-4,-5],[-3,-5],[-2,-4],[-4,-2],[-2,-4],[-6,-10],[-2,0]],[[6249,7562],[6,8],[2,1],[4,-1],[8,-5],[0,-3],[1,-2],[1,-2],[4,-2],[3,-1],[2,1],[2,1],[3,-3],[3,-3],[1,-1],[1,-1],[2,1],[3,5],[1,4],[0,3],[-2,3],[-3,4],[-3,3],[-2,3],[-2,5],[-1,1],[-1,0],[0,2],[0,3],[1,2],[1,1],[2,0],[1,2],[1,4],[1,2]],[[6289,7597],[3,-2],[0,-3],[1,-1],[1,1],[2,1],[2,-1],[2,-4],[3,-4],[2,-3],[0,-2],[2,-2],[2,-2],[2,-3],[1,-9],[2,-1],[5,-3],[2,-1],[6,-1],[2,1],[3,7],[2,7],[3,1],[4,4],[3,3],[1,4],[2,6],[2,4]],[[5848,5046],[0,-2],[-3,-11],[0,-1],[0,-1],[1,-2],[-1,-4],[0,-1],[0,-3],[0,-3],[0,-1],[2,-1],[3,-1],[2,-3],[2,0],[1,-2],[0,-3],[0,-3],[0,-5],[0,-4],[-3,-2],[-2,-2],[0,-1],[0,-1],[0,-2],[-3,-4],[-2,-6],[-1,-4],[-1,-4],[-1,-3],[-2,-4],[-2,-8],[-1,-6],[-6,-12],[-5,-7],[-1,-2],[-9,1]],[[5816,4928],[0,8],[-2,12],[-3,11],[0,4],[0,9],[0,12],[0,6],[0,5],[0,8],[0,5],[-2,6],[-2,6],[-2,3],[0,2],[0,2]],[[5805,5027],[1,3],[1,4],[1,0],[2,-1],[3,-3],[2,-7],[1,-1],[2,0],[5,1],[1,0],[3,1],[2,3],[1,3],[0,7],[1,12],[1,0],[3,-4],[1,0],[1,0],[1,2],[1,2],[1,0],[4,2],[2,-4],[1,-1],[1,0]],[[5158,8108],[0,1],[3,1],[2,-3],[3,0]],[[5166,8107],[0,-1],[3,-3],[1,-3],[3,-2],[-2,-3],[0,-1],[1,-2],[2,0],[2,-2],[0,-3],[0,-5],[-5,-5],[-1,-5],[-1,-1]],[[5169,8071],[0,2],[-1,0],[-3,0],[-3,-5],[-1,-4],[-1,-3],[-1,-2],[0,-2],[0,-2],[0,-1],[0,-1],[1,-3],[1,-2],[2,-5],[-1,-2],[0,-2],[-1,-1],[-1,-1]],[[5160,8037],[-2,0],[-3,0],[-2,-1],[-1,0],[-2,2],[-2,4],[-1,2],[-1,1],[-2,1],[-2,2],[-2,2],[-1,1],[-3,1],[-1,0],[-1,3],[0,4],[-1,2],[2,11],[-2,1],[-1,-1],[-2,-3],[-1,-3],[0,-2],[-3,-3],[-5,0],[-6,0],[0,1],[-1,1],[0,1],[1,1],[1,2],[0,2],[-1,2],[-1,1],[1,2],[0,2],[0,2],[-3,4],[-3,1],[-2,0],[-2,1],[-1,0],[-1,-2],[-1,-1],[-1,1],[-1,8],[-1,1],[-3,1],[-4,1],[-2,1],[0,4],[-1,4],[-1,4],[-1,1],[-1,2],[-3,-1],[-2,-2],[-2,-1],[-1,0],[-2,2],[-2,3],[-2,4],[-1,2],[1,3],[-1,2],[-1,3],[0,3]],[[5070,8127],[12,10],[7,5],[4,1]],[[5093,8143],[0,-5],[1,-1],[1,-2],[1,0],[1,2],[2,1],[3,-1],[2,-1],[1,-1],[1,-1],[2,-1],[4,3],[3,3],[1,2],[1,3]],[[5117,8144],[2,-2],[2,0],[1,0],[-1,4],[2,2],[2,1],[0,-2],[2,-1],[1,0],[4,4],[0,-1],[1,-2],[0,-1],[0,-1],[1,0],[3,0],[1,2],[1,1],[1,-1],[0,-2],[1,-4],[3,-4],[3,-1],[3,1],[2,1],[1,-1],[0,-2],[2,-2],[4,-2],[2,-1],[0,-1],[0,-3],[-2,-5],[0,-2],[0,-1],[0,-1],[-3,-3],[0,-2],[1,-2],[1,-2]],[[5099,5857],[-1,-3],[-2,-8],[0,-6],[5,-12],[0,-2],[1,-2],[1,-2],[0,-6],[1,-7],[0,-5],[2,-7],[0,-2],[-1,-10],[-1,-1],[-2,0],[-1,-1],[-1,-3],[-1,-3],[0,-2],[2,-6],[-1,-9],[-2,-6],[-2,-3],[-2,-1],[-1,-1],[-1,-2],[0,-6],[-3,-6],[-2,-4],[0,-3],[0,-7],[-1,-8],[-2,-6],[-4,-1],[-3,-1],[-2,-15],[0,-10],[0,-10],[0,-4],[0,-6],[0,-13],[-1,-10],[1,-2],[0,-6],[0,-7],[1,-4],[1,-4],[0,-1],[-1,-2],[0,-1],[0,-15],[0,-4],[0,-3],[-1,-2],[0,-7],[1,-5],[1,-4],[-1,-2],[-1,-4],[0,-10],[0,-3]],[[5075,5551],[-12,-3],[-13,-4],[-5,-2]],[[5045,5542],[-1,2],[5,2],[-1,8],[-3,9],[-1,2],[-1,4],[1,3],[0,2],[-1,6],[-1,7],[3,0],[0,21],[0,21],[0,17],[0,14],[-1,17],[0,12],[0,16],[-1,5],[-4,9],[-1,4],[0,6],[-1,6],[0,10],[0,13],[-1,2],[-4,5],[-6,9],[-4,6],[-1,0],[0,2],[0,19],[1,2],[2,8],[1,6]],[[5025,5817],[1,2],[1,3],[1,-1],[1,0],[1,1],[0,2],[0,2],[1,1],[0,3],[0,2],[1,1],[2,-1],[1,1],[1,1],[1,5],[1,2],[0,1],[1,1],[2,1],[2,-1],[1,-3],[7,3],[4,-2],[6,13],[2,3],[2,9],[1,3]],[[5066,5869],[1,6],[-2,11],[0,2],[3,2],[4,2],[1,0],[1,1],[1,2],[2,2],[2,0],[0,-1],[8,-14],[3,-7],[1,-4],[2,-3],[2,-2],[3,-3],[1,-6]],[[5006,6043],[-1,-3],[0,-5],[0,-7],[-1,-9],[2,-6],[3,-6],[1,-3],[-1,-6],[1,-3],[1,-6],[3,-8],[3,-8],[2,-1],[1,-1],[1,-1],[2,-1],[1,-1],[2,-2],[1,-2],[1,-4],[3,-4],[2,-3],[-1,-1],[-3,0],[-2,2],[0,-3],[0,-9],[0,-7],[0,-1],[3,-1],[6,-10],[5,-9],[2,-2],[3,-1],[3,-1],[2,1],[3,5],[2,0],[1,0],[1,-1],[1,-3],[2,-6],[0,-4],[0,-2],[0,-1],[-3,-1],[-1,-1],[0,-1],[0,-3],[1,-2],[2,-8],[5,-11],[1,-3]],[[5025,5817],[-8,-1],[-2,-1],[-2,0],[0,1],[0,1],[-9,4],[-6,3]],[[4998,5824],[-7,3],[0,-3],[-1,-2],[-1,0],[-1,1],[-1,-2],[-1,-3],[-2,-2],[-1,-1],[-1,-2],[-1,0],[-1,4],[-2,0],[-4,0],[-1,0],[-2,1],[-6,-1],[-8,2],[-2,-1],[0,-1],[-8,0],[-9,0],[-8,0],[-7,0],[-2,0],[0,-1],[-2,-14],[0,-8],[1,-5],[1,-3],[1,-1],[0,-2],[-1,-2],[0,-3],[1,-2],[1,-2],[-1,-3],[0,-6],[1,-10],[0,-7],[-1,-3],[1,-5],[1,-7],[1,-3]],[[4925,5730],[-1,-1],[-1,-2],[-2,0],[-1,4],[-1,2],[-1,4],[-1,5],[-2,2],[-1,2],[-2,5],[-2,3],[-2,-1],[-3,1],[-5,1],[-6,0],[-2,-1],[-3,-2],[-6,-5],[-2,-2],[-2,-6],[-2,1],[-2,1],[-1,3],[-3,-1],[-3,3],[-2,5],[-2,1],[-3,4],[0,6],[-2,5],[-1,7],[-2,3],[-3,1],[-3,0],[-2,2],[-2,4]],[[4846,5784],[1,4],[0,4],[0,5],[1,7],[0,9],[-1,7],[2,2],[2,3],[1,4],[2,10],[0,8],[0,4],[-1,2],[0,4],[-1,4],[1,4],[1,4],[2,3],[2,1],[3,2],[5,2],[3,2],[2,3],[1,2],[1,4],[2,3],[1,3],[1,9],[0,5],[-1,3],[-1,3],[7,7],[0,5],[-1,5],[-1,5],[-1,3],[2,5],[2,3],[1,3],[3,5],[3,1],[2,-2],[8,-10],[2,-1],[1,1],[2,3],[3,2],[1,7],[0,10],[0,4],[2,1],[4,-2],[1,0],[2,1],[0,2],[0,3],[0,3],[2,9],[2,7],[6,9],[1,2],[2,1],[10,-6],[1,1],[3,15],[2,2],[3,0],[2,1],[1,2],[5,5],[8,8],[4,3],[1,2],[3,5],[4,7],[3,1],[4,0],[2,-1],[0,-2],[1,-1],[5,3],[7,-4],[6,-4]],[[7553,6423],[-1,-1],[-1,2],[0,2],[0,8],[1,1],[1,0],[0,-2],[1,-5],[-1,-5]],[[7551,6441],[-1,-4],[0,3],[0,4],[1,3],[1,-3],[-1,-3]],[[7531,6461],[-3,-4],[1,24],[2,-9],[1,-5],[-1,-6]],[[7542,6473],[-1,-2],[-1,2],[-2,5],[1,7],[1,1],[0,-2],[2,-5],[0,-4],[0,-2]],[[7521,6456],[-5,-2],[-2,1],[4,15],[0,7],[-1,5],[-2,5],[0,3],[-1,4],[-1,5],[3,2],[2,-3],[0,-2],[1,-4],[1,-4],[3,-9],[0,-6],[-1,-13],[-1,-4]],[[7517,6506],[1,-2],[-2,1],[-1,2],[-1,2],[1,2],[2,-5]],[[7571,6450],[0,-2],[0,-20],[0,-8],[1,-6],[0,-3],[-1,-2],[-1,3],[-2,2],[-3,3],[-1,2],[-1,-1],[-2,-4],[-1,-4],[0,-5],[1,-5],[1,-3],[0,-3],[1,-5],[0,-3],[1,-5]],[[7564,6381],[-1,0],[-1,6],[-2,5],[-4,11],[-1,20],[0,10],[-3,11],[-1,16],[-1,4],[1,5],[0,2],[-2,-3],[-2,6],[-1,6],[-4,12],[-2,5],[0,5],[-2,-5],[-2,-4],[-3,-5],[-2,-2],[-5,-1],[-4,8],[-5,17],[0,4],[0,10],[-1,10],[0,5],[0,4],[-1,-1],[0,-2],[0,-4],[0,-3],[-4,0],[-4,2],[3,-5],[4,-1],[2,-5],[0,-4],[0,-4],[-2,-3],[-2,-1],[1,-4],[2,-5],[-3,-1],[-1,-3],[0,-5],[2,-4],[0,-2],[0,-3],[1,-3],[2,-6],[0,-4],[0,-6],[-1,-2],[-2,-3],[-4,-7],[-2,-9],[-1,-4],[-2,-1],[-1,2],[-2,2],[0,5],[1,3],[3,8],[-2,-1],[-2,-2],[-3,-5],[-1,6],[-1,5],[0,6],[3,9],[-3,-5],[-1,-5],[1,-7],[-1,-5],[-1,-6],[-1,-4],[-3,-2],[-1,-4],[-2,-2],[0,5],[0,7],[-2,17],[0,-4],[0,-10],[0,-7],[-1,-5],[-3,-6],[-2,-1],[-1,1],[-2,4],[-2,5],[0,8],[-1,4]],[[7473,6456],[0,6],[0,5],[-2,13],[-2,7],[0,3],[0,1],[0,9],[-1,5],[-1,6],[2,8],[0,2],[-3,1],[-2,1],[-1,2],[1,9],[-1,3],[-2,3],[0,2],[-1,1],[-1,4],[2,9],[2,10],[1,4],[0,7],[0,2],[0,3],[-2,3],[-4,1],[-3,3],[-2,3],[-1,2],[-2,-1],[-2,1],[-2,4],[-2,4],[1,2],[0,3],[3,12],[1,0],[2,-2],[1,0],[2,5],[2,13],[4,0],[3,-1],[1,-1],[2,1],[2,1],[2,2],[0,2],[0,2],[-3,2],[-1,2],[0,5],[-1,2],[-5,0],[-2,3],[-2,2],[-2,7],[-3,5],[-3,1],[-1,2],[-1,3],[0,4],[1,3],[1,4],[2,6],[3,4],[1,3],[2,4],[0,1],[0,3],[-2,2],[-1,0],[0,1],[1,4],[1,0],[3,-3],[3,-5],[2,-4],[0,-4],[1,0],[1,-1],[2,-1],[2,0],[1,-1],[1,1],[0,2],[-1,3],[-1,2],[1,2],[1,1],[1,-1],[1,-2],[1,-4],[0,-6],[3,-6],[3,-3],[2,-2],[2,-2],[3,2],[1,4],[-1,3],[1,3],[1,2],[1,0],[1,-3],[3,-13],[0,-6],[0,-16],[0,-11],[0,-2],[0,-2],[1,0],[1,0],[3,-2],[4,-3],[3,-2],[5,-1],[4,0],[1,0],[4,0],[8,1],[7,0],[3,-2],[2,0],[8,1],[8,1],[4,-4],[5,-5],[3,-4],[0,-3],[0,-2],[-1,-1],[-2,0],[-3,3],[-1,-1],[0,-6],[-1,-5],[-2,-11],[0,-5],[-1,-2],[-2,0],[-2,-1],[0,-2],[-1,-4],[-1,-4],[0,-1],[-3,2],[-1,0],[-1,-1],[-2,-2],[-1,-3],[-1,-1],[-4,1],[-1,0],[0,-2],[-1,-3],[-3,-5],[-1,-9],[-1,-6],[1,-5],[2,-12],[2,-15],[0,-2],[1,0],[0,3],[0,4],[1,1],[1,-1],[1,-3],[1,-6],[1,-3],[2,-1],[2,2],[2,3],[1,3],[-1,6],[0,4],[1,4],[4,7],[0,2],[0,5],[0,5],[1,0],[2,0],[2,2],[1,0],[1,-3],[2,1],[1,-11],[1,-10],[0,-4],[0,-10],[1,-9],[1,-1],[1,-5],[1,-5],[0,-3],[1,-9],[1,-6],[0,-21],[1,-4]],[[5793,7703],[0,-14],[-3,-6],[-4,2],[-5,-2],[-3,-7],[-1,-2],[-2,-3],[-1,-9],[0,-16],[-2,-2],[-2,0],[-7,-14],[4,-4],[2,-3],[3,-8],[5,-9],[1,-5]],[[5778,7601],[-4,1],[-1,0],[-1,-2],[-2,1],[-2,0],[-2,-2],[-2,-1],[-1,2],[-3,4],[-2,4],[-2,0],[-1,-1],[-5,-1],[-1,-2],[-3,-2],[-2,0],[-3,-1],[-2,0],[-1,-1],[-1,-3],[-1,-3],[0,-1],[-4,-1],[-1,-2],[-1,-2],[1,-1]],[[5731,7587],[-4,1],[-2,-1],[-1,-1],[-1,-2],[1,-2],[1,-2],[1,-5],[0,-5],[-1,-2],[-2,-2],[-3,-3],[-4,1],[-2,-1],[-3,0],[-2,0],[-5,-2],[-3,-2],[-3,5],[-4,2],[-4,2],[-2,-1],[0,-1],[-4,4],[-1,1],[-1,1],[-2,5],[-3,-2],[-3,1],[-1,0],[-5,0],[-1,-4],[-1,0],[-1,-1],[-2,1],[-3,-3],[-4,-1],[-3,0],[-3,0],[-1,0],[-4,0],[-2,-4],[-4,0],[-3,1]],[[5636,7565],[0,1],[1,14],[1,7],[0,1],[0,1],[-1,1],[-1,3],[-2,10],[-1,1],[-3,2],[-3,3],[-3,3],[-4,9]],[[5620,7621],[2,1],[1,2],[2,4],[0,3],[0,1],[-1,2],[-1,5],[0,5],[0,2],[0,3],[1,2],[1,2],[1,1],[4,0],[3,6],[1,2],[2,3],[1,1],[0,3],[1,2],[-4,4],[-1,3],[-1,3],[-2,2],[-4,4],[-2,3],[0,5],[-1,4],[-1,2],[-1,2],[0,3],[0,4],[1,6],[0,3],[2,0],[3,3],[0,5],[1,2],[1,2],[1,1]],[[5630,7732],[2,-3],[5,-4],[2,-2],[0,-2],[-1,-2],[-2,-2],[-1,-2],[-1,-3],[1,-2],[1,-1],[9,2],[8,-1],[12,-4],[7,-1],[6,1],[11,-3],[9,-3],[10,-1],[5,3],[4,3],[3,6],[8,8],[7,4],[10,4],[7,1],[1,-1],[8,-8],[4,0],[3,-1],[1,-2],[1,0],[4,1],[2,-4],[3,-5],[4,-3],[5,-2],[1,0],[4,0]],[[6405,6675],[-1,-5],[-1,2],[-2,7],[1,6],[-1,7],[0,3],[3,1],[1,-1],[-1,-2],[1,-4],[0,-8],[0,-6]],[[2971,6404],[-1,-4],[-3,-8],[-6,-2],[-7,0],[-1,2],[0,2],[0,3],[0,1],[0,1],[3,2],[1,3],[3,1],[4,-3],[1,0],[3,3],[2,6],[2,0],[-1,-7]],[[2974,6423],[-3,-3],[-1,3],[2,3],[2,-3]],[[2971,6476],[2,-1],[4,-2],[2,-2],[0,-1],[-1,-2],[-3,4],[-3,0],[-3,0],[-2,1],[1,4],[3,-1]],[[2938,6463],[-2,-1],[1,3],[4,5],[2,4],[1,2],[0,1],[2,1],[1,3],[0,3],[-2,4],[0,2],[0,2],[3,1],[0,-3],[1,-8],[-4,-10],[-3,-3],[-4,-6]],[[2943,6493],[0,-1],[-2,-3],[-4,3],[-1,3],[-1,2],[1,2],[2,-1],[1,-3],[4,-2]],[[2921,6502],[0,-1],[-4,12],[-4,2],[-3,3],[1,2],[1,0],[1,4],[-1,4],[-2,8],[-2,5],[0,2],[0,4],[2,-7],[2,-6],[1,-6],[2,-11],[3,-3],[3,-5],[0,-7]],[[2898,6534],[-1,0],[-2,2],[-5,7],[-2,0],[0,4],[2,-1],[4,-6],[1,-3],[3,-3]],[[2932,6570],[-2,-6],[-1,0],[1,8],[1,1],[1,0],[0,-3]],[[2843,6581],[0,-2],[-3,-3],[2,-3],[2,6],[1,-5],[1,-9],[0,-1],[0,-1],[0,-2],[0,-2],[-1,-8],[-6,1],[0,6],[-1,1],[-1,9],[-2,3],[-2,8],[1,2],[2,-1],[1,1],[3,1],[1,1],[2,-2]],[[2908,6578],[0,-3],[-2,0],[-3,-1],[-1,0],[1,2],[2,3],[0,2],[-2,4],[-3,9],[-1,3],[-1,3],[-2,4],[0,2],[1,0],[1,-1],[4,-13],[0,-1],[6,-13]],[[2851,6625],[-3,-2],[-2,2],[-1,0],[1,2],[2,1],[4,1],[1,-2],[0,-1],[-2,-1]],[[2840,6607],[0,-7],[0,-5],[0,-2],[-3,-4],[-1,-2],[-2,-2],[-2,-2],[-1,4],[-2,3],[0,5],[-1,-2],[-2,1],[-3,4],[-2,4],[3,1],[0,-3],[2,4],[0,2],[-1,0],[0,4],[3,9],[1,6],[-2,10],[2,0],[3,-3],[2,-3],[0,-5],[1,-4],[2,-8],[3,-5]],[[2871,6652],[4,-7],[4,-2],[4,-8],[2,-3],[0,-3],[0,-12],[-1,-7],[0,-6],[-1,1],[-1,5],[-2,2],[0,1],[3,1],[0,6],[1,5],[0,6],[-3,6],[-3,5],[-3,1],[-4,6],[-2,0],[-2,-1],[1,3],[0,5],[1,0],[2,-4]],[[2819,6723],[4,-1],[2,0],[1,1],[5,0],[4,1],[0,-3],[0,-1],[-8,-2],[-8,-4],[-5,-3],[-2,-1],[-1,2],[-5,9],[1,-1],[4,-5],[2,1],[2,3],[1,3],[-1,1],[1,4],[3,-4]],[[2855,6676],[-1,-1],[-2,6],[-2,2],[3,4],[1,3],[0,8],[1,4],[-1,4],[1,4],[-1,4],[-2,3],[-5,13],[-8,3],[-4,0],[2,3],[2,-1],[3,-1],[4,-1],[2,-3],[3,-6],[2,-2],[0,-1],[0,-1],[1,-2],[2,-2],[3,-4],[1,-11],[-4,-6],[0,-16],[-1,-3]],[[5527,7768],[1,0],[3,2],[3,1],[2,-1],[1,-1],[0,-1],[0,-5],[-2,-5],[-2,-5],[-2,-4],[0,-3],[0,-4],[0,-3],[0,-2],[0,-1],[3,-2],[3,-3],[2,-4],[3,-5],[1,-1],[0,-2],[-1,-2],[-2,0],[-3,0],[-1,1],[-1,-1],[-1,-1],[0,-1],[3,-6],[4,-8],[0,-3],[0,-3],[-1,-2],[-2,0],[-1,2],[-1,0],[-2,-1],[-1,-3]],[[5533,7691],[-1,0],[-2,0],[-1,-1],[-1,1],[-1,1],[-1,-1],[0,-2],[1,-3],[1,-5],[0,-4],[-1,0],[-2,3],[-1,1],[-1,-1],[-3,-3],[-2,-3],[0,-2],[-1,-3],[0,-1],[0,-6],[-4,-1],[-1,-1],[0,-1],[0,-7],[0,-4],[3,-6],[0,-2],[-1,-1],[-1,-3],[-1,-1]],[[5512,7635],[-3,2],[-1,0],[-5,6],[-2,3],[-4,3],[-2,3],[-1,3],[-2,1],[-2,-1]],[[5490,7655],[-2,2]],[[5488,7657],[2,1],[0,1],[0,2],[-1,2],[-6,9],[-3,6],[-1,2],[0,6],[0,2],[-5,2],[-5,8],[-5,7],[-1,2],[-3,6],[-3,5],[-3,4],[-2,3],[-2,6],[-1,7],[-1,7],[-1,3],[-2,1],[-4,8],[-4,5],[0,5],[0,9],[1,10],[1,1],[2,1],[2,0],[2,-1],[3,-7],[2,-3],[2,-1],[2,3],[3,6],[2,3],[7,-1],[3,5],[6,-6],[3,-1],[1,1],[2,-1],[4,-2],[1,0],[1,0],[3,2],[1,0],[3,-5],[2,0],[2,2],[1,2],[4,-1],[3,0],[1,0],[2,0],[2,-1],[2,-1],[5,-1],[2,-3],[1,-3],[0,-1],[0,-2],[2,-2],[3,-1],[1,0]],[[3254,6213],[0,1],[-1,1],[0,1],[2,-1],[0,-1],[-1,-1]],[[5781,8418],[4,-5],[1,-1],[2,2],[1,0],[4,1],[2,-2],[1,-4],[2,-2],[1,-1],[5,3],[2,2],[1,0],[6,-4],[2,-1],[1,-2],[0,-2],[-1,-2],[0,-3],[1,-4],[2,-2],[4,4],[2,1],[2,0],[2,2],[1,2],[2,0],[3,0],[5,0],[6,-3],[1,-1],[3,-4],[1,-2],[1,-1],[2,-1],[2,-2],[2,1],[0,-1],[1,-1],[0,-3],[0,-7],[-1,-3],[-1,-1],[-1,-2],[0,-1],[2,-3],[2,-5],[1,-3],[0,-2],[-3,-7],[-1,-1],[-1,-3],[0,-3],[0,-2],[5,-5],[4,-3],[1,-1],[0,-1],[-2,-5],[0,-2],[3,-2],[1,-3],[2,-6],[3,-6],[6,-4],[5,-4],[0,-1],[1,-2],[-1,-4],[-1,-4],[-1,-3],[2,-1],[5,0],[6,0],[7,-6],[0,-2],[-1,-2],[1,-2],[0,-2],[6,-6],[1,-1],[0,-3],[0,-2],[-2,-1],[-2,0],[-3,-3],[-1,-3],[-5,-5],[-3,-2],[-2,0],[-6,1],[-2,2],[-1,2],[-2,1],[-3,0],[-4,0],[-1,-1],[0,-2],[-2,-5],[-1,-3],[1,-1],[1,-3],[3,-4],[2,-4],[1,-2],[0,-2],[-1,-2],[0,-4],[3,-5],[-1,0],[0,-7],[0,-6],[0,-2],[2,-1],[1,-2],[2,-6],[0,-1]],[[5882,8185],[-6,0],[-6,0],[-3,-3],[-2,1],[-2,0],[-3,-1],[-4,-6],[-2,-3],[-3,-5],[0,-2],[-2,-5],[-1,-5],[0,-4],[1,-4],[1,-3],[0,-3],[-1,-2],[-1,-3],[-3,0],[-3,3],[-1,4],[-2,3],[-2,2],[-2,0],[-5,-1],[-5,-1],[-5,-1],[-2,-1],[-3,-2],[-2,2],[-2,5],[-1,5],[-1,2],[-1,0],[-1,0],[-2,-1],[-1,-2],[-1,0],[-2,-2],[-2,-1],[-1,-5],[-2,1],[-1,1],[-1,5],[-2,1],[-3,0],[-4,1],[-3,1],[-1,0],[-2,-2],[-1,0],[-5,1],[-1,0],[-1,-3],[-1,-3],[-1,0],[-1,1],[1,4],[-3,2],[-4,0],[-3,0],[-1,0],[-1,1],[-4,8],[-2,0],[-3,0],[-5,1],[-6,2],[-3,0],[-1,2],[-4,1],[-9,3],[-4,1],[-6,0],[-9,0],[-5,0],[-3,-1],[-3,-1],[-5,-1],[-2,1],[-3,-1],[-4,-1],[-1,-1],[-1,-4],[-4,-6],[-4,-5],[-1,0],[-3,2],[-2,1],[-2,0],[-2,0],[-1,-2],[0,-4],[0,-1]],[[5655,8151],[-2,6],[0,5],[1,3],[2,3],[-1,4],[1,5],[0,4],[0,2],[-1,2],[-3,2],[-1,2],[-4,2],[-3,3],[-1,1],[0,2],[1,1],[3,6],[3,5],[2,2],[10,6],[1,2],[1,4],[0,3],[0,5],[-1,7],[-1,5],[-2,9],[-5,19],[-3,20]],[[5652,8291],[2,-2],[5,0],[4,1],[2,1],[1,-1],[3,1],[2,0],[2,-1],[2,-2],[4,2],[4,3],[4,0],[1,1],[1,7],[1,1],[5,0],[2,1],[2,3],[3,3],[2,0],[3,2],[1,-2],[1,-2],[-1,-3],[0,-1],[2,-1],[3,0],[2,1],[0,1],[0,3],[0,2],[-2,2],[-2,1],[-2,0],[0,1],[1,3],[1,5],[2,4],[1,2],[0,1],[0,3],[0,4],[2,7],[2,5],[3,2],[3,1],[3,2],[1,3],[0,2],[1,2],[1,1],[8,-1],[2,4],[0,2],[2,1],[1,1],[0,2],[-2,0],[-6,1],[-1,1],[1,2],[1,5],[1,5],[1,5],[0,2]],[[5738,8390],[1,1],[4,1],[1,1],[4,6],[3,1],[7,-2],[3,0],[1,0],[3,0],[1,0],[1,6],[2,2],[5,8],[4,3],[2,1],[1,0]],[[2559,6187],[-2,-8],[0,3],[1,6],[1,2],[1,2],[0,2],[1,-1],[0,-2],[-2,-4]],[[2557,6216],[-2,-1],[1,3],[1,3],[1,8],[1,0],[1,0],[-3,-13]],[[2530,6099],[-1,0],[-5,1],[-3,-1],[0,15],[1,22],[0,16],[0,16],[0,12],[1,16],[0,14]],[[2523,6210],[0,5],[1,4],[2,2],[3,-4],[1,-1],[1,0],[2,3],[2,6],[4,12],[2,9],[1,2],[3,0],[2,0]],[[2547,6248],[-1,-7],[1,-1],[1,1],[4,0],[1,-7],[0,-6],[-3,-16],[-1,-6],[-1,-8],[2,-5],[-2,-7],[-1,-5],[0,-7],[1,-13],[-1,-19],[-3,-8],[-2,-4],[-2,-8],[-4,-2],[-5,-14],[-1,-3],[0,-4]],[[3202,7044],[-3,-2],[-1,0],[0,1],[2,2],[3,4],[-1,-5]],[[3384,4022],[1,10],[-1,8],[0,2],[-9,10],[-7,9],[-10,12],[-12,0],[-13,-1],[-13,-5],[-12,-5],[-5,-3],[-12,-4],[-7,-3],[-2,-9],[-2,-14],[-3,-9],[-3,-8],[-4,-13],[0,-14],[0,-15],[-3,-19],[-3,-17],[-2,-17],[-2,-11],[-1,-3]],[[3133,3869],[-4,-2],[-7,-2],[-3,0],[-2,1],[-1,1],[-2,2],[0,2],[0,4],[0,5],[0,8],[-2,9],[0,3],[0,5],[-1,8],[-2,5],[-1,7],[0,6],[-2,8],[-1,9],[0,9],[-3,10],[-3,10],[-3,2],[-1,1],[0,3],[0,5],[0,2],[2,5],[0,1],[0,1],[-6,6],[-1,2],[0,3],[0,2],[1,2],[1,2],[-2,5],[1,4],[-1,2],[0,2],[1,1],[3,1],[1,5],[0,3],[0,3],[-4,7],[0,1],[4,9],[2,6],[1,2],[0,1],[-1,1],[-1,3],[-2,2],[-2,3],[-2,5],[-3,4],[-2,4],[-1,3],[0,4],[0,5],[-2,9],[0,6],[-1,7],[0,4],[-1,5],[0,4],[-1,4],[1,2],[1,2],[-1,1],[-5,5],[-1,1],[-1,10],[-4,9],[0,6]],[[3069,4175],[0,1],[0,2],[0,4],[-2,3],[-1,3],[-1,2],[1,3],[3,6],[2,1],[0,2],[1,3],[4,8],[1,5],[2,3],[3,2],[0,2],[0,6],[0,4],[1,2],[2,3],[2,2],[0,1],[0,1],[-2,3],[-3,3],[-3,-1],[-1,3],[-1,2],[-5,23],[-1,6],[0,2],[4,12],[1,4],[2,5],[0,2],[-4,10],[-1,4],[0,4],[0,6],[2,2],[1,5],[1,4],[0,1],[2,3],[1,3],[2,3],[1,3],[0,6],[1,2],[2,2],[1,2],[-1,4],[-1,5],[-1,2],[-2,11],[-1,6],[1,2],[1,3],[0,5],[1,7],[0,24],[0,5],[1,3],[2,4],[1,2],[2,2],[0,5],[1,2],[1,4],[-4,13],[-3,12],[-3,11],[-4,13],[-2,8],[-3,10],[-3,9],[-3,13]],[[3067,4553],[3,0],[7,0],[6,-2],[4,-1],[2,-2],[0,-3],[2,-2],[1,1],[2,0],[3,3],[3,2],[2,3],[1,2],[3,9],[3,4],[2,2],[4,1],[2,-2],[2,0],[1,5],[2,6],[5,6],[2,2],[2,3],[2,0],[2,2],[11,17],[4,5],[3,0],[2,1],[4,3],[9,2],[6,1],[2,-2],[3,0],[1,4],[2,1],[1,0],[2,-4],[1,-5],[-1,-3],[0,-6],[1,-7],[-1,-6],[-2,-8],[-1,-3],[0,-3],[0,-5],[1,-7],[2,-11],[0,-7],[-1,-5],[-1,-4],[0,-4],[1,-2],[1,-2],[0,-3],[0,-4],[1,-4],[2,-4],[1,-4],[0,-4],[0,-2],[1,-1],[0,1],[1,1],[1,0],[1,-6],[0,-1],[1,-4],[0,-3],[3,-2],[2,-1],[1,-2],[3,-5],[2,-3],[3,-3],[1,-4],[1,-7],[5,-2],[5,-1],[4,-2],[4,4],[3,-1],[2,-2],[2,-2],[2,-3],[3,-5],[3,-1],[2,2],[1,1],[2,-1],[1,-5],[0,-3],[2,-2],[3,-6],[2,-3],[2,0],[5,-4],[5,-4],[2,0],[3,0],[1,-1],[1,-5],[4,-9],[2,-4],[2,-3],[6,0],[2,-1],[3,1],[8,1],[1,1],[5,-4],[5,-6],[3,-5],[3,-2],[1,-5],[1,-4],[1,-5],[-1,-4],[-1,-2],[0,-3],[0,-5],[2,-4],[1,-5],[1,-8],[1,-3],[0,-27],[-3,-1],[-5,0],[1,-2],[4,-11],[4,-9],[1,-15],[0,-9],[1,-13],[0,-8],[10,-1],[11,-1],[13,-1],[12,-1],[1,0],[2,1],[1,2],[1,0],[0,-3],[0,-4],[0,-5],[-4,-9],[0,-3],[1,-12],[1,-10],[1,-9],[1,-3],[4,-4],[6,-9],[2,-1],[2,1],[1,-3],[1,-6],[3,-16],[2,-10],[1,-4],[2,-1],[-1,-2],[-1,0],[-1,-2],[-1,-11],[-3,-15],[-1,-11],[1,0],[0,-3],[0,-4],[-1,-1],[-1,-1],[-2,-9],[-3,-11],[-2,-12],[-2,-6],[3,-6],[4,-8],[0,-2],[-2,-2],[-2,0],[-1,-4],[-1,-2],[-2,-1]],[[3653,3584],[-2,-2],[0,14],[1,4],[1,4],[2,2],[1,-3],[-1,-7],[-2,-8],[0,-4]],[[3650,3663],[0,-1],[-2,8],[3,6],[1,-2],[0,-6],[-1,-4],[-1,-1]],[[3742,3808],[0,-3],[-1,1],[-3,-1],[-1,2],[4,10],[1,-1],[1,-2],[0,-3],[0,-1],[-1,-2]],[[3774,3851],[1,-2],[-2,0],[-2,-1],[-2,-1],[-2,2],[3,3],[1,3],[0,-1],[1,-1],[2,-2]],[[3919,4408],[-1,-4],[-1,1],[-1,2],[0,2],[0,2],[1,1],[2,0],[0,-4]],[[3923,4429],[-1,-1],[0,4],[3,4],[0,6],[2,-3],[0,-2],[0,-2],[-4,-6]],[[3764,5014],[-3,-5],[1,6],[-1,5],[1,3],[1,4],[1,0],[0,-4],[0,-1],[0,-8]],[[3753,5108],[-2,-3],[0,-1],[-2,1],[0,1],[1,0],[0,5],[3,-1],[0,-2]],[[3560,5101],[-3,-1],[4,15],[3,6],[0,14],[4,11],[3,5],[5,2],[3,-8],[-4,-20],[-1,0],[-4,-11],[-5,-7],[-5,-6]],[[3621,5171],[3,-1],[3,1],[3,3],[3,1],[2,-1],[9,-3],[6,-1],[2,0],[2,-2],[1,-1],[1,-4],[-2,-5],[-1,-5],[-1,-7],[0,-2],[-1,0],[0,-6],[0,-3],[-1,-3],[-1,-5],[-2,-7],[-1,-1],[-2,-3],[-1,-3],[0,-3],[1,-3],[-1,-3],[-2,-6],[-2,-1],[-2,0],[-1,0],[-2,5],[-1,-4],[0,-4],[-1,-2],[-3,0],[-2,2],[-3,3],[0,-7],[-2,-5],[-2,-1],[-2,-1],[-2,-2],[-3,1],[-3,3],[-1,1],[-1,-3],[-7,0],[-3,-3],[-1,1],[-3,5],[0,3],[-2,7],[-1,9],[-1,7],[0,7],[2,0],[2,-1],[1,0],[0,2],[-1,2],[-3,0],[-2,4],[0,6],[0,12],[0,3],[2,3],[0,3],[0,4],[0,6],[2,5],[5,7],[6,2],[17,-6]],[[3593,5176],[-8,-11],[-3,4],[0,2],[0,2],[0,1],[1,4],[4,3],[2,0],[3,-1],[1,-2],[0,-2]],[[3626,5177],[-7,-1],[-4,2],[1,3],[3,4],[3,2],[3,2],[2,-2],[1,-3],[0,-3],[-2,-4]],[[3618,5199],[1,-3],[-4,-12],[-2,-2],[-2,0],[-3,4],[-5,-1],[-2,1],[0,6],[2,5],[4,0],[7,4],[4,-2]],[[3599,5192],[-1,-9],[-5,4],[1,9],[2,2],[2,5],[1,5],[0,8],[1,1],[0,1],[1,-1],[0,-11],[1,-7],[-3,-7]],[[3607,5206],[-4,-2],[0,2],[0,8],[1,4],[4,1],[0,1],[1,1],[1,-3],[0,-4],[-3,-8]],[[3602,5295],[-2,-2],[-2,1],[-1,7],[0,5],[2,2],[2,0],[0,-1],[2,-9],[-1,-3]],[[3431,5296],[1,-1],[1,0],[5,-3],[6,-2],[1,1],[1,2],[0,5],[0,3],[-1,3],[-1,4],[-2,5],[-2,1],[1,2],[1,3],[1,1],[1,2],[0,6],[1,1],[1,0],[1,-2],[5,-5],[2,1],[7,1],[1,3],[2,1],[3,3],[1,0],[1,-1],[1,1],[2,2],[1,-2],[1,-3],[1,-3],[1,-1],[2,1],[2,-1],[0,-2],[0,-2],[1,-2],[2,0]],[[3483,5318],[0,-1],[1,-1],[1,-3],[3,-2],[4,-3],[1,0],[2,-1],[1,-1],[1,2],[4,4],[2,3],[1,2],[1,2],[1,0],[1,-1],[0,-1],[1,-1],[4,-2],[1,0],[2,1],[2,3],[1,1],[2,-3],[0,-4],[1,-1],[1,0],[3,0],[2,-2],[1,1],[2,1],[1,3],[2,3],[3,3],[1,4],[2,5],[1,3],[0,4],[3,13],[1,2],[0,4],[1,5],[0,3],[1,4],[2,3],[1,2],[2,6],[1,5],[3,11],[0,3],[2,2],[0,2],[2,3],[1,3],[1,3],[1,4],[2,2],[1,2]],[[3565,5418],[2,10],[1,4],[2,0],[4,-5],[3,-7],[4,-25],[1,-22],[1,-12],[5,-24],[0,-5],[1,-5],[1,-6],[2,-10],[0,-2],[-1,-2],[1,0],[2,-2],[1,-6],[1,-4],[2,-6],[4,-2],[4,0],[3,-4],[3,-4],[2,-13],[-1,-9],[1,-6],[-2,-3],[-3,-4],[0,-2],[-6,-10],[-2,-5],[-3,-6],[-3,-13],[-5,-11],[-2,-3],[-3,-1],[-1,-2],[-4,-9],[-5,-3],[0,-5],[-3,-13],[-3,-7],[-1,-2],[-5,-12],[0,-5],[0,-10],[-3,-6],[-3,-3],[0,-8],[-1,-3],[-1,-2],[-6,2],[-9,-8],[-3,-3],[10,0],[3,-5],[7,3],[8,11],[3,3],[7,7],[2,5],[5,6],[1,3],[3,3],[1,-4],[0,-2],[-2,-4],[1,-3],[1,-4],[1,-5],[0,-3],[1,-7],[3,-9],[0,-3],[0,-4],[1,-3],[1,-2],[6,-9],[4,5],[2,2],[2,2],[3,1],[2,-2],[6,-3],[3,3],[8,8],[-3,-14],[-1,-12],[-2,-6],[-1,-13],[-1,-4],[-1,-4],[2,1],[1,2],[2,6],[1,9],[6,24],[1,3],[5,2],[8,20],[3,0],[2,-4],[1,-3],[1,5],[3,2],[-3,3],[-1,3],[0,4],[2,5],[-1,5],[4,6],[-1,4],[2,4],[2,4],[2,2],[0,3],[1,2],[1,0],[2,-4],[3,5],[2,2],[1,-1],[1,-2],[1,-1],[1,0],[3,3],[2,-4],[1,-1],[0,2],[-1,3],[1,1],[1,2],[4,-1],[2,-2],[2,-4],[2,0],[3,0],[1,-2],[2,0],[1,-3],[4,-5],[1,-3],[3,-2],[2,-2],[3,0],[3,0],[0,-4],[2,-1],[3,1],[2,-5],[5,-3],[4,-6],[2,1],[3,-1],[3,-12],[0,-9],[2,1],[1,4],[2,7],[3,2],[1,-2],[3,-5],[2,-4],[1,-4],[2,0],[-1,-4],[1,1],[2,2],[2,-5],[1,-6],[0,-6],[-1,-4],[-1,-2],[-1,-5],[-1,0],[-2,-2],[2,-3],[1,-3],[2,8],[2,3],[2,1],[2,-6],[0,-5],[-4,-3],[0,-4],[-1,-3],[-1,-2],[-1,-6],[0,-5],[-3,-22],[0,-4],[3,4],[5,11],[2,12],[2,12],[2,3],[1,0],[2,-1],[1,-4],[-1,-2],[-2,-6],[-1,-3],[1,-3],[5,10],[2,3],[2,-1],[4,5],[8,1],[0,5],[2,2],[4,-1],[8,-4],[3,-4],[4,-3],[2,-4],[10,-8],[7,-1],[3,4],[5,-4],[2,-4],[4,-2],[5,-1],[3,3],[9,1],[11,4],[7,-1],[7,-3],[6,-7],[4,-4],[3,-4],[4,-4],[10,-11],[3,-7],[6,-9],[6,-3],[3,-9],[3,-5],[6,-15],[7,-11],[4,-11],[9,-7],[4,-11],[6,-2],[3,-1],[3,-5],[4,-3],[6,1],[6,-1],[5,3],[12,-5],[2,-2],[2,-5],[5,-18],[2,-20],[2,-15],[3,-12],[1,-23],[2,-7],[0,-6],[1,-1],[1,-15],[-1,-6],[-1,-8],[0,-4],[0,-2],[0,-3],[0,-3],[1,-8],[0,-5],[-2,-7],[-2,-18],[-5,-31],[-5,-17],[-7,-18],[-5,-9],[-2,-1],[-1,2],[1,-5],[-1,-4],[-5,-14],[-5,-8],[-4,-15],[-1,0],[-6,-6],[-4,-5],[-4,-8],[-5,-14],[-1,-2],[-1,1],[0,-7],[-4,-10],[-1,-2],[0,3],[1,2],[0,3],[0,3],[-1,-2],[-2,-8],[0,-6],[-1,-9],[-6,-26],[-8,-22],[-1,-6],[-7,-15],[-4,-7],[-1,0],[-2,1],[-1,11],[-3,6],[-1,2],[-2,-7],[-1,-2],[-2,-1],[2,-3],[1,-4],[-2,-7],[0,-6],[-4,-8],[-2,-5],[-1,-7],[0,-6],[1,2],[1,-1],[1,-2],[-1,-3],[-1,-6],[0,-13],[0,-3],[1,-3],[1,5],[1,-1],[-3,-36],[1,-16],[0,-19],[2,-18],[1,-16],[1,-1],[-3,-19],[-2,-18],[-2,-15],[-1,-16],[-1,-8],[-1,-8],[2,-18],[0,-4],[-3,-8],[-4,-4],[-2,-4],[-5,-16],[-2,-22],[0,-12],[1,-25],[-1,-10],[-1,-7],[-2,-4],[-5,-5],[-3,-13],[-2,-14],[-3,-5],[0,-8],[-2,-8],[-6,-12],[-4,-4],[-1,-3],[-2,-8],[-3,-11],[-3,-16],[1,-5],[0,-1],[1,-18],[0,-4],[-4,-5],[-12,-9],[-4,-4],[-8,-16],[0,-3],[0,-6],[2,-3],[-2,-3],[-1,-6],[-2,0],[-13,0],[-7,-1],[-4,0],[-1,1],[-2,3],[-1,3],[1,4],[0,3],[-2,0],[-2,-1],[-1,-3],[1,-2],[0,-3],[1,-3],[-1,-3],[-4,-1],[-5,-3],[-5,-1],[-5,-2],[-2,3],[2,1],[3,-1],[3,2],[0,3],[-5,3],[-5,-2],[-3,-4],[-6,1],[-7,-3],[-2,-3],[1,-6],[1,-1],[2,-3],[-2,-2],[-1,-1],[-8,-3],[-7,-11],[-3,-2],[-3,-4],[0,-5],[-1,-2],[-2,0],[-4,2],[-5,0],[-3,-2],[-19,-18],[-6,-7],[-8,-15],[-12,-17],[-7,-9],[-1,-3],[-1,0],[-2,-2],[0,-2],[2,0],[-1,-6],[-2,-4],[-5,-10],[-1,1],[1,5],[-2,0],[-4,2],[-1,-2],[0,-5],[-1,-3],[-2,0],[-3,1],[-2,4],[1,-7],[5,-2],[2,-2],[1,-3],[-4,-12],[-3,-2],[-1,-2],[2,0],[1,-3],[-1,-14],[-2,-3],[-1,0],[0,-2],[1,-5],[1,-3],[0,-7],[0,-5],[-1,-5],[2,-10],[1,-11],[1,-3],[0,-5],[-1,-4],[0,-6],[-2,-10],[1,-16],[0,-14],[-1,-8],[-1,-6],[-3,-7],[0,-8],[-6,-7],[-7,-10],[-6,-12],[-7,-16],[-8,-26],[-8,-36],[-8,-27],[-4,-10],[-5,-11],[-6,-12],[-9,-13],[-9,-12],[-4,-5],[-3,-7],[-1,3],[1,5],[0,4],[-1,4],[2,1],[3,-3],[2,2],[1,2],[3,2],[7,12],[4,5],[3,8],[1,4],[-1,8],[2,3],[4,-1],[0,2],[0,3],[1,6],[4,5],[3,6],[-1,16],[1,1],[2,-2],[1,1],[1,7],[-1,3],[-2,1],[-8,-8],[-3,1],[0,6],[-4,3],[-2,5],[0,3],[-1,2],[0,-6],[0,-6],[4,-7],[-1,-3],[-2,-3],[-1,-7],[0,-9],[-1,2],[-1,2],[0,-10],[-3,-4],[0,-3],[0,-5],[-1,-3],[-6,-8],[-6,-5],[-1,-3],[-1,-6],[-1,-6],[-2,-6],[-2,-11],[0,-4],[1,-7],[1,-5],[-2,-3],[-2,-6],[-2,-7],[-5,-25],[-4,-15],[-3,-7],[-4,-8],[-13,-20]],[[3517,3240],[-1,1],[-1,1],[-2,2],[0,1],[-1,2],[1,7],[0,19],[0,4],[1,2],[2,3],[3,5],[2,6],[3,5],[-1,3],[-2,4],[-4,2],[-3,5],[-3,5],[-2,6],[-1,7],[-1,5],[-1,2],[-1,1],[-2,3],[-1,2],[-2,2],[-3,1],[-3,3],[-5,6],[-3,7],[-1,5],[-2,3],[-8,6],[-4,6],[-2,-2],[-2,2],[-2,3],[-1,3],[-1,2],[-1,3],[0,3],[-3,4],[-3,5],[-1,2],[-1,-1],[0,-2],[-1,-1],[-1,-2],[-1,-2],[-2,-3],[-1,-2],[-3,0],[-1,0],[0,1],[0,4],[0,9],[-1,3],[-2,4],[-2,5],[-6,10],[-9,15],[-3,5],[-3,0],[-3,0],[-2,-2],[-2,-7],[-1,-1],[-4,0],[-5,1],[-2,4]],[[3483,3711],[0,8],[4,12],[1,6],[-1,3],[1,11],[3,20],[1,13],[-1,6],[0,4],[1,4],[1,1],[-4,4],[-2,4],[-2,3],[-3,2],[-1,-1],[-1,-1],[-3,-2],[-3,-4],[-2,-1],[-2,-1],[-4,-2],[-2,1],[-2,1],[-2,2],[0,5],[0,4],[-1,6],[-2,4],[0,3],[0,3],[0,3],[0,3],[0,3],[-1,3],[1,4],[-1,5],[-1,4],[0,4],[0,4],[-1,4],[0,4],[0,4],[1,4],[-1,3],[-2,2],[-1,4],[0,6],[-1,3],[-2,3],[-1,0],[-3,1],[-2,0],[-3,0],[-2,1],[-1,2],[-2,3],[-1,5],[-1,1],[-2,-1],[-1,-2],[-1,-3],[-1,-3],[-2,0],[-2,-1],[-2,-1],[-3,0],[-2,2],[-4,1],[-2,1],[-3,-1],[-2,1],[-2,1],[-2,0],[-2,3],[-3,2],[-1,-1],[-1,-2],[-2,1],[-2,1],[-1,4],[0,2],[1,3],[0,3],[0,3],[0,3],[1,3],[0,3],[0,3],[0,3],[-1,3],[0,3],[1,4],[1,4],[0,3],[0,2],[0,3],[1,5],[0,7],[-1,5],[0,1],[-1,2],[1,1],[-1,2],[0,2],[1,2],[-1,3],[-1,1],[-1,1],[0,4],[-1,4],[0,3],[0,3],[-1,2],[-1,3],[-1,2],[0,3],[-1,4]],[[3067,4553],[-3,0],[-4,1],[-4,0],[-3,-3],[-4,-4],[-2,0],[-1,-1],[-2,1],[-1,2],[-3,4],[-1,-1],[-2,-2],[0,9],[0,15],[0,13],[1,10],[0,12],[0,9],[1,3],[1,4],[-1,5],[0,4],[0,3],[1,3],[-2,-1],[0,-1],[-1,-2],[-3,-4],[-1,-3],[-2,-2],[-3,-6],[-2,-3],[-2,-2],[-3,-6],[-3,-2],[-7,-1],[-8,0],[-7,1],[-1,0],[0,5],[0,4],[-3,4],[0,5],[0,3],[-1,4],[-2,3],[-2,1],[-4,2],[-6,3],[-5,0],[-6,0],[3,8],[4,8],[0,8],[-3,6],[-1,4],[-3,6],[-2,3],[-2,5],[0,3],[0,2],[-1,2],[-1,1],[-2,2],[-1,3],[0,3],[-1,3],[-1,3],[0,3],[-1,4],[-1,3],[-1,2],[-2,3],[0,2],[2,1],[0,3],[0,3],[-1,1],[-2,1],[-2,5],[-1,2],[-1,2],[-1,2],[1,1],[0,1],[0,3],[0,3],[0,2],[1,0],[1,0],[1,1],[2,1],[1,0],[1,2],[0,2],[-1,6],[-1,2],[0,3],[0,6],[1,4],[2,4],[5,9],[5,6],[2,1],[2,2],[1,3],[0,4],[0,3],[-1,5],[-1,6],[-1,4],[1,4],[1,5],[3,8],[2,9],[1,3],[0,5],[1,11],[1,6],[0,3],[0,2],[2,1],[3,2],[3,3],[4,6],[3,7],[3,2],[4,6],[3,4],[1,2],[3,2],[5,1],[4,1],[2,2],[4,1],[2,2],[2,0],[5,2],[2,3],[1,4],[2,3],[2,1],[3,0],[3,0],[3,1],[2,-3],[0,-3],[3,-3],[1,0],[2,1],[2,-3],[1,1],[1,1],[0,4]],[[3056,4940],[1,2],[1,12],[1,19],[2,18],[2,19],[1,20],[2,21],[2,16],[1,15],[1,8],[1,12],[0,10],[1,3],[0,2],[-1,4],[0,1],[0,2],[0,2],[-2,2],[0,1],[-1,2],[0,2],[-1,3],[0,2],[-1,2],[0,2],[0,3],[1,2],[-1,2],[0,3],[-1,2],[-1,2],[-2,2],[-2,4],[-3,4],[-3,6],[-1,4],[0,9],[0,10],[1,15],[0,7],[2,1],[1,0],[2,0],[2,1],[1,1],[1,1],[1,1],[1,0],[1,1],[1,1],[1,1],[2,1],[1,-2],[1,-2],[1,-1],[1,1],[1,-1],[0,-1],[1,0],[1,0],[1,0],[1,1],[0,1],[-1,1],[0,2],[0,2],[0,3],[0,4],[0,2],[-1,3],[-1,3],[-2,2],[-1,1],[-1,-1],[-1,0],[-1,1],[-1,0],[-2,0],[-1,1],[-3,-1],[-1,1],[-1,0],[-2,-1],[0,14],[0,14],[0,9],[2,0],[1,2],[3,0],[2,2],[1,0],[2,-1],[2,-2],[2,0],[6,0],[5,0],[7,0],[6,0],[6,0],[2,0],[-1,3],[-1,4],[0,3],[1,4],[0,1],[2,-2],[2,-5],[1,-4],[1,-2],[2,0],[1,0],[2,2],[3,8],[3,6],[1,2],[2,2],[1,1],[1,0],[2,-2],[1,-3],[3,-11],[2,-8],[1,-5],[0,-13],[0,-11],[0,-1],[1,0],[5,2]],[[3142,5254],[7,-13],[5,-10],[3,-3],[1,-1],[3,1],[4,1],[1,1],[2,4],[4,4],[2,2],[1,0],[1,0],[2,-3],[2,-5],[-1,-5],[0,-4],[2,1],[2,5],[1,5],[3,3],[2,6],[2,5],[2,3],[4,3],[2,2],[3,0],[1,2],[3,5],[1,3],[1,1],[3,0],[2,1],[3,4],[3,5],[1,9],[1,7],[1,2],[1,1],[1,1],[2,1],[5,4],[3,4],[3,1],[1,1],[1,4],[0,7],[0,4],[-6,1],[-3,0],[-6,1],[-3,2],[0,1],[0,1],[0,3],[1,6],[-1,7],[-3,12],[-2,11],[0,8],[0,9],[0,5],[-2,5],[-8,13],[-3,7],[-1,4],[-3,9],[1,2],[2,0],[1,-2],[2,-5],[1,-1],[1,0],[8,0],[2,0],[1,-2],[1,-2],[1,-5],[1,-3],[3,0],[5,0],[3,1],[1,-2],[2,-1],[4,3],[1,0],[1,-1],[5,-10],[2,-4],[3,-5],[3,0],[2,4],[1,16],[1,4],[1,1],[2,1],[1,2],[2,3],[2,1],[7,-3],[2,1],[7,5],[8,5],[2,6],[3,2],[2,5],[2,-1],[3,0],[2,1],[1,1],[1,2],[2,7],[2,2],[2,3],[2,3],[2,4],[0,3],[0,2],[-1,6],[-1,4],[-1,2],[-1,0]],[[3312,5483],[3,2],[2,-2],[3,0],[2,1],[2,-1],[2,4],[2,-1],[1,0],[1,-3],[1,-3],[2,-3],[0,-6],[0,-5],[-1,-5],[0,-4],[-1,-4],[-1,-4],[-1,-2],[0,-2],[1,-1],[2,-1],[2,0],[2,-1],[2,0],[2,-4],[1,-2],[0,-1],[0,-4],[-1,-4],[1,-2],[1,-2],[2,-7],[0,-3],[1,-1],[0,-2],[0,-3],[-1,-3],[-2,-4],[0,-3],[-2,-2],[-3,-5],[1,-7],[0,-3],[0,-3],[-1,-4],[-2,-11],[-1,-6],[-1,-13],[0,-4],[1,-6],[2,-13],[1,-2],[3,-3],[0,-9],[0,-9],[0,-4],[0,-1],[1,-1],[1,-1],[0,-3],[0,-3],[2,-1],[2,-1],[1,-4],[3,-6],[1,-1],[1,-3],[2,-5],[4,-2],[4,-2],[1,-3],[2,-3],[1,0],[1,0],[1,3],[2,2],[2,-1],[2,1],[1,1],[0,2],[-1,6],[1,1],[3,1],[0,3],[0,1],[1,2],[1,0],[1,-1],[1,0],[2,-1],[1,-2],[1,0],[2,0],[0,1],[1,2],[0,5],[1,0],[2,1],[2,2],[3,0],[3,0],[1,1],[1,3],[3,8],[1,2],[2,1],[1,0],[2,1],[2,2],[1,-1],[1,-4],[1,-1],[1,0],[4,-2],[2,1],[2,1],[2,1],[1,-1],[2,1],[1,1]],[[3347,5937],[-1,-1],[-2,2],[-1,3],[0,9],[1,1],[3,-7],[2,-3],[-2,-4]],[[8194,5466],[4,0]],[[8198,5466],[0,-2],[2,-7],[1,-6],[0,-11],[2,-4],[-1,-1],[-2,-1],[-2,1],[-1,2],[-2,11],[-1,6],[0,7],[0,5]],[[8194,5466],[-2,-2],[-2,-4],[-2,-2],[-1,-2],[0,-3],[0,-7],[1,-5],[1,-2],[0,-2],[0,-2],[-1,-5],[-1,-6],[-1,-4],[-2,-4],[-1,0],[-1,1],[-2,4],[-2,5],[-1,3],[-2,0],[-1,3],[0,3],[-1,3],[-1,4],[-1,3],[-3,2],[0,1]],[[8168,5448],[3,0],[3,1],[4,3],[3,4],[3,4],[2,5],[3,4],[5,4],[1,0],[0,-3],[-1,-4]],[[7545,6783],[-1,-2],[0,-3],[-1,-4],[1,-3],[1,-4],[3,-3],[3,0],[2,1],[2,0],[1,-5],[1,-4],[-1,-5],[-1,-4],[0,-2],[0,-1],[1,-3],[1,-3],[0,-4],[-1,-2],[-1,-1],[-2,0],[-1,0],[-2,-1],[-2,-1],[-2,-1],[-5,0],[-1,3],[-1,0],[-4,-4],[-4,1],[-8,-2],[-3,0],[-4,0],[-1,1],[-3,3],[-3,3],[-3,-2],[-1,-1],[-2,-5],[-5,-2],[-5,-1],[-2,0],[-3,1],[0,1],[0,1],[0,1],[-1,1],[-2,1],[-3,1],[-1,1],[-5,-2],[-3,3],[-4,4],[-1,2],[-1,6],[-1,2],[-1,2],[-1,2],[1,3],[3,4],[0,1]],[[7468,6757],[2,9],[2,3],[2,4],[2,7],[3,7],[3,7],[3,6],[1,3],[4,3],[2,1],[2,4],[2,2],[3,1],[3,0],[3,-1],[4,-2],[0,-2],[0,-3],[0,-3],[0,-1],[0,-1],[4,0],[4,0],[2,0],[5,-3],[2,-2],[2,-1],[1,0],[2,3],[2,3],[2,0],[1,-1],[1,-2],[4,-2],[3,-2],[1,-2],[0,-7],[0,-2]],[[5701,4159],[0,-3],[-1,-4],[1,-3],[1,-4],[1,-4],[2,-2],[1,-6],[1,-6],[2,-5],[6,-12],[1,-5],[0,-4],[4,-8],[1,-3],[-1,-5],[4,-17],[2,-10],[2,-1],[7,-11],[5,-8],[7,-6],[5,-3],[2,-3],[2,-3],[1,-5],[0,-8],[0,-6],[5,0],[5,0],[1,-1],[1,-2],[0,-3],[0,-6],[0,-4],[0,-5],[-1,-6],[0,-6],[1,-3],[4,-9],[2,-5],[1,-9],[2,-3],[0,-1],[4,-1],[10,-3],[6,-4],[5,-3],[2,-1],[1,-1],[-1,-8],[1,-2],[0,-2],[1,-2],[1,-1],[4,-1],[2,-4],[1,-3]],[[5815,3905],[-6,-1],[-4,-3],[-2,-7],[-2,-5],[-4,-3],[-5,-2],[-4,-2],[-5,-5],[-5,-11],[-3,-6],[0,-3],[-1,-2],[-2,-2],[-1,-3],[-1,-2],[-1,-2],[-2,0],[-1,-2],[-1,-4],[-2,-2],[-2,-1],[-3,-2],[-2,-4],[-1,-2],[-2,0],[-1,-3],[-3,-8],[0,-3],[-4,-27],[-2,-4],[-4,-5],[-3,-7],[-2,-4],[-1,-2],[-8,-3],[-2,-2],[-4,-3],[-1,-2],[0,-8],[-3,-13],[-2,-9],[-1,-7],[-2,-10],[-2,-3],[-2,-3],[-3,-2],[-3,-1],[-4,1],[-2,-1],[-4,-3],[-3,0],[-5,2],[-5,2],[-2,0],[-4,6],[-2,0],[-4,1],[-2,1],[-2,3],[-4,7],[-4,5],[-4,3],[-3,1],[-4,-1],[-2,-1],[-1,-1],[-2,-2],[-2,-6],[-2,-7],[0,-5],[-2,-11],[-3,-12],[-1,-3],[-1,-3],[-2,-2],[-7,-10],[-4,-11],[-2,-3],[-3,-2],[-2,-1],[-1,-2],[-2,-5],[-1,-2],[-1,-1],[-4,1],[-2,0],[-10,-1],[-4,2],[-2,1],[-3,-3],[-2,2],[-1,4],[-1,10],[0,8],[2,6],[2,4],[2,6],[0,2],[0,3],[-1,4],[0,5],[-2,11],[-3,14],[-4,15],[-1,4],[-2,7],[-9,13],[-2,2]],[[5554,3757],[0,1],[0,13],[0,16],[0,17],[0,16],[0,17],[0,16],[0,17],[0,16],[0,17],[0,14],[7,0],[8,0],[9,0],[4,0],[0,2],[0,10],[0,24],[0,23],[0,24],[0,23],[0,24],[0,23],[0,24],[0,23],[0,12],[7,0],[8,3],[14,4],[12,4],[8,3],[10,3],[3,1],[1,0],[2,-2],[4,-11],[3,-9],[0,-4],[1,0],[1,0],[2,2],[4,9],[1,2],[3,4],[4,5],[3,3],[3,2],[2,0],[1,-3],[2,-1],[7,11],[3,2],[9,2],[1,0]],[[5634,5813],[2,-7],[1,-3],[8,-17],[2,-4],[4,-12],[2,-8],[3,-12],[1,-7],[-1,-5],[0,-16],[-1,-5],[-4,-8],[0,-4],[1,-3],[1,-2],[1,-1],[-1,-7],[2,-3],[2,-2],[7,-2],[3,-1],[3,-1]],[[5670,5683],[2,-1],[0,-2],[-1,-9],[1,-5],[2,-5],[3,-2],[2,-1],[8,-2],[3,-3],[4,-10],[5,-9],[2,-5],[0,-5],[-2,-5],[0,-2],[3,-5],[2,-6],[6,-6],[9,-9],[4,-7],[1,-4],[2,-6],[4,-4],[2,-4],[-2,-10],[1,-4],[0,-3],[2,-4],[1,-5],[2,-7],[2,-3],[4,-1],[2,-3],[4,-5],[4,-4],[1,-4],[1,-2],[1,-4],[1,-3],[0,-7],[1,-9],[2,-5],[2,-5]],[[5761,5478],[-8,5],[-2,0],[-1,-1],[-4,-6],[-2,-1],[-1,1],[-4,1],[-13,5],[-9,4],[-3,2],[-6,2],[-3,-3],[-3,-12],[-1,-2],[-5,-3],[-3,1],[-6,-3],[-9,4],[-3,-1],[-3,-2],[-6,-5],[-4,-3],[-5,-2],[-4,-4],[-3,-3],[-3,0],[-3,3],[-2,2],[-4,0],[-3,-1],[-3,-5],[-2,-3],[-2,-8],[-3,-14],[-2,-3],[-1,-1],[-14,7],[-6,1],[-4,-2],[-5,4],[-3,1],[-1,-1],[-3,1],[-4,5],[-5,2],[-4,-1],[-2,2],[-2,4],[-3,9],[-5,8],[-6,7],[-4,5],[-1,3],[-4,2],[-5,0],[-5,-3],[-7,-10],[-6,-22],[-4,-8],[-3,-2],[-1,-5],[2,-8],[0,-9],[-1,-16],[0,-12]],[[5516,5384],[-1,2],[-2,5],[0,1],[-5,-2],[-2,-2],[-1,-2],[-1,-1],[-1,3],[-2,1],[-1,-1],[-2,0],[-1,1],[-1,-1],[-2,2],[-7,5],[-2,1],[-1,0],[-4,-4],[-2,-1],[-6,-2],[-7,-2],[-2,0],[-2,-1],[-1,-3],[-1,-5],[-1,-9],[-1,-3],[0,-4],[0,-6],[0,-5],[0,-4],[-2,-8],[-2,-9],[-2,-8],[-2,-7]],[[5449,5315],[-1,5],[-1,6],[0,8],[0,1],[-1,3],[0,6],[0,3],[0,4],[-2,4],[-1,3],[-1,3],[-1,1],[-1,1],[-2,1],[-3,6],[-3,6],[-3,7],[-3,6],[-3,8],[-3,7],[-2,7],[-1,4],[1,1],[1,0],[1,0],[0,2],[-1,6],[-1,7],[-1,4],[-4,6],[-3,5],[-1,3],[-1,4],[-1,23],[-1,6],[-1,3],[-1,1],[0,2],[0,4],[1,4],[0,1],[0,3],[0,22],[0,1],[-1,2],[-1,-1],[-1,1],[-1,3],[-1,4],[1,2],[1,3],[1,2],[1,1],[4,4],[1,2],[1,2],[0,2],[2,11],[4,11],[1,3],[2,7],[1,9],[1,4],[1,4],[1,3],[4,6],[2,9]],[[5429,5617],[3,0],[4,-2],[4,-1],[3,2],[2,4],[4,3],[5,3],[1,5],[2,3],[1,3],[1,0],[0,-2],[1,-5],[2,-5],[4,-6],[1,0],[2,4],[5,3],[1,1],[4,7],[4,4],[1,0],[1,1],[5,5],[3,-1],[5,1],[8,2],[6,0],[3,1],[1,1],[1,6],[1,2],[2,3],[5,9],[3,8],[0,2],[0,1],[1,0],[1,3],[-1,4],[-5,7],[0,1],[0,1],[0,1],[2,3],[3,3],[2,1],[7,0],[6,1],[2,-1],[4,2],[4,2],[3,3],[8,0],[6,8],[2,2],[0,1],[1,1],[2,4],[4,7],[2,6],[1,4],[7,15],[3,0],[1,2],[3,10],[0,2],[2,0],[1,2],[2,2],[1,5],[0,5],[-1,5],[0,2],[1,2],[1,2],[6,5],[1,3],[1,2],[1,1],[2,-1],[1,2],[1,2],[4,4],[3,2],[4,-1],[3,-1],[2,-2],[1,0]],[[3339,7715],[-4,-2],[-3,0],[-2,2],[5,0],[2,0],[4,3],[-2,-3]],[[3159,7735],[-2,-2],[1,2],[1,5],[2,1],[-2,-6]],[[3145,7757],[-4,-3],[2,8],[1,3],[2,-1],[-1,-5],[0,-2]],[[3306,7804],[-1,-1],[0,1],[-2,3],[0,1],[2,1],[3,-1],[-1,-3],[-1,-1]],[[2953,7809],[-4,-1],[-1,1],[4,5],[4,2],[-3,-7]],[[2956,7803],[-2,-1],[-4,1],[-4,-2],[-1,0],[3,4],[5,3],[4,8],[2,0],[-2,-9],[0,-3],[-1,-1]],[[3027,7884],[-3,-1],[1,2],[3,4],[3,2],[1,0],[-2,-5],[-3,-2]],[[3302,7830],[1,0],[4,2],[2,0],[0,-2],[-3,-2],[-2,-1],[2,-2],[0,-1],[-2,-2],[-1,-3],[1,-3],[3,3],[2,0],[2,-1],[2,1],[1,1],[6,10],[0,2],[-7,-3],[0,2],[4,6],[0,3],[2,5],[2,3],[2,2],[2,1],[1,-2],[1,-4],[3,0],[4,-1],[3,-1],[0,-2],[0,-1],[-1,-3],[-1,-3],[3,-3],[-1,-1],[-4,-4],[-3,-3],[-3,-4],[-5,-6],[-8,-3],[-2,0],[-3,1],[-3,0],[-3,-2],[-3,0],[-1,0],[-2,0],[-1,1],[-2,4],[-1,3],[-2,13],[1,7],[2,6],[3,4],[2,4],[7,20],[1,4],[2,4],[3,4],[4,7],[1,1],[2,0],[3,0],[-1,-2],[0,-2],[3,-9],[0,-2],[-2,-7],[-2,-12],[-1,-6],[0,-2],[-1,-3],[-1,-3],[-5,-4],[-2,-1],[-2,-2],[-6,-6]],[[3227,7860],[1,0],[1,1],[2,5],[4,-2],[2,-2],[1,1],[1,0],[3,-3],[4,-2],[5,0],[7,1],[1,1],[7,1],[7,0],[2,-1],[1,-1],[1,-1],[-4,-4],[-4,-5],[-6,-4],[-1,-2],[0,-4],[0,-4],[1,0],[1,-2],[-1,-1],[-6,-1],[-2,1],[-2,1],[-1,4],[-2,0],[-1,0],[4,3],[-2,5],[-2,-1],[-1,2],[0,3],[2,1],[0,2],[-2,-2],[-2,-2],[-2,-1],[-2,-2],[3,-1],[-1,-1],[-2,-1],[-8,3],[-2,2],[-3,3],[-2,4],[1,1],[1,0],[0,1],[-3,1],[-5,0],[-2,1],[0,8],[-1,2],[-3,2],[-4,0],[0,3],[1,5],[2,3],[2,4],[2,3],[4,6],[0,-4],[0,-4],[-3,-8],[6,-8],[0,-2],[1,-2],[-1,-2],[0,-1],[2,-1],[0,-2]],[[3280,7907],[1,-1],[2,0],[1,0],[-2,-2],[-3,0],[-2,0],[3,11],[2,3],[6,7],[2,2],[2,1],[2,0],[-2,-5],[-3,0],[-3,-3],[-2,-4],[-2,-2],[-1,-3],[-1,-4]],[[3493,7916],[-1,-2],[-1,0],[0,2],[1,4],[1,2],[0,1],[1,2],[1,1],[1,2],[0,-4],[-3,-8]],[[3208,7942],[-1,-4],[-2,-4],[-2,0],[1,3],[-1,4],[2,0],[1,0],[2,1]],[[3209,7946],[-4,-3],[2,5],[0,1],[1,0],[1,0],[0,-3]],[[1571,7992],[-1,-2],[-1,1],[0,1],[-2,10],[1,0],[2,-4],[0,-1],[1,-3],[1,-2],[-1,0]],[[1573,8000],[-1,-1],[-4,4],[-3,5],[-1,4],[6,-8],[3,-3],[0,-1]],[[2924,7776],[4,2],[9,9],[6,3],[8,9],[5,1],[2,2],[0,8],[1,2],[3,7],[3,6],[2,9],[5,5],[7,5],[7,10],[4,3],[3,2],[2,4],[2,2],[5,5],[7,1],[6,4],[5,2],[3,4],[5,1],[13,11],[3,5],[5,10],[4,5],[2,5],[6,9],[6,11],[3,9],[5,4],[8,13],[5,6],[2,0],[5,5],[4,5],[5,5],[10,6],[9,7],[12,6],[15,9],[11,5],[9,1],[10,2],[3,0],[16,-4],[7,-5],[9,-10],[1,-3],[0,-4],[-4,2],[-4,0],[2,-2],[5,-7],[0,-8],[-3,-7],[-8,-4],[-2,-3],[-1,-4],[-2,-2],[-4,-2],[-2,-3],[-6,-5],[-3,-1],[-3,1],[-8,5],[-5,4],[-2,-2],[-2,-3],[-5,1],[-2,-1],[-3,1],[-7,-5],[2,-1],[5,3],[2,0],[5,-4],[10,-5],[2,-3],[3,-9],[1,-1],[4,0],[4,5],[3,3],[6,2],[-1,-3],[5,0],[4,-4],[-1,-3],[-3,-6],[-1,-12],[-5,-8],[-7,-7],[2,-2],[2,-1],[4,2],[3,0],[3,-2],[-1,-6],[-1,-4],[0,-3],[2,-7],[3,-2],[1,-9],[1,-5],[0,-4],[2,-3],[1,-4],[9,-1],[2,-2],[6,-1],[1,-1],[2,-2],[-7,-5],[5,-4],[5,-6],[4,1],[2,0],[4,-4],[1,-1],[1,-2],[2,0],[3,2],[5,-1],[6,-2],[0,-3],[-1,-2],[4,1],[3,-2],[1,1],[1,1],[5,4],[8,8],[1,-1],[0,-3],[1,-5],[3,-4],[3,0],[5,2],[1,-2],[2,-4],[3,-6],[-1,-2],[-2,-2],[-3,-2],[10,-1],[1,-1],[1,-2],[-1,-3],[-1,-1],[-1,1],[-4,-1],[-3,-3],[-3,-1],[-2,0],[-2,-2],[-2,-2],[-2,0],[-6,-6],[-7,-3],[-7,-5],[-7,-4],[-7,-4],[-2,0],[-2,0],[-4,-4],[-2,1],[-2,-1],[-2,1],[-2,1],[1,-4],[1,-4],[-1,-1],[-1,-2],[-4,0],[-2,2],[-2,2],[-1,3],[-2,2],[-1,-3],[0,-2],[-2,-4],[-2,6],[-3,-2],[-1,-6],[0,-2],[1,-5],[-1,-2],[-2,1],[-2,-7],[-3,-3],[-3,-7],[-4,-5],[-1,-3],[-6,-9],[-3,1],[-1,-1],[-3,-3],[0,-7],[-2,1],[-1,0],[0,-2],[-1,-1],[-3,2],[-2,-1],[-2,2],[-3,10],[-2,3],[-2,1],[-1,-2],[-1,-2],[-2,4],[-2,16],[0,3],[3,13],[6,12],[-2,0],[-6,-8],[1,2],[1,2],[2,3],[3,4],[4,1],[2,1],[2,1],[3,3],[0,2],[-2,-2],[-4,-2],[1,3],[1,1],[21,21],[4,3],[8,4],[2,3],[-2,2],[4,-1],[-1,-3],[0,-2],[0,-2],[0,-3],[3,-2],[3,-5],[-1,7],[2,4],[10,6],[8,0],[2,3],[-6,1],[-8,0],[-6,1],[-6,-1],[-8,1],[-2,-1],[-2,-4],[-2,2],[-1,0],[-1,1],[2,6],[7,9],[5,7],[1,2],[1,3],[-2,-1],[-2,-1],[-2,4],[-3,4],[0,-2],[1,-5],[-5,-10],[-3,-1],[-4,-5],[-7,-4],[-7,-8],[-9,-6],[-2,0],[-5,5],[2,2],[1,4],[-1,-1],[-1,-2],[-3,-2],[2,-4],[-1,-2],[-3,-2],[-2,-4],[-3,-2],[-2,3],[-5,-3],[-5,-1],[-1,1],[0,3],[-2,1],[-3,-1],[-1,1]],[[3135,7785],[-1,1],[-1,1],[-1,0],[-1,-1],[0,-1],[-1,0],[-2,1],[-1,2],[-1,2],[-1,2],[1,2],[0,1],[1,2],[-1,3],[-1,1],[0,2],[0,2],[1,0],[1,1],[0,2],[0,2],[-2,1],[-1,0],[-2,0],[-2,2],[-1,1],[-1,1],[-1,1],[-1,2],[0,2],[1,2],[0,1],[0,1],[0,1],[0,1],[0,1],[0,2],[0,2],[0,5],[0,9],[0,8],[-1,9],[0,7],[0,9],[0,9],[0,9],[-3,5],[-5,6],[-4,4],[-2,0],[-1,0],[-1,-2],[-3,-2],[-5,-1],[-4,-3],[-2,0],[-1,0],[-2,2],[-1,2],[-1,3],[1,5],[-3,2],[-3,1],[-1,-4],[-2,-3],[-3,-6],[-4,-9],[-3,-5],[-4,-9],[-4,-8],[-1,-8],[-1,-7],[-3,-6],[-2,-5],[0,-6],[-1,-5],[0,-5],[0,-2],[0,-2],[-1,-2],[-2,-4],[0,-4],[-2,-2],[-3,-3],[-3,-6],[0,-3],[0,-2],[0,-2],[0,-1],[-2,0],[-1,0],[-1,-2],[0,-3],[-1,-3],[-1,0],[0,1],[-1,3],[-2,0],[-1,-1],[-2,-3],[-2,0],[-4,1],[-2,-5],[-3,-11],[-11,0],[-12,0],[-12,0],[-11,0],[-12,0],[-11,0],[-12,0],[-6,0],[-2,0]],[[1497,8027],[1,-6],[-3,1],[-2,1],[0,3],[1,2],[3,-1]],[[3484,8040],[-4,-3],[-1,-2],[-1,0],[-1,1],[-1,3],[0,1],[1,1],[1,-1],[0,-1],[1,0],[3,3],[2,0],[1,0],[-1,-2]],[[3497,8049],[2,-4],[1,-1],[-7,-4],[-1,0],[0,4],[0,3],[0,1],[2,-2],[2,3],[1,0]],[[1551,8037],[1,-1],[-7,4],[-2,3],[-1,2],[-1,1],[-3,2],[-1,2],[1,1],[2,-1],[4,-2],[3,-3],[4,-8]],[[1482,8041],[-1,0],[-2,0],[-2,2],[-3,5],[-1,0],[1,1],[1,1],[0,1],[-1,3],[3,2],[2,-1],[1,-2],[2,-4],[0,-4],[0,-3],[0,-1]],[[3283,8012],[-12,-1],[-9,3],[-7,2],[-6,3],[-15,10],[-2,4],[-1,4],[-3,4],[-3,3],[-15,10],[-2,3],[4,2],[3,2],[3,-1],[11,-3],[13,-4],[5,-2],[7,-4],[6,-5],[14,-12],[2,-1],[7,-7],[2,-4],[1,-4],[-1,-2],[-2,0]],[[1528,8065],[-1,6],[1,3],[0,1],[0,1],[1,-3],[1,-2],[0,-2],[0,-1],[-2,-3]],[[1523,8069],[-1,-3],[-2,5],[-2,11],[0,2],[1,4],[1,0],[2,-2],[2,-3],[0,-1],[1,-3],[1,-3],[-2,-3],[-1,-4]],[[3457,8105],[-1,0],[-1,0],[-1,0],[0,1],[1,3],[2,1],[2,0],[0,-2],[-1,-2],[-1,-1]],[[1467,8101],[13,-8],[14,-3],[10,-4],[7,-2],[2,-1],[1,-1],[2,-4],[3,-8],[2,-6],[5,-9],[3,-7],[1,-2],[0,-1],[0,-2],[2,-6],[6,-6],[4,-3],[8,-5],[6,-4],[1,-3],[2,-3],[1,-2],[2,-8],[4,-7],[3,-14],[1,1],[0,4],[1,1],[1,1],[0,-2],[1,-4],[2,-8],[0,-3],[-1,0],[-3,1],[-1,-1],[-2,-4],[-1,-1],[0,1],[-9,3],[-6,3],[-7,4],[-9,5],[-5,3],[-4,4],[-3,2],[0,3],[0,1],[5,8],[3,4],[1,3],[0,3],[0,4],[-1,-4],[-1,-3],[-1,-3],[0,-1],[-7,-1],[-5,0],[-3,-3],[-1,-1],[-1,1],[-4,5],[-4,3],[0,1],[3,2],[2,3],[-1,0],[-1,0],[-1,1],[-1,3],[-2,1],[-2,-2],[-1,0],[-1,3],[2,5],[0,1],[-3,-2],[0,1],[-1,2],[-1,0],[-2,0],[-2,2],[-1,-1],[0,-2],[-1,-1],[-3,4],[-2,-3],[-1,0],[0,1],[-1,7],[0,2],[1,1],[3,2],[7,2],[1,1],[-6,-1],[-1,1],[-2,3],[-2,0],[-1,0],[-1,2],[-2,7],[-2,1],[-3,1],[-1,2],[-1,-1],[0,-2],[-1,-1],[-2,-1],[-2,1],[-2,2],[0,2],[-1,2],[1,4],[0,1],[0,1],[-1,2],[-1,1],[0,-1],[0,-2],[-1,-1],[-2,-1],[-1,2],[-1,2],[-1,2],[-6,0],[-2,-2],[-2,0],[-1,0],[0,1],[1,4],[0,5],[-1,1],[-2,1],[-1,1],[2,5],[1,1],[1,1],[5,0],[2,0],[3,-4],[-1,1],[0,4],[-1,3],[2,2],[-2,1],[-6,1],[0,-2],[1,-2],[-4,-3],[-3,0],[-2,0],[-2,2],[-4,5],[-2,5],[0,3],[1,2],[2,2],[3,2],[6,0],[5,-2],[15,-10]],[[3459,8152],[-2,-6],[-1,-2],[-2,-1],[-2,-1],[-6,-1],[-3,-1],[0,-4],[0,-2],[1,-1],[1,-1],[3,1],[1,0],[0,-1],[1,-1],[0,-2],[0,-3],[0,-3],[-2,-7],[-3,-4],[-3,-3],[-1,-2],[0,-1],[-1,-5],[-1,-4],[-6,-9],[-2,-2],[0,-2],[0,-5],[-2,-3],[-4,-9],[-1,-3],[-1,-2],[0,-4],[0,-1],[-1,-3],[-1,-3],[0,-1],[0,-2],[1,-1],[0,-2],[-1,-4],[2,3],[4,7],[3,5],[2,2],[2,2],[1,5],[2,4],[2,1],[1,0],[1,-3],[0,-2],[-1,-4],[0,-1],[2,3],[4,2],[2,-1],[3,-3],[2,1],[4,2],[1,-1],[-1,-3],[-1,-2],[-4,-4],[-9,-7],[-3,-5],[1,0],[2,2],[2,1],[2,0],[1,0],[-1,-2],[0,-3],[-5,-8],[1,0],[6,4],[4,-5],[5,2],[3,1],[0,-1],[1,-2],[0,-3],[2,1],[0,1],[0,6],[2,-1],[0,-1],[0,-4],[0,-5],[-1,-3],[-3,-6],[1,-3],[-1,-2],[1,0],[2,2],[0,1],[0,2],[0,2],[2,2],[3,3],[1,1],[1,-1],[-1,-2],[1,1],[2,2],[2,2],[2,1],[2,2],[2,3],[2,2],[2,2],[1,1],[-1,-4],[1,-4],[0,-3],[0,-1],[2,4],[1,1],[1,1],[1,-1],[9,2],[2,-1],[3,-3],[4,-3],[2,-4],[0,-4],[0,-3],[-3,-3],[-3,-3],[-1,-2],[0,-3],[-1,-1],[-2,-2],[-7,-6],[2,0],[4,1],[3,0],[0,-1],[-1,-1],[-2,-2],[-1,-1],[1,-1],[2,-1],[3,1],[2,-1],[0,-2],[-2,-4],[-1,-3],[-2,-3],[-5,-3],[-2,-2],[1,0],[4,3],[3,0],[1,0],[2,3],[3,1],[2,-2],[4,5],[1,1],[3,-1],[1,1],[3,3],[2,1],[1,-1],[0,-4],[-1,-3],[0,-2],[-2,-4],[-2,-2],[-1,-1],[-2,1],[-1,-1],[-2,-4],[-3,-3],[-3,-2],[2,-1],[0,-4],[0,-1],[-4,-2],[-2,-1],[-3,-1],[2,-1],[4,1],[1,-1],[-1,-2],[-1,-3],[-5,-7],[0,-1],[1,-3],[1,-3],[1,-2],[3,0],[2,1],[2,5],[7,14],[5,4],[5,5],[1,-1],[0,-1],[0,-1],[-2,-4],[-2,-3],[-3,-9],[-1,-5],[0,-4],[0,-9],[0,-1],[1,-2],[2,2],[3,4],[2,4],[2,6],[0,2],[2,0],[0,-1],[1,-3],[1,-4],[0,-4],[0,-5],[-1,-3],[-6,-18],[1,-3],[0,-2],[0,-3],[-3,-8],[-1,-6],[-2,-2],[-1,-2],[-1,0],[-2,0],[-1,3],[-1,1],[-1,0],[-1,-1],[-4,-4],[-1,0],[-1,0],[-1,3],[1,12],[0,3],[-1,4],[1,5],[0,2],[-1,0],[-2,-3],[-2,-4],[-2,-5],[-5,-5],[-1,-1],[-1,0],[-1,1],[-1,2],[0,2],[0,3],[2,7],[3,10],[3,7],[1,3],[-1,2],[-1,2],[-1,8],[-1,6],[-2,3],[-4,3],[-1,-5],[-5,-12],[0,-5],[-1,-2],[-1,-2],[-2,-1],[1,2],[2,7],[-1,0],[-2,-5],[-2,-3],[-3,0],[-2,0],[-1,-1],[-7,-12],[0,-4],[-1,-3],[-3,-6],[-2,-3],[-2,0],[-2,1],[-2,0],[-3,-2],[-4,-1],[-2,1],[-1,0],[-2,3],[0,1],[0,1],[1,3],[3,3],[1,1],[5,2],[3,2],[3,4],[1,2],[5,11],[6,4],[3,3],[2,4],[0,1],[-3,-2],[-2,0],[-2,0],[-1,2],[-4,-1],[-4,1],[-1,-1],[-1,-5],[0,-3],[-1,-1],[-1,-1],[-2,0],[-6,2],[-1,1],[-1,0],[-6,-1],[-1,0],[1,1],[6,4],[0,11],[0,2],[-2,-1],[-2,-2],[-2,0],[-1,1],[-1,0],[-2,-6],[-1,-1],[-2,0],[-4,-3],[-7,-1],[-1,-2],[-5,1],[-15,3],[-5,0],[-6,2],[-1,1],[-9,-1],[-3,1],[0,2],[0,1],[-2,-3],[-3,-1],[-2,-2],[-10,-3],[-4,0],[-3,2],[-1,1],[-2,6],[-1,8],[0,1],[0,3],[2,3],[9,10],[7,9],[3,5],[3,2],[4,4],[0,1],[-4,-1],[-3,1],[-4,1],[-6,-1],[-6,0],[0,2],[3,4],[6,7],[1,0],[-2,-4],[-1,-2],[1,-2],[1,-1],[4,0],[0,1],[2,8],[2,8],[2,6],[2,5],[2,1],[1,-1],[3,-1],[4,-5],[1,0],[1,0],[-2,2],[-1,2],[0,2],[1,5],[2,2],[0,1],[-3,0],[-3,2],[-1,3],[1,4],[0,3],[3,4],[2,2],[2,0],[3,-4],[1,1],[0,1],[-3,6],[0,4],[0,1],[6,19],[2,10],[4,15],[1,3],[2,4],[1,2],[3,0],[1,0],[-2,2],[-1,2],[0,1],[1,1],[1,2],[3,2],[2,4],[1,5],[0,1],[-1,2],[0,1],[2,1],[4,6],[1,1],[1,7],[2,3],[2,2],[3,2],[8,5],[5,5],[4,0],[1,-3],[5,-3],[1,3],[-2,3],[1,1],[4,1],[1,-1],[1,-1],[0,-2]],[[1446,8149],[0,-1],[-1,0],[-2,1],[-1,2],[-2,6],[0,2],[1,1],[2,2],[1,0],[1,-2],[1,-4],[1,-1],[0,-5],[-1,-1]],[[3462,8173],[-1,0],[-1,0],[1,2],[1,3],[2,1],[0,-4],[-2,-2]],[[2795,8176],[-2,0],[-2,0],[-2,2],[-2,1],[9,6],[2,-1],[0,-1],[-2,-3],[0,-2],[0,-1],[-1,-1]],[[1360,8177],[-1,1],[-1,2],[0,5],[0,2],[0,1],[3,-4],[-1,-7]],[[1434,8202],[-2,-1],[1,3],[0,2],[-1,2],[0,3],[0,8],[2,5],[3,0],[0,-2],[-1,-12],[-1,-5],[0,-2],[-1,-1]],[[1418,8208],[-1,-2],[-3,6],[-2,2],[-2,7],[-1,2],[0,2],[1,1],[1,-1],[0,-1],[6,-7],[1,-3],[0,-6]],[[1408,8236],[-1,0],[-1,0],[-1,2],[-2,4],[0,2],[-1,3],[1,0],[1,0],[3,-7],[1,-4]],[[2757,8222],[-2,-1],[-6,2],[-2,1],[-7,4],[-14,6],[-4,3],[-1,2],[2,5],[2,2],[1,1],[14,2],[6,-1],[6,-9],[4,-7],[2,-5],[0,-3],[-1,-2]],[[1340,8248],[3,-6],[1,-4],[-1,-6],[-4,-2],[-2,2],[-1,-1],[-2,-1],[2,-1],[2,-3],[3,-4],[3,0],[4,-3],[-3,-4],[0,-3],[4,-7],[0,-2],[1,0],[3,0],[1,0],[0,-2],[-2,-4],[0,-1],[2,0],[3,0],[1,-4],[-3,-4],[-6,5],[-2,4],[-2,5],[-1,2],[-6,6],[-7,12],[-2,2],[-2,5],[-1,2],[0,2],[1,1],[2,0],[0,2],[-9,5],[-1,1],[-1,2],[1,1],[5,-1],[5,2],[3,1],[1,1],[3,2],[1,0],[3,-2]],[[1429,8233],[1,-18],[0,-6],[-2,-4],[-1,-7],[-2,-2],[-1,3],[0,7],[-1,5],[0,2],[1,10],[-1,-1],[-2,-4],[-2,0],[-3,4],[-2,4],[0,4],[-2,4],[-1,2],[1,2],[1,4],[1,3],[1,5],[1,3],[1,-1],[3,-2],[4,-3],[3,-4],[2,-10]],[[1412,8243],[-3,0],[-1,0],[0,2],[-1,2],[1,2],[2,4],[0,2],[0,1],[1,-3],[1,-2],[0,-8]],[[2779,8254],[0,-2],[-2,1],[-1,1],[0,1],[-1,1],[1,2],[2,-1],[1,-3]],[[1393,8246],[-1,0],[-1,1],[-6,9],[-5,4],[-3,5],[-3,3],[2,5],[2,-1],[5,-4],[5,-4],[2,-2],[6,-11],[-1,-2],[-2,-3]],[[1382,8292],[-1,-2],[-2,-4],[-1,-1],[-1,1],[-1,0],[-2,3],[-2,2],[-1,0],[0,-1],[0,-2],[0,-2],[0,-1],[-1,0],[0,1],[-1,2],[0,2],[0,1],[2,3],[4,4],[1,1],[2,0],[2,-2],[0,-1],[2,-4]],[[1315,8301],[3,-3],[6,2],[1,0],[1,-1],[1,-3],[2,-4],[0,-5],[-1,-2],[-1,-2],[-9,-7],[-1,-1],[1,-1],[2,0],[8,2],[0,1],[1,6],[1,3],[0,2],[-1,6],[0,2],[6,1],[3,2],[4,3],[0,-7],[-1,-2],[-3,-8],[-2,-7],[-1,-8],[0,-12],[-1,-4],[-1,-2],[-9,-5],[-5,1],[-5,4],[-2,2],[2,4],[1,0],[3,-1],[2,-1],[1,0],[0,1],[-6,6],[-5,3],[-2,3],[0,2],[0,2],[-4,8],[-1,4],[0,5],[0,4],[1,8],[0,1],[2,0],[2,-1],[7,-1]],[[1363,8322],[-1,0],[0,1],[0,2],[1,5],[1,1],[3,-1],[1,-1],[0,-2],[-2,-2],[-3,-3]],[[1373,8338],[2,4],[5,7],[3,4]],[[1383,8353],[0,-4],[-4,-8],[-5,-4],[-1,1]],[[3305,8412],[1,-2],[-5,1],[-1,1],[0,1],[0,1],[1,2],[2,1],[1,0],[2,-2],[0,-1],[-1,-2]],[[2810,8418],[-1,-1],[-1,0],[0,2],[1,4],[1,3],[0,3],[1,2],[1,3],[1,1],[1,0],[1,-7],[-1,-4],[-1,-2],[-1,-3],[-2,-1]],[[2778,8421],[-1,0],[-2,1],[1,4],[1,2],[4,1],[1,1],[1,1],[1,0],[2,2],[2,3],[1,0],[-1,-4],[-2,-4],[-8,-7]],[[2807,8425],[-2,-6],[-2,-6],[-3,-10],[-1,-1],[-1,3],[3,12],[1,2],[-1,1],[-1,2],[-1,-3],[-5,-13],[-1,-3],[-1,-1],[-1,0],[-3,0],[-4,-4],[7,17],[1,1],[-2,1],[0,-1],[-6,-10],[-4,-4],[-2,1],[-1,1],[0,1],[6,11],[6,7],[2,5],[1,5],[0,3],[0,3],[1,1],[0,-1],[0,-4],[-1,-8],[-1,-3],[-1,-4],[3,1],[1,4],[2,6],[1,5],[1,8],[0,-2],[1,-1],[2,-1],[1,-1],[0,-2],[1,-2],[2,-1],[1,0],[1,-3],[0,-2],[0,-1],[1,0],[-1,-3]],[[2791,8447],[-1,-1],[-1,0],[1,6],[-1,1],[0,1],[0,1],[1,0],[1,-1],[1,-2],[0,-2],[0,-1],[-1,-1],[0,-1]],[[2781,8454],[-1,-1],[-1,1],[0,3],[1,2],[1,0],[1,-1],[0,-2],[-1,-2]],[[3285,8499],[2,-2],[1,-6],[-5,0],[-5,4],[-1,4],[1,1],[1,-1],[1,1],[2,0],[3,-1]],[[2785,8497],[0,-1],[-1,1],[-1,-4],[0,-1],[-1,3],[1,2],[0,1],[0,1],[1,2],[1,1],[0,-3],[0,-2]],[[3079,8584],[-2,-4],[-2,1],[-1,-1],[-1,0],[1,4],[0,2],[0,3],[1,1],[3,1],[0,-4],[0,-1],[1,0],[0,-2]],[[2770,8618],[-1,0],[-1,1],[1,2],[1,0],[2,3],[1,-1],[-1,-2],[-1,-2],[-1,-1]],[[2776,8627],[-3,-1],[1,4],[1,1],[1,1],[3,1],[1,-2],[-1,-2],[-3,-2]],[[3211,8661],[-1,-4],[-4,1],[-5,3],[-2,2],[0,3],[0,3],[1,0],[4,0],[3,-4],[1,-1],[3,-3]],[[3104,8654],[-2,-1],[-1,1],[0,4],[0,2],[3,6],[3,6],[1,2],[3,-1],[2,-2],[2,-3],[1,-2],[-1,-4],[-2,-3],[-3,-2],[-6,-3]],[[2818,8682],[-4,-1],[0,1],[2,2],[6,2],[4,1],[-1,-2],[-2,-2],[-5,-1]],[[3199,8718],[-1,0],[-1,0],[-2,3],[-2,1],[-1,1],[-9,7],[-1,2],[0,3],[3,1],[6,1],[4,0],[5,-2],[1,-1],[2,-3],[0,-3],[0,-4],[-1,-1],[-2,-2],[-1,-3]],[[2415,8746],[-1,0],[-2,3],[-1,1],[3,1],[3,-2],[-1,-2],[-1,-1]],[[3193,8748],[1,-1],[1,1],[1,-2],[0,-1],[2,-2],[0,-1],[0,-1],[-1,-1],[-1,-1],[-6,4],[-2,4],[0,2],[0,2],[1,1],[2,0],[1,-1],[1,-3]],[[2790,8779],[2,-2],[4,-5],[1,-3],[1,-3],[-1,-5],[-1,-5],[-1,-3],[-3,-4],[-2,-5],[-2,-6],[-1,-4],[-2,-1],[-1,-1],[-1,0],[-3,2],[-3,4],[-2,2],[-3,2],[-2,2],[0,3],[0,7],[0,4],[0,3],[1,3],[2,3],[4,8],[3,3],[1,0],[4,0],[2,0],[2,1],[1,0]],[[3199,8787],[5,-1],[4,1],[1,-1],[1,-3],[-1,-4],[-2,-2],[-3,0],[-5,1],[-2,1],[-2,2],[1,2],[3,0],[0,1],[-1,1],[0,1],[1,1]],[[2944,8791],[-1,-1],[-6,1],[-7,2],[-3,3],[0,1],[1,0],[2,0],[3,-2],[8,-1],[3,-1],[0,-1],[0,-1]],[[3046,8787],[-2,-1],[-4,1],[-4,1],[-2,1],[-2,3],[0,3],[-4,5],[-4,2],[-3,3],[3,0],[3,0],[5,-2],[5,-2],[6,-4],[2,-4],[2,-3],[1,-2],[-1,-1],[-1,0]],[[2722,8810],[1,-2],[0,-2],[0,-3],[-1,-3],[-1,-3],[-2,-5],[-8,-7],[-3,-4],[-2,-3],[-12,-11],[-2,-1],[-1,1],[-4,1],[-3,1],[-9,-5],[-1,1],[0,5],[-1,2],[-4,6],[0,1],[0,2],[0,1],[5,6],[10,19],[2,1],[5,-2],[2,-1],[2,0],[7,4],[7,0],[6,2],[3,0],[3,0],[1,-1]],[[2836,8840],[3,-3],[2,0],[2,-2],[3,-6],[0,-1],[0,-2],[-2,-3],[-1,-1],[-4,-2],[-4,-1],[-3,1],[-6,6],[-6,7],[-2,4],[1,1],[2,2],[6,1],[8,-1],[1,0]],[[2870,8835],[-3,0],[-4,1],[-4,2],[-8,8],[6,6],[10,-6],[3,-4],[0,-7]],[[2843,8870],[-2,-3],[-6,1],[-1,1],[0,1],[1,1],[6,1],[3,0],[1,0],[0,-1],[-2,-1]],[[2641,8943],[1,-1],[1,0],[2,3],[4,8],[2,1],[1,0],[7,-5],[2,-3],[2,-4],[1,-2],[5,-2],[5,-1],[7,-2],[2,-1],[5,-8],[1,-1],[5,-3],[9,-7],[3,-1],[8,-2],[4,-2],[3,-3],[3,-5],[4,-7],[3,-13],[0,-2],[0,-2],[-1,-1],[-5,-5],[0,-1],[5,0],[10,3],[7,-2],[2,0],[1,0],[2,4],[2,-1],[4,-3],[3,-4],[1,-2],[-1,-1],[-2,-1],[6,-2],[5,-3],[-1,-3],[-5,-5],[-6,-4],[-7,-7],[-2,-1],[-1,0],[-3,1],[-6,3],[-16,8],[-5,1],[-7,1],[0,2],[-2,11],[-3,2],[-10,2],[-3,1],[0,3],[1,3],[-2,2],[-3,0],[-3,-1],[-6,-2],[-2,-3],[-1,-2],[-1,-6],[0,-2],[-2,-4],[-8,-8],[-4,-3],[-3,-1],[-1,-1],[-2,-3],[-4,-8],[-1,-2],[-2,-3],[-5,-3],[-4,-3],[-8,-3],[-4,-2],[-3,2],[-2,7],[-4,22],[-1,2],[-1,1],[-1,0],[-14,-3],[-7,1],[-8,-5],[-2,-1],[-3,0],[-3,1],[-1,1],[0,2],[0,2],[1,3],[3,6],[3,4],[1,2],[13,7],[3,2],[2,3],[0,3],[-1,3],[-2,8],[-1,7],[0,4],[1,5],[4,14],[1,6],[2,24],[1,6],[1,7],[2,3],[4,8],[3,3],[4,2],[1,-1],[1,0],[1,-4],[6,-2],[2,-3],[1,-3],[1,-4],[-1,-2],[-3,-3],[0,-1],[0,-1],[5,-4],[4,-10]],[[2648,8961],[-2,-1],[-1,1],[-2,1],[-1,3],[-1,2],[-4,3],[-1,1],[-1,4],[0,4],[-1,3],[0,2],[0,2],[4,1],[2,-1],[1,-1],[1,-1],[0,-2],[3,-5],[2,-4],[3,-7],[0,-2],[-1,-2],[-1,-1]],[[2674,8974],[4,-3],[3,-1],[6,-1],[1,0],[0,-1],[-1,-2],[-2,-2],[-1,0],[-4,1],[-1,1],[-1,2],[-1,0],[-1,-1],[1,-1],[-1,0],[-4,0],[0,1],[0,2],[3,2],[-3,1],[0,1],[-4,-2],[-2,0],[-3,1],[0,6],[-1,2],[-1,2],[-1,2],[-1,1],[-3,1],[-2,3],[-1,1],[1,1],[1,2],[8,-3],[5,-3],[4,-4],[3,-2],[0,-2],[-1,-2],[-1,-1],[1,-2]],[[2691,9002],[3,-1],[2,0],[0,-1],[-2,-3],[-1,0],[-3,2],[-2,2],[0,2],[0,1],[0,1],[3,-3]],[[1997,9043],[4,0],[4,0],[-1,-5],[-1,-2],[-2,-1],[0,1],[-3,4],[-1,3]],[[3259,9046],[-4,-1],[-2,1],[2,1],[1,2],[3,2],[1,2],[4,1],[2,0],[0,-1],[-2,-2],[-5,-5]],[[2003,9066],[-2,-5],[0,1],[-1,2],[-2,1],[-2,3],[0,5],[0,3],[0,3],[2,2],[2,-2],[1,-4],[-1,-3],[2,-2],[1,-2],[0,-2]],[[1967,9099],[4,0],[2,0],[2,-2],[0,-2],[0,-1],[-1,0],[-5,2],[-1,2],[-1,1]],[[2955,9088],[-14,0],[-7,0],[-3,1],[-3,2],[-3,4],[-2,5],[0,2],[1,1],[1,1],[9,2],[7,-2],[6,-2],[9,-1],[2,0],[1,-1],[1,-1],[1,-5],[0,-3],[0,-2],[-6,-1]],[[1963,9100],[-1,0],[-4,3],[1,3],[4,-3],[0,-2],[0,-1]],[[2594,9085],[-1,0],[-2,1],[-4,4],[-1,1],[0,2],[0,2],[0,2],[1,4],[-2,3],[-1,2],[0,1],[2,3],[0,1],[2,3],[3,4],[4,-1],[3,-4],[1,-2],[0,-3],[0,-3],[1,-5],[0,-4],[0,-2],[-2,-4],[-1,-2],[-1,-2],[-2,-1]],[[2898,9119],[14,-5],[2,-2],[0,-2],[1,-1],[0,-4],[-1,-2],[-1,-3],[0,-2],[1,-12],[0,-7],[-1,-5],[-2,-5],[-3,-3],[-3,-2],[-10,-5],[-8,-1],[-8,0],[-10,-2],[-4,1],[-3,0],[-1,1],[-2,3],[-3,5],[-1,6],[-3,10],[0,2],[2,8],[3,5],[5,9],[6,8],[1,1],[3,2],[6,2],[6,-1],[2,1],[3,1],[3,0],[6,-1]],[[2806,9112],[-2,-1],[-4,3],[0,2],[1,4],[6,1],[2,-3],[1,-2],[-4,-4]],[[2096,9124],[-2,0],[-3,1],[-4,2],[-3,2],[-2,2],[0,2],[1,1],[3,0],[5,0],[3,-1],[4,-4],[1,-1],[0,-2],[-1,-1],[-2,-1]],[[2920,9121],[-2,-1],[-4,4],[-6,4],[-3,3],[0,1],[0,2],[1,3],[2,3],[3,1],[3,-1],[3,-2],[3,-6],[1,-3],[1,-2],[-1,-1],[0,-1],[1,-1],[-1,-1],[0,-1],[-1,-1]],[[2171,9134],[-1,0],[-2,1],[-9,4],[-1,1],[1,1],[3,2],[2,2],[2,3],[5,-1],[2,-2],[1,-1],[0,-2],[0,-4],[-2,-1],[-1,-3]],[[2216,9147],[-1,-2],[-1,0],[-2,-3],[-1,0],[-1,2],[-1,2],[-1,0],[-2,-1],[-1,0],[0,1],[0,1],[0,3],[0,5],[0,1],[0,2],[0,1],[1,1],[2,0],[3,0],[2,-2],[1,-2],[2,-2],[1,-1],[-1,-6]],[[2222,9159],[0,-4],[-4,1],[-1,2],[-2,2],[0,1],[0,1],[2,3],[1,1],[2,-1],[1,-2],[1,-2],[0,-2]],[[2486,9171],[-2,-1],[-2,3],[-1,0],[0,2],[-3,0],[0,2],[1,2],[2,1],[2,-1],[2,-2],[1,-2],[0,-3],[0,-1]],[[2799,9149],[-1,0],[-3,1],[-1,2],[0,2],[0,1],[1,1],[2,2],[2,3],[2,2],[6,2],[1,1],[3,6],[1,1],[3,0],[0,1],[-1,1],[0,2],[1,1],[1,1],[4,2],[4,-1],[1,0],[0,-1],[2,-3],[-2,-3],[-4,-3],[-3,-3],[0,-1],[-1,-2],[0,-1],[-4,-4],[-2,-4],[-2,-2],[-5,-2],[-5,-2]],[[2494,9182],[1,-3],[-3,-5],[0,-1],[-1,0],[-1,0],[-3,4],[-1,2],[1,2],[2,1],[2,1],[2,-1],[0,1],[1,-1]],[[2861,9166],[-4,0],[-2,0],[-2,1],[-1,2],[-2,5],[1,2],[0,4],[0,1],[1,1],[4,1],[2,0],[3,-1],[7,-1],[2,-1],[0,-1],[0,-1],[0,-1],[-4,-4],[-2,-2],[-1,-3],[-2,-2]],[[2189,9181],[-2,-1],[0,1],[0,1],[0,1],[-1,1],[2,1],[0,1],[-3,2],[-1,1],[0,1],[2,1],[1,0],[4,-2],[2,-2],[1,-2],[-1,-1],[-1,0],[-1,-2],[-2,-1]],[[2347,9191],[3,-4],[0,-2],[0,-3],[-1,-2],[-2,-2],[-2,-1],[-3,0],[-1,1],[1,3],[0,2],[0,4],[-1,2],[-1,1],[-2,0],[0,-1],[1,-2],[-1,-3],[-1,-4],[-1,-2],[-2,1],[-1,2],[1,2],[-1,2],[1,2],[1,4],[2,2],[2,1],[2,0],[3,-1],[3,-2]],[[1138,9191],[-3,-2],[-3,2],[-1,2],[4,3],[2,-1],[4,-1],[1,-2],[-4,-1]],[[3113,9189],[-1,0],[-7,3],[0,2],[3,2],[3,1],[2,0],[3,0],[2,-3],[-3,-2],[-2,-3]],[[2832,9199],[2,-3],[0,-1],[-2,-2],[-7,-3],[-5,-3],[-2,-1],[-3,1],[-4,-1],[-2,0],[2,2],[6,7],[5,1],[1,1],[2,0],[1,1],[0,1],[1,2],[2,0],[3,-2]],[[2793,9203],[1,-3],[1,-1],[-1,-1],[-4,-4],[-9,-1],[-5,2],[2,-5],[1,-2],[-1,-1],[-2,1],[-3,1],[-2,1],[0,2],[-1,1],[-1,-1],[-1,0],[-2,3],[-1,1],[-9,1],[-1,1],[1,1],[1,2],[2,0],[6,0],[0,2],[1,1],[3,0],[3,0],[1,-1],[1,-2],[2,0],[2,0],[3,1],[4,2],[4,1],[4,-2]],[[2293,9195],[1,-1],[2,1],[1,2],[1,0],[1,0],[4,-3],[3,-4],[3,-3],[5,-2],[11,-7],[3,-5],[3,-8],[3,-6],[3,-4],[3,-3],[5,-3],[4,2],[1,1],[2,-1],[1,-3],[0,-1],[-2,-2],[-3,-1],[-4,-1],[-2,0],[-3,-3],[-3,-3],[-4,-2],[-6,-5],[-4,-2],[-6,-1],[-11,5],[-7,-1],[-6,1],[-6,5],[-5,2],[-10,4],[-1,1],[0,1],[0,2],[-1,1],[0,1],[-2,0],[-1,-1],[-3,-2],[-5,1],[-2,1],[-1,1],[-1,1],[0,2],[-1,1],[-1,1],[-1,0],[-3,-1],[-1,-1],[1,-1],[-1,-1],[-4,0],[-2,1],[-3,2],[-2,3],[-2,4],[0,1],[2,3],[1,2],[10,1],[5,1],[5,3],[7,5],[1,1],[0,1],[0,2],[-2,3],[-1,2],[1,1],[2,0],[-1,1],[-1,1],[-1,1],[0,2],[2,0],[3,0],[4,-5],[2,-1],[3,-1],[-3,4],[-3,6],[-1,3],[0,1],[1,4],[1,1],[1,1],[3,2],[6,2],[2,0],[3,-1],[3,-3],[5,-3],[1,-2],[0,-1],[-2,-1],[-1,-1],[1,-1]],[[2585,9222],[4,0],[3,0],[2,0],[1,-2],[1,-2],[1,-1],[-2,-2],[-5,-1],[-3,1],[-3,1],[-2,0],[-4,1],[-2,1],[-2,2],[0,2],[4,1],[2,1],[5,-2]],[[2213,9244],[-6,2],[-2,1],[-1,1],[-1,2],[0,3],[1,1],[3,0],[3,-1],[4,-3],[-1,-1],[0,-2],[1,-2],[-1,-1]],[[2924,7776],[-1,0],[-3,0],[-4,-2],[-5,-4],[-6,-7],[-11,-16],[0,-2],[-2,-3],[-4,-3],[-4,-3],[-1,-4],[-1,-2],[-6,-9],[-4,-7],[-3,-8],[-3,-9],[-7,0],[-6,0],[-9,0],[-8,0],[-9,0],[-7,0],[-7,0],[-3,-3],[-5,-3],[-4,-4],[2,-7],[1,-3],[-1,-10],[1,-1],[0,-2],[1,-2],[0,-2],[1,-1],[1,-1],[0,-1],[1,-2],[-1,-2],[-3,-4],[-4,-3],[-7,-6],[-9,-6],[-7,-6],[-6,-4],[-12,-4],[-10,-3],[-7,-2],[-6,-6],[-7,-7],[-6,-5],[-7,-7],[-6,-6],[-7,0],[-5,5],[-5,4],[-3,9],[0,9],[1,6],[1,3],[2,2],[4,3],[3,6],[3,4],[3,4],[1,7],[2,16],[1,3],[2,11],[4,12],[1,5],[-2,15],[-1,11],[-1,10],[-1,12],[-1,10],[-1,10],[-1,10],[-2,10],[0,7],[-1,8],[-6,6],[-5,4],[-7,6],[-6,6],[-5,5],[3,10],[0,2],[-1,2],[-3,3],[-1,0],[-3,0],[-4,-2],[-2,0],[-1,4],[-2,4],[-1,4],[0,5],[-1,4],[1,2],[0,1],[0,2],[-1,1],[-1,0],[-4,-2],[-2,0],[-1,-1],[-2,-2],[-1,0],[-3,5],[-3,5],[-2,7],[-1,8],[-5,5],[-6,4],[-5,5],[-5,5],[-6,4],[-5,5],[-6,4],[-5,5],[-2,2],[-5,4],[-7,5],[-8,7],[-8,6],[-7,6],[-4,4],[-2,2],[-5,4],[-6,4],[-7,-2],[-8,-7],[-4,-3],[-4,-3],[-2,-1],[-5,-2],[-3,1],[-6,0],[-3,-1],[-3,1],[-1,4],[-2,2],[-6,-1],[-8,1],[-4,0],[-1,1],[-2,4],[-2,1],[-3,-1],[-5,-5],[-5,-3],[-3,0],[-4,3],[-6,5],[-4,6],[-5,2],[-3,-1],[-1,-3],[-2,0],[-2,6],[-1,4],[-2,1],[-4,4],[-3,2],[-4,3],[-2,0],[-3,1],[-3,0],[-3,-1],[-2,-3],[-3,-2],[-4,0],[-3,1],[-1,4],[-6,2],[-10,3],[-6,2],[-1,2],[-1,2],[0,3],[-3,8],[-1,7],[0,8],[0,3],[-1,0],[-1,2],[-6,1],[-1,-9],[0,-12],[-6,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-12,0],[-12,0],[-12,0],[-11,0],[-12,0],[-12,0],[-3,0]],[[1589,8006],[-1,2],[-3,2],[-1,0],[-1,0],[-1,-2],[0,-2],[-1,-1],[0,1],[-1,3],[0,2],[1,2],[0,1],[-2,-1],[-1,1],[0,1],[0,4],[-1,2],[1,1],[3,1],[4,0],[1,2],[1,4],[-3,-4],[-1,0],[-5,1],[-3,0],[0,1],[0,1],[1,1],[0,3],[1,8],[1,3],[0,2],[-4,-6],[0,-1],[0,-2],[0,-3],[-2,-1],[-1,0],[-2,-3],[-1,0],[-9,5],[-1,1],[-1,2],[-2,4],[-1,3],[1,3],[1,2],[1,0],[1,-2],[2,-4],[0,-3],[3,0],[3,4],[1,1],[-3,-1],[-2,0],[-2,2],[-1,3],[-1,3],[0,11],[1,2],[1,1],[1,3],[0,1],[-1,2],[-1,2],[-2,1],[0,-1],[2,-4],[0,-2],[-2,-5],[-1,-1],[0,-4],[0,-1],[-2,-2],[-3,-3],[-3,-1],[-4,0],[-2,2],[-6,8],[-2,4],[0,3],[-5,11],[0,2],[-1,3],[-2,1],[0,3],[3,7],[2,5],[1,2],[0,3],[-1,6],[1,3],[-3,-4],[0,-2],[1,-3],[-1,-3],[-1,-4],[-2,-5],[-4,-2],[-8,1],[0,1],[-1,1],[0,7],[-1,-1],[-1,-3],[0,-5],[-1,-1],[-2,-1],[-1,1],[-1,2],[-2,0],[-3,-1],[-2,0],[-2,0],[-4,2],[-4,0],[-2,1],[0,3],[1,1],[5,1],[5,2],[5,1],[0,1],[-3,1],[-10,-3],[-4,0],[0,1],[-1,2],[2,3],[2,2],[0,2],[-1,1],[-2,-1],[-1,2],[1,5],[-1,6],[-1,-6],[-2,-3],[-9,-1],[-1,-1],[-2,0],[-5,2],[-3,2],[-2,3],[-4,5],[-4,4],[0,7],[1,4],[2,5],[5,10],[2,2],[2,1],[9,1],[6,1],[2,1],[-10,1],[-8,-1],[-3,-2],[-4,-6],[-1,-3],[-1,-2],[-2,1],[-1,3],[-2,3],[-1,4],[0,6],[0,3],[1,3],[3,7],[-4,-1],[1,6],[1,6],[3,3],[4,3],[3,3],[5,3],[2,-5],[5,-1],[1,-2],[2,-4],[2,-4],[2,-3],[1,-1],[-1,3],[-4,7],[0,2],[-1,3],[-5,3],[-1,2],[-1,3],[-1,3],[1,2],[5,7],[1,3],[0,2],[0,2],[-1,3],[0,-5],[0,-2],[-1,-2],[-1,-1],[-1,-2],[-11,-15],[-1,-1],[-5,-2],[-2,-1],[-1,-3],[-2,-5],[-3,-12],[-3,-9],[-2,12],[-5,9],[9,9],[0,2],[0,5],[0,1],[1,2],[2,3],[0,1],[-3,-1],[-4,-8],[-1,-2],[-1,0],[0,4],[2,11],[2,10],[0,3],[2,3],[-2,0],[-7,-5],[-2,3],[-2,16],[-4,6],[-6,4],[-6,3],[-1,4],[-1,5],[1,6],[3,3],[2,2],[3,-1],[0,-2],[-2,-6],[2,-1],[8,-7],[2,-1],[3,3],[2,0],[5,-2],[1,-3],[4,-6],[0,4],[-5,6],[-2,2],[-5,1],[-3,-1],[-1,0],[-2,2],[-2,2],[-3,7],[0,2],[0,3],[1,1],[0,2],[2,1],[3,1],[1,1],[-4,3],[-1,0],[-5,-5],[-1,0],[-1,1],[-2,-3],[-1,-1],[-4,-8],[-1,-3],[0,-6],[-1,-3],[0,-2],[-5,-3],[-3,-5],[-4,5],[-3,4],[-3,8],[-4,2],[-6,4],[-2,4],[3,8],[4,7],[1,7],[1,2],[7,2],[4,3],[-5,1],[-2,-1],[-6,-2],[-5,5],[-3,4],[-1,4],[1,4],[0,3],[0,5],[1,2],[1,2],[3,2],[2,6],[1,3],[4,11],[2,5],[3,7],[6,10],[-2,0],[-1,-1],[-1,0],[-1,1],[-1,2],[-1,4],[0,-2],[0,-6],[-1,-6],[-1,-4],[-3,-8],[-2,-3],[-1,3],[1,5],[2,4],[0,5],[-1,7],[-1,5],[-1,4],[0,4],[0,3],[1,4],[1,3],[0,1]],[[1388,8403],[0,3],[0,4],[-1,3],[-1,3],[-3,-2],[-6,2],[-1,7],[-5,1],[-3,5],[-5,2],[-4,2],[-4,2],[-3,3],[-4,3],[-3,3],[-2,0],[-5,-1],[0,6],[-2,3],[1,3],[-3,1],[-4,3],[1,5],[1,4],[-3,2],[-5,1],[1,4],[2,3],[-2,5],[-4,7],[-3,6],[-4,8],[-3,7],[-3,6],[-3,5],[-3,7],[-4,8],[-4,7],[0,4],[-4,6],[-3,5],[-4,6],[-4,3],[-3,2],[-4,3],[-3,3],[-1,3],[0,1],[-1,3],[-1,2],[-1,2],[-5,4],[-1,3],[-4,3],[-3,1],[-1,1],[-3,9],[0,3],[1,3],[-1,1],[-5,7],[-3,3],[-3,3],[-7,-4],[-6,-4],[-5,-1],[-6,-2],[2,-4],[-1,-3],[-2,-2],[-3,1],[0,-11],[-3,-7],[-6,0],[-4,-3],[-5,-4],[-4,-3],[-5,-4],[-2,0],[1,5],[-2,7],[-1,6],[-3,3],[-5,6],[-3,4],[-6,5],[-3,4],[-4,4],[-5,6],[-2,7],[-5,3],[-4,2],[-4,6],[1,5],[2,6],[0,4],[-5,-1],[-6,0],[-6,0],[-4,-5],[-4,-4],[-6,3],[-8,4],[-2,-5],[-6,3],[-7,2],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17],[0,16],[0,17],[0,17],[0,17],[0,17],[0,17]],[[1083,9196],[4,-1],[13,-2],[12,1],[22,-6],[13,-12],[11,-5],[5,-4],[7,-4],[17,-7],[5,-1],[10,-3],[6,0],[11,-1],[7,-3],[14,-7],[3,-1],[-4,8],[-1,1],[-6,3],[-6,1],[-1,1],[-1,3],[0,1],[2,0],[5,0],[2,1],[1,1],[-2,0],[-3,1],[-3,2],[-1,2],[6,11],[2,-1],[3,3],[6,-2],[1,1],[0,6],[1,1],[2,1],[8,1],[10,-1],[1,1],[-1,3],[0,2],[0,4],[1,1],[1,1],[5,0],[1,-2],[2,-3],[2,-2],[4,-1],[1,-2],[-2,-4],[-2,-3],[-4,-6],[0,-1],[6,2],[7,4],[6,2],[5,1],[4,1],[2,2],[2,2],[3,7],[2,2],[9,-1],[2,0],[1,1],[0,1],[-2,1],[-3,0],[0,1],[1,1],[2,1],[4,0],[3,-2],[2,0],[6,2],[10,8],[4,2],[3,0],[3,-1],[2,0],[3,5],[1,2],[2,2],[7,4],[5,1],[3,-1],[3,-2],[3,0],[4,0],[2,0],[2,1],[4,5],[2,0],[1,-2],[3,-3],[0,-2],[-3,-4],[-23,-13],[-7,-5],[-3,-2],[-4,-2],[-7,0],[-3,-2],[-4,-1],[-11,-1],[-2,-1],[-1,-1],[-4,-7],[-2,-2],[-4,-3],[-4,-2],[-6,-1],[-4,-3],[-4,-6],[-3,-4],[-4,-4],[-4,-4],[-1,-3],[1,-3],[1,-1],[4,-2],[2,0],[-2,2],[-3,3],[-1,1],[1,0],[17,-2],[3,2],[1,2],[0,1],[-4,0],[-1,2],[-1,3],[0,2],[0,1],[1,3],[5,3],[5,2],[4,2],[2,2],[6,3],[3,2],[1,2],[0,1],[-1,1],[1,2],[4,2],[2,0],[6,-2],[2,-1],[-1,-3],[1,0],[2,4],[1,1],[2,1],[1,-1],[2,-1],[0,-4],[0,-6],[1,-3],[1,4],[1,3],[6,9],[4,5],[5,5],[6,4],[16,6],[8,1],[4,2],[3,1],[1,2],[2,2],[1,0],[-1,-4],[-1,-2],[-5,-2],[-1,-2],[1,-3],[1,-2],[1,-1],[2,1],[4,2],[4,4],[9,8],[0,2],[3,7],[5,3],[9,3],[2,3],[-8,2],[-2,1],[0,1],[2,2],[-4,2],[-1,1],[0,3],[1,3],[2,2],[2,1],[3,-2],[3,-2],[11,-8],[4,-4],[2,-4],[6,-10],[3,-6],[2,-6],[2,-4],[2,-3],[10,-11],[5,-4],[4,-3],[5,-2],[6,-2],[4,0],[6,5],[0,3],[-3,5],[-2,3],[0,2],[4,4],[-1,2],[1,4],[2,-1],[1,0],[2,2],[2,3],[2,2],[2,2],[1,1],[-3,1],[-1,0],[-1,0],[-1,1],[1,1],[6,2],[1,2],[2,2],[2,0],[1,0],[2,-2],[0,-3],[-1,-4],[0,-4],[2,-9],[2,-2],[6,-2],[0,-2],[-8,-9],[-1,-3],[-1,-1],[0,-2],[2,-1],[2,-1],[6,0],[2,1],[12,0],[3,1],[1,1],[3,5],[3,1],[1,1],[2,6],[1,6],[1,2],[1,2],[2,0],[5,0],[2,0],[9,0],[9,0],[9,-1],[6,-1],[5,-2],[11,-5],[4,-2],[14,-12],[5,-2],[8,-2],[27,-5],[3,-1],[8,-6],[5,-3],[5,-2],[8,-3],[14,-4],[3,-1],[2,0],[3,0],[13,-2],[4,0],[2,0],[3,-2],[5,0],[0,1],[-5,6],[0,1],[2,0],[6,-1],[2,1],[2,0],[5,0],[5,-2],[6,-3],[7,-3],[10,-6],[6,-5],[5,-6],[3,-4],[1,-2],[1,-2],[1,0],[1,-1],[-1,-5],[-1,-1],[-2,-1],[-4,-1],[-14,1],[-3,-4],[-7,-4],[-2,-1],[0,-2],[1,-3],[-1,-2],[-6,-4],[-1,-1],[4,-2],[5,-3],[3,-1],[4,1],[6,-1],[6,-3],[5,-1],[2,0],[4,0],[4,-1],[6,-1],[13,0],[4,-1],[5,0],[11,0],[2,0],[3,2],[2,1],[4,0],[11,2],[3,-1],[4,2],[4,2],[3,0],[1,-1],[2,-1],[3,0],[5,3],[12,7],[4,0],[3,2],[1,0],[1,-1],[3,-5],[1,-1],[2,0],[2,-3],[2,-4],[2,-1],[11,0],[4,-1],[1,-1],[1,-3],[1,-6],[0,-3],[2,-3],[1,-1],[1,1],[3,8],[1,2],[2,-1],[3,-6],[4,-5],[10,-8],[2,-3],[0,-3],[0,-2],[-2,-2],[-3,-1],[-3,-1],[-4,0],[-3,2],[-1,0],[1,-1],[7,-7],[1,-3],[2,-2],[1,-1],[2,-2],[1,-2],[5,-5],[2,-3],[6,-8],[3,-4],[2,-2],[1,0],[0,2],[-8,11],[-4,7],[-1,2],[0,2],[0,9],[0,1],[3,1],[4,-4],[1,0],[1,0],[0,1],[2,-1],[4,-3],[1,0],[-2,6],[-2,2],[-1,2],[2,3],[-1,1],[-5,4],[-2,5],[-2,6],[0,3],[0,2],[0,2],[-3,5],[-3,3],[-3,3],[0,2],[0,5],[2,2],[3,3],[1,3],[-1,3],[-1,2],[1,-1],[7,2],[2,-1],[3,1],[3,2],[3,1],[4,0],[2,0],[2,1],[1,1],[3,3],[1,1],[3,0],[3,-1],[1,0],[-1,5],[1,2],[4,4],[4,0],[2,1],[3,2],[2,2],[2,3],[1,4],[0,1],[-5,1],[-2,-1],[-6,-2],[-6,-4],[-3,-3],[0,-4],[-2,-2],[-4,2],[-2,0],[-3,-1],[-3,-2],[-2,-2],[-5,0],[-5,1],[-4,1],[-3,-3],[0,-2],[2,-3],[-2,-2],[-8,0],[-2,0],[-4,-1],[-2,0],[-1,2],[-9,5],[-1,2],[2,4],[8,13],[1,1],[15,2],[9,2],[17,7],[4,1],[10,4],[5,1],[4,0],[6,-3],[3,-2],[2,-2],[2,-4],[2,-8],[1,-7],[2,-3],[5,-4],[2,-2],[2,-1],[1,1],[1,0],[1,0],[1,-3],[4,0],[3,-1],[0,-1],[0,-4],[0,-2],[4,-3],[4,-1],[5,-1],[8,1],[6,1],[6,3],[4,-3],[8,-7],[5,-5],[4,-2],[9,-3],[2,-2],[3,0],[4,1],[5,0],[5,-2],[4,-1],[13,4],[1,0],[5,2],[3,0],[4,0],[3,1],[1,1],[7,0],[12,-1],[9,-2],[5,-2],[4,-1],[3,-1],[3,1],[3,1],[3,2],[7,1],[1,0],[0,1],[-1,2],[-4,3],[-3,4],[-1,2],[1,2],[0,1],[2,1],[3,-2],[3,-3],[10,-13],[2,-2],[1,-1],[9,-5],[5,-1],[5,3],[2,2],[1,2],[0,1],[0,3],[0,1],[-1,2],[-4,3],[-6,3],[-5,1],[-5,-1],[-6,-3],[-2,1],[-7,8],[-1,3],[0,1],[3,-1],[0,1],[-2,4],[-1,1],[-4,7],[-1,1],[3,1],[1,1],[2,0],[6,-4],[4,1],[8,3],[-3,3],[-1,4],[1,1],[2,0],[6,-3],[2,0],[2,1],[2,0],[2,-1],[2,-1],[4,-5],[1,-2],[2,-4],[1,-1],[10,0],[5,3],[0,-1],[-1,-3],[-7,-10],[0,-1],[4,0],[1,1],[1,1],[1,3],[1,1],[10,5],[3,1],[-2,-5],[-4,-19],[0,-7],[-1,-2],[-4,-7],[0,-3],[4,-6],[1,-1],[0,-5],[1,-1],[4,-1],[3,2],[5,1],[1,-1],[-3,-6],[4,1],[2,0],[1,0],[3,-3],[1,-2],[0,-4],[-1,-2],[-1,-2],[-1,0],[-2,-1],[-1,0],[-4,0],[-3,1],[-3,2],[-1,0],[-3,-1],[-3,0],[-4,4],[-1,0],[-1,-1],[0,-1],[2,-3],[13,-14],[2,-3],[1,-4],[1,4],[-1,2],[-6,8],[-1,3],[0,1],[2,1],[10,-2],[3,1],[3,1],[1,2],[1,10],[2,6],[-1,6],[-3,9],[-2,5],[-5,5],[0,2],[5,17],[1,1],[1,1],[4,0],[3,1],[5,-2],[3,0],[3,2],[7,6],[3,3],[4,4],[4,5],[5,5],[7,4],[5,3],[1,1],[-4,0],[-1,1],[-1,3],[0,6],[0,3],[0,3],[-1,2],[-2,2],[-1,2],[-1,0],[-1,0],[0,-1],[-2,-5],[-1,-4],[-2,-2],[-4,-2],[-8,-1],[-3,2],[0,2],[1,6],[2,3],[7,5],[4,4],[0,1],[-4,0],[0,1],[-1,5],[0,2],[1,2],[2,2],[9,2],[6,2],[0,-1],[-5,-7],[0,-1],[2,-2],[5,4],[3,4],[0,1],[-2,0],[-1,2],[1,2],[0,2],[-4,2],[-4,-1],[-3,-3],[-3,0],[-4,0],[-3,0],[-2,1],[-2,3],[-3,4],[-3,4],[-1,0],[-1,-1],[-2,-3],[-1,-1],[-13,6],[-6,2],[-2,3],[-4,1],[-4,0],[-3,1],[-2,2],[-2,2],[-2,3],[-2,4],[-7,8],[-1,5],[0,2],[0,5],[6,8],[1,2],[2,2],[3,1],[2,0],[4,-1],[-2,3],[-1,1],[3,5],[-8,-4],[-2,1],[-3,2],[-5,7],[0,5],[1,6],[1,4],[-1,4],[0,1],[2,0],[0,1],[0,4],[1,2],[4,4],[3,3],[2,1],[2,0],[2,-1],[2,-2],[4,-2],[2,0],[2,1],[3,7],[2,2],[-1,0],[-7,0],[-3,1],[-1,1],[-1,2],[1,2],[6,5],[3,5],[8,7],[9,4],[4,1],[4,0],[1,0],[2,-4],[0,-4],[5,-5],[4,0],[2,1],[8,-1],[2,-1],[0,-1],[-1,-3],[0,-2],[5,-4],[5,-3],[4,-3],[7,-7],[1,-2],[1,-3],[1,-8],[1,-3],[-1,-9],[0,-1],[-2,-2],[1,-1],[4,-2],[4,-5],[2,-1],[5,-3],[1,-1],[1,-1],[3,-7],[5,-6],[0,-1],[-1,-3],[1,-1],[2,-1],[1,1],[2,2],[1,0],[2,-1],[1,-1],[2,-4],[2,-3],[0,-1],[-1,-1],[-7,-1],[-4,1],[-3,1],[-3,2],[-2,3],[-1,-1],[-1,-2],[-2,-3],[-2,-2],[2,-2],[9,1],[2,-1],[2,-2],[-3,-3],[-6,-6],[-13,-10],[-3,-2],[0,-1],[2,0],[4,0],[4,1],[6,0],[2,-1],[-1,-1],[1,-2],[9,-4],[5,1],[5,4],[4,1],[5,0],[2,0],[-1,-1],[-3,-2],[-4,-3],[0,-1],[4,1],[9,-1],[5,-1],[3,1],[3,-1],[3,-2],[1,-1],[-3,0],[-2,0],[-2,-1],[-2,-2],[-1,-3],[-1,-3],[-2,-2],[-3,1],[-1,1],[0,1],[-1,0],[-2,0],[-2,-1],[-1,0],[14,-11],[4,-9],[3,-4],[1,-1],[-2,-2],[0,-2],[1,-6],[-1,-4],[-1,-8],[1,-3],[3,-2],[2,-3],[1,0],[1,-3],[1,-1],[1,-1],[1,1],[0,2],[2,2],[3,3],[3,6],[0,2],[0,4],[0,2],[3,6],[1,4],[1,7],[1,5],[3,4],[6,8],[2,2],[2,1],[4,-1],[3,-2],[4,-5],[5,-5],[9,-6],[2,-2],[5,-6],[2,-6],[2,-8],[1,-5],[1,-2],[1,-2],[-1,-4],[0,-2],[-1,-2],[-1,-1],[-2,-1],[-4,1],[-1,1],[-2,4],[-3,-3],[-1,-2],[1,-5],[0,-10],[1,-2],[3,-11],[5,-8],[14,-16],[1,-1],[1,-7],[1,-1],[1,-1],[1,0],[2,0],[5,5],[4,5],[3,3],[2,0],[2,1],[2,2],[1,2],[1,2],[1,7],[1,4],[2,5],[1,1],[10,13],[1,2],[5,14],[1,7],[1,4],[-1,4],[0,3],[1,2],[2,2],[2,1],[1,3],[1,0],[2,0],[2,-2],[2,0],[11,2],[0,1],[-6,3],[0,2],[0,2],[2,2],[3,1],[1,1],[0,2],[0,3],[0,1],[-7,5],[-3,-1],[-1,1],[-3,3],[-1,5],[0,2],[0,4],[0,1],[0,1],[-1,2],[0,2],[1,2],[0,2],[-2,2],[0,2],[1,5],[0,2],[-1,2],[-1,1],[1,1],[2,0],[3,-1],[4,-2],[4,0],[5,2],[5,1],[10,0],[2,-1],[9,-5],[7,-3],[3,1],[15,-1],[7,0],[4,0],[7,-3],[-1,-2],[-3,-4],[-4,-1],[-3,-1],[3,-3],[9,-2],[3,-5],[0,-2],[-1,-2],[1,-1],[2,0],[5,2],[6,-1],[9,-3],[1,-1],[2,-3],[0,-1],[-8,-7],[-4,-2],[-6,-3],[0,-2],[8,0],[6,-1],[2,-1],[2,-1],[1,-3],[1,-2],[0,-3],[-1,-2],[-7,-5],[-3,-2],[-5,-2],[-3,-2],[-2,0],[-3,2],[-3,1],[-5,-2],[-3,0],[-1,-1],[0,-1],[2,-3],[1,-2],[1,-1],[-1,-2],[1,-1],[5,-8],[1,-1],[1,1],[2,2],[1,1],[1,0],[0,-2],[-3,-7],[0,-1],[0,-2],[1,-4],[3,-3],[3,-4],[4,-4],[6,-5],[2,-3],[4,-5],[0,-3],[-1,-6],[-2,-9],[-2,-6],[0,-1],[-5,-4],[-2,-1],[-5,0],[-1,-1],[-2,-3],[-3,-5],[-3,-4],[-1,-1],[-3,-2],[-5,-5],[-3,-2],[-8,-2],[-7,-7],[-3,-2],[-3,-1],[-3,0],[-2,1],[-1,4],[-1,1],[-2,3],[-5,8],[-3,3],[-1,1],[-3,-1],[-1,1],[-4,2],[-1,2],[0,1],[3,1],[-1,1],[-5,4],[-1,2],[-1,0],[-4,3],[-4,1],[-5,-5],[-3,-2],[1,-1],[2,-1],[1,0],[2,3],[2,0],[3,0],[3,-2],[1,-1],[0,-1],[8,-9],[2,-1],[1,-2],[1,-4],[2,-3],[3,-6],[4,-8],[1,-3],[-2,-1],[-1,-1],[-3,2],[-8,3],[-1,0],[-2,-2],[-1,-4],[-1,0],[-4,1],[-8,4],[-5,3],[-3,3],[-3,4],[-4,5],[-4,2],[-5,-2],[-8,-1],[-16,1],[-2,-1],[-1,0],[2,-3],[-1,-1],[-1,-1],[0,-1],[2,-3],[3,-2],[7,-3],[6,-3],[3,-2],[1,-2],[0,-2],[-1,-4],[-1,-1],[-19,-21],[-7,-8],[-3,-5],[-3,-3],[-3,-2],[-4,-1],[-7,0],[-8,1],[-4,2],[-8,7],[-5,5],[-2,1],[-2,4],[-2,1],[-4,0],[-4,2],[-9,7],[-5,3],[-4,2],[-4,0],[-2,-1],[3,-3],[-1,0],[-3,1],[-3,0],[-6,2],[-6,0],[-3,0],[-5,2],[-5,0],[-9,0],[-2,0],[-1,-1],[4,-3],[7,-4],[-1,4],[0,1],[2,1],[11,-2],[12,-4],[3,-1],[4,-1],[4,-3],[5,-5],[10,-12],[3,-3],[4,-2],[22,-4],[7,0],[15,-1],[8,-2],[2,-2],[1,-5],[-1,-3],[-4,-8],[-3,-5],[-17,-25],[-2,-5],[-1,-4],[-3,-3],[-7,-6],[-8,-4],[-4,-1],[-4,1],[-3,1],[-4,5],[0,-1],[3,-7],[-1,-1],[-2,1],[-6,3],[-1,0],[-1,-1],[-2,0],[-2,1],[-3,3],[-1,1],[0,4],[-1,0],[-6,-2],[-1,-1],[2,-1],[1,-1],[3,-6],[0,-1],[-2,-1],[-6,2],[-1,0],[3,-6],[1,-3],[0,-1],[-4,-7],[-2,-3],[-3,-1],[-3,1],[-2,2],[-2,0],[-1,-3],[-2,-1],[-3,-1],[-4,0],[-4,2],[-12,6],[-4,1],[-7,1],[-1,1],[0,1],[1,1],[-1,1],[-2,-1],[-1,-1],[-3,-1],[-4,1],[-6,2],[-12,7],[-13,5],[-7,7],[3,-7],[0,-2],[-2,-1],[0,-2],[3,-5],[4,-1],[4,0],[0,1],[-2,1],[-1,1],[-1,3],[1,0],[3,-1],[3,-2],[18,-8],[5,-1],[4,-2],[1,-1],[-1,-2],[-8,-5],[0,-1],[5,1],[6,4],[3,2],[4,2],[4,-3],[5,-5],[5,-3],[6,-2],[4,-2],[6,-5],[1,-3],[1,-11],[-1,-3],[0,-2],[-2,-3],[-2,-2],[-4,0],[-3,-1],[-7,-6],[-2,-1],[-12,2],[-5,2],[-2,0],[-1,-2],[-1,0],[-5,-1],[-1,-1],[1,-2],[1,-2],[1,-1],[1,-2],[3,-1],[5,-1],[1,-3],[0,-1],[-2,-2],[-2,0],[-4,3],[-1,0],[-2,-2],[-2,0],[-3,0],[-1,-1],[0,-2],[-1,-2],[-3,-3],[-2,-2],[0,-2],[2,-1],[2,-3],[2,-4],[1,-2],[-2,0],[-2,2],[-2,3],[-4,3],[-8,3],[-1,0],[0,-1],[6,-4],[2,-2],[0,-2],[-4,-3],[-1,-2],[2,-1],[0,-1],[-2,-2],[-2,-1],[-5,0],[-1,-1],[2,-2],[1,-1],[-2,-2],[-1,0],[-6,1],[2,-4],[1,-2],[1,-2],[4,-2],[0,-1],[-1,-1],[-2,-2],[-8,-6],[-6,-7],[-1,-2],[2,-5],[0,-1],[-2,-2],[-3,1],[-1,-1],[1,-2],[0,-4],[0,-4],[-3,-6],[-4,-9],[-3,-8],[-2,-7],[-2,-4],[-3,0],[-3,-3],[2,-1],[1,-1],[1,-2],[-1,-7],[-2,-11],[-1,-9],[0,-27],[0,-12],[-1,-7],[-2,-4],[-2,-1],[3,-1],[2,-2],[1,-2],[1,-4],[1,-2],[1,0],[2,0],[1,-2],[3,-6],[4,-1],[0,-4],[-2,-18],[0,-2],[2,4],[2,15],[2,6],[2,1],[8,1],[8,-2],[3,0],[3,1],[2,-2],[1,-1],[1,-8],[1,-4],[5,-16],[2,-8],[3,-13],[1,-4],[6,-18],[1,-5],[0,-4],[0,-2],[-1,-4],[-2,-6],[-2,-4],[-2,-3],[-1,-2],[-2,-1],[0,-1],[2,1],[2,2],[4,3],[2,1],[4,1],[0,-2],[-2,-3],[3,2],[7,4],[25,10],[6,1],[8,-2],[7,-5],[8,-5],[8,-4],[12,-4],[4,-2],[7,-2],[3,-2],[4,-5],[7,-7],[5,-4],[5,-4],[6,-7],[9,-16],[2,-2],[5,-3],[10,-4],[15,-8],[7,-3],[4,-1],[5,-2],[4,-4],[3,-3],[2,-4],[2,-2],[4,-3],[2,-2],[0,-3],[-4,-12],[-1,-1],[5,9],[2,2],[2,1],[4,0],[6,-1],[5,0],[5,1],[3,1],[3,-1],[3,1],[1,1],[2,0],[7,-3],[2,0],[10,-3],[7,1],[1,0],[2,-4],[2,0],[3,0],[3,-1],[5,-4],[2,-4],[3,-9],[0,-2],[-4,-19],[-2,-7],[0,-7],[1,-3],[4,-7],[0,-1],[2,-9],[1,-4],[0,-5],[-1,-7],[0,-6],[1,-8],[0,-6],[-2,-3],[-1,-3],[-1,-6],[0,-2],[1,-4],[1,-2],[3,-3],[2,-3],[5,-10],[3,-5],[4,-7],[1,-4],[-1,-2],[-2,-2],[-3,-2],[-1,-2],[0,-1],[5,2],[2,0],[3,-2],[2,-4],[3,-3],[4,-2],[5,-5],[7,-10],[1,-2],[2,-5],[3,-8],[1,-6],[0,-2],[-1,-3],[-5,-4],[-5,-8],[1,0],[4,3],[5,7],[3,1],[3,0],[5,-2],[4,-3],[3,-4],[5,-9],[6,-8],[3,-6],[-1,4],[-2,5],[-5,7],[-3,4],[0,2],[0,2],[0,4],[1,5],[1,4],[2,2],[1,3],[1,2],[0,2],[5,4],[1,-1],[1,-4],[1,-1],[2,0],[2,-2],[1,-2],[1,-2],[1,-2],[1,-8],[1,-3],[0,4],[1,6],[1,3],[3,4],[0,2],[-2,2],[-5,10],[0,2],[1,1],[1,3],[1,4],[1,3],[4,4],[3,6],[1,4],[1,2],[2,1],[-2,2],[-1,1],[0,5],[0,5],[-2,3],[-3,5],[-1,2],[0,6],[0,3],[1,2],[0,3],[-4,4],[-1,4],[-1,9],[-1,12],[-2,9],[-2,5],[0,4],[1,1],[1,5],[1,1],[2,-1],[0,1],[-3,2],[-1,3],[0,1],[2,3],[0,1],[-2,2],[-4,3],[1,1],[1,2],[0,1],[-2,1],[-2,2],[-2,2],[-2,5],[-1,3],[-1,5],[-2,7],[-1,1],[-1,1],[-2,1],[0,1],[2,1],[21,11],[2,1],[10,6],[5,4],[4,4],[7,5],[3,3],[2,4],[11,12],[4,6],[3,5],[4,7],[4,7],[4,6],[1,6],[1,9],[1,8],[0,12],[0,11],[-1,16],[-1,6],[-2,6],[-3,12],[-1,4],[-2,6],[-8,15],[-9,10],[-2,2],[-3,3],[-6,4],[-3,2],[-10,11],[-3,1],[-1,3],[0,2],[0,5],[1,3],[0,3],[1,1],[5,8],[3,6],[2,4],[2,2],[4,4],[3,4],[-1,2],[-2,2],[0,2],[3,4],[0,2],[0,4],[1,1],[3,0],[6,-6],[1,0],[-2,2],[-2,5],[1,1],[4,5],[0,2],[-1,3],[-1,2],[3,6],[-1,1],[-6,1],[-1,2],[0,1],[3,1],[0,1],[-5,13],[-1,3],[2,5],[3,2],[0,1],[-4,0],[-2,1],[-2,4],[1,2],[0,1],[2,5],[2,1],[0,1],[-7,-2],[-4,2],[-3,-1],[-2,1],[1,2],[6,8],[3,5],[2,4],[1,3],[0,2],[-1,9],[0,2],[3,3],[4,4],[-6,4],[-3,4],[-2,2],[-1,2],[-3,4],[-1,5],[-2,11],[0,6],[0,4],[1,2],[1,2],[5,4],[8,7],[6,2],[5,-1],[9,-2],[7,-3],[23,-9],[4,-4],[-4,-3],[0,-1],[9,6],[2,2],[2,0],[6,-3],[3,0],[3,-2],[8,-6],[-2,3],[1,2],[6,4],[6,2],[5,3],[5,4],[3,2],[1,0],[2,-1],[6,-5],[4,-2],[3,-3],[4,-5],[1,-1],[3,-3],[4,0],[2,0],[0,-1],[1,-2],[0,-1],[0,-2],[-1,-4],[-3,-6],[2,0],[1,1],[3,3],[2,0],[4,-2],[3,-3],[2,-2],[1,-2],[1,-2],[2,-3],[-2,-2],[-4,-2],[1,-1],[5,2],[2,1],[1,2],[1,1],[7,-4],[1,-2],[-1,-1],[-1,-1],[-3,-1],[-2,-4],[0,-1],[1,-1],[5,-1],[0,-1],[-3,-1],[0,-2],[5,-7],[4,-4],[2,0],[5,0],[4,-1],[8,-5],[5,0],[5,1],[2,0],[3,-1],[1,-2],[0,-2],[0,-3],[2,-3],[2,-1],[3,0],[3,3],[2,0],[1,2],[1,4],[1,2],[2,1],[1,-1],[1,-2],[2,-5],[0,-2],[0,-3],[-1,-1],[-2,-2],[-2,-3],[-2,-3],[-2,-7],[-1,-4],[0,-3],[0,-3],[0,-3],[1,-3],[2,-4],[1,-1],[0,-3],[0,-1],[-2,-3],[-3,-3],[-5,0],[-15,0],[-4,0],[1,-2],[4,-1],[4,0],[15,-1],[2,-2],[1,-3],[2,-3],[1,-5],[0,-3],[-1,-3],[-1,-3],[-1,-5],[-1,-5],[1,-3],[8,0],[1,-2],[0,-2],[-2,-6],[-1,-1],[2,-4],[-1,-1],[0,-1],[-1,-3],[-1,-4],[-1,-3],[-2,-3],[-1,0],[-1,0],[-2,7],[-1,1],[-1,-1],[0,-1],[0,-1],[0,-2],[-1,-1],[-3,-2],[-5,-2],[0,-2],[3,-1],[5,-2],[2,-1],[4,2],[7,8],[4,1],[2,1],[3,0],[4,0],[6,1],[2,-1],[2,-2],[3,-2],[1,-2],[1,-3],[2,-8],[2,-2],[0,-2],[0,-3],[0,-4],[-2,-10],[-1,-4],[-3,-5],[-4,-2],[-6,-3],[-3,-1],[-3,-3],[0,-1],[7,4],[8,2],[2,2],[2,3],[2,5],[3,13],[2,4],[2,0],[1,-1],[3,-8],[0,-1],[-1,-2],[-4,-7],[2,0],[4,7],[1,2],[0,4],[2,2],[0,-1],[1,-8],[0,-6],[1,-2],[-1,-6],[1,-1],[1,5],[0,4],[1,2],[1,2],[5,5],[6,4],[4,3],[3,2],[5,2],[3,3],[2,5],[1,4],[1,2],[3,3],[2,0],[2,-1],[2,-3],[2,-4],[1,-3],[1,-2],[0,-8],[2,6],[0,2],[0,3],[0,2],[-2,5],[-1,3],[0,2],[2,1],[3,0],[1,1],[-2,2],[0,1],[2,4],[1,0],[3,-1],[-1,2],[0,1],[1,1],[4,-1],[1,1],[3,0],[0,2],[-3,1],[-3,1],[-1,1],[0,2],[-1,3],[0,1],[1,0],[1,-1],[1,2],[1,5],[1,1],[3,-2],[0,1],[-2,7],[0,1],[3,1],[3,-1],[5,-5],[1,0],[-1,2],[-3,3],[-2,2],[-2,1],[-2,1],[-2,5],[0,1],[0,3],[1,5],[1,1],[1,1],[2,0],[2,0],[5,-4],[0,1],[-2,2],[-1,2],[-1,2],[0,2],[2,5],[1,4],[4,11],[1,2],[1,1],[1,2],[3,0],[6,-4],[2,-2],[0,-3],[-3,-5],[-5,-3],[-1,-2],[1,0],[4,2],[5,1],[3,0],[3,-5],[0,-7],[-1,-6],[2,3],[2,1],[2,-3],[1,-4],[1,-3],[2,-4],[3,-3],[-3,-4],[-3,-2],[0,-2],[5,-2],[1,-2],[-1,-2],[1,0],[3,4],[3,-1],[3,-8],[-2,-4],[-4,-2],[-3,-1],[-5,0],[-1,-1],[1,-1],[4,0],[6,1],[5,2],[2,0],[2,-1],[0,-1],[-2,-1],[1,-2],[2,-4],[0,-1],[-2,-3],[3,0],[3,1],[1,-1],[3,-5],[1,-6],[-6,-7],[-3,-2],[-5,-3],[-1,-4],[-3,-3],[2,0],[4,6],[3,1],[2,0],[0,-1],[0,-2],[2,0],[6,4],[3,1],[4,0],[0,-1],[-2,-9],[-4,-7],[-7,-4],[-3,-3],[-3,-4],[2,0],[6,5],[5,2],[6,2],[3,-1],[5,-10],[3,-1],[2,0],[5,-3],[1,-2],[0,-3],[-2,-1],[0,-2],[1,-6],[-1,-3],[-3,-3],[-2,-1],[-3,-1],[-2,-2],[-1,-1],[-3,1],[1,-1],[1,-1],[3,-1],[3,1],[3,0],[5,-2],[2,-2],[0,-1],[-1,-1],[-2,-4],[-1,-2],[1,-1],[2,-2],[2,0],[2,0],[3,-1],[8,-9],[0,-6],[-2,-4],[1,-4],[0,-5],[-5,-2],[-14,3],[-9,3],[0,2],[2,2],[-2,0],[-2,-1],[-1,-1],[2,-4],[8,-3],[4,-5],[3,0],[2,-1],[2,-2],[-1,-1],[-4,-1],[-3,-3],[2,-1],[7,-2],[5,0],[2,-2],[-2,-2],[-5,-2],[-1,-3],[5,-2],[4,1],[1,0],[1,-8],[1,-2],[-4,-1],[0,-2],[2,-1],[5,-1],[2,-2],[0,-2],[1,-1],[2,-1],[3,3],[2,3],[2,-1],[1,-3],[2,-4],[2,0],[0,-5],[3,4],[2,-1],[2,0],[-1,-4],[-1,-4],[1,-2],[1,-3],[4,-5],[-1,-2],[-4,-4],[-2,-7],[0,-3],[-2,-4],[-3,-4],[2,1],[6,7],[3,2],[8,2],[2,2],[3,1],[1,-3],[1,-4],[2,-1],[2,1],[3,-1],[-2,-3],[-7,-11],[-2,-4],[0,-3],[2,4],[9,10],[1,1],[2,5],[2,2],[4,-1],[3,-2],[1,-5],[2,-6],[3,-7],[8,-3],[2,0],[5,2],[1,3],[4,1],[3,0],[1,-6],[2,-3],[3,-3],[3,-1],[4,-1],[2,-3],[0,-1],[-2,-3],[-2,-5],[-4,-3],[-5,0],[-8,-2],[0,-1],[-2,-2],[-3,-2],[-3,-2],[-3,-7],[-2,-3],[-2,-1],[-4,1],[-2,-1],[-2,-1],[-1,-2],[0,-1],[-5,-2],[-8,-5],[-4,-1],[-3,1],[-2,0],[-1,-2],[-4,-3],[-2,-1],[0,-2],[-1,-4],[0,-1],[-1,-1],[-3,1],[-4,2],[1,-2],[6,-5],[1,-2],[-1,-3],[-4,-3],[0,-2],[1,-1],[-1,-1],[-2,-2],[1,-1],[5,2],[4,5],[3,5],[2,2],[6,1],[3,3],[5,4],[5,5],[6,8],[7,6],[9,4],[7,2],[4,0],[1,1],[-4,1],[-3,1],[-4,-1],[-1,2],[0,1],[1,2],[3,1],[16,-2],[6,-2],[6,-13],[1,-5],[1,-3],[-1,-2],[-2,-2],[-7,-5],[-1,-1],[0,-1],[3,-1],[1,-1],[1,-5],[3,3],[6,8],[5,4],[4,1],[5,1],[1,0],[1,-3],[2,-6],[3,-1],[4,-1],[4,-6],[2,-5],[1,-3],[0,-1],[0,-2],[1,-2],[1,-2],[-1,-5],[-2,-7],[2,-7],[-1,-4],[0,-5],[1,-3],[1,-2],[-2,-1],[-9,-3],[-3,0],[-1,-2],[3,0],[5,0],[6,-2],[2,-2],[1,-2],[0,-3],[-2,-1],[-3,0],[-3,2],[0,-2],[5,-3],[1,-2],[3,-2],[0,-3],[0,-3],[-9,-12],[-8,-8],[-7,-6],[-12,-13],[-1,-1],[-2,0],[-6,2],[-4,-1],[-9,-2],[-2,-2],[-5,-4],[-2,-1],[-5,-1],[-5,1],[-2,-1],[-2,-2],[-1,-1],[0,-4],[-12,-17],[-3,-5],[-6,-6],[-6,-11],[-6,-4],[-2,-6],[-5,-4],[-10,-1],[-5,-1],[-5,2],[-5,-2],[-6,-1],[-3,0],[-12,-5],[-3,5],[-2,2],[-7,0],[-6,3],[-5,0],[-4,1],[-4,0],[-3,0],[-5,0],[-3,-3],[-10,1],[-4,2],[-3,1],[-5,-1],[-4,-2],[-9,3],[-10,-2],[-9,1],[-2,1],[-14,-3],[-5,2],[-5,-6],[-3,1],[-4,0],[-1,1],[-2,-1],[-2,-3],[-2,0],[-3,-6],[-6,-4],[-8,-22],[-1,-9],[-3,-6],[-2,-1],[-3,0],[-14,-4],[-6,-4],[2,-2],[-2,-2],[-4,-1],[-3,-3],[-3,-2],[-1,-4],[-7,-7],[-8,-14],[-4,-11],[-5,-8],[-4,-3],[-2,0],[-3,0],[-4,4],[-3,1],[-7,5],[-18,5],[3,-2],[2,-3],[5,-1],[4,0],[10,-6],[5,-3],[3,-2],[3,-4],[-2,-8],[-2,-7],[-3,-5],[-8,-14],[-4,-5],[-7,-16],[-8,-8],[-4,-4],[-4,-8],[-10,-5],[-4,-2],[-3,1],[-4,-5],[-5,-2],[-1,-5],[-12,-11],[-5,-2],[-4,-3],[-1,-5],[-3,-3],[-1,-2],[-3,-7],[-5,-10],[-7,-1],[-2,-4],[-3,-5],[-4,-3],[-8,1],[2,-2],[7,-3],[1,-5],[-4,-2],[-7,-6],[-10,-12]],[[2311,9385],[-4,-1],[-4,4],[0,4],[0,2],[0,2],[2,2],[4,1],[2,-1],[1,-2],[3,-2],[1,-1],[0,-2],[-1,-3],[-1,-2],[-1,-1],[-2,0]],[[1819,9365],[1,-1],[4,1],[4,2],[6,1],[8,2],[2,-2],[1,0],[2,3],[0,1],[0,2],[0,4],[1,3],[5,5],[2,1],[4,1],[9,0],[8,-3],[11,-3],[17,-7],[5,-3],[1,-3],[-3,-5],[-7,-8],[-6,-3],[-2,-2],[3,-1],[3,-2],[3,3],[3,3],[4,3],[1,0],[0,-2],[0,-1],[0,-1],[0,-1],[2,-1],[2,1],[5,4],[5,6],[7,3],[2,2],[7,2],[-1,1],[1,5],[-2,2],[-8,4],[-4,4],[1,4],[4,-1],[12,0],[2,0],[11,-7],[4,-4],[3,-1],[7,-3],[2,-3],[1,0],[1,-1],[-1,-1],[0,-3],[1,-1],[5,0],[1,-1],[1,-3],[2,-5],[2,-6],[3,-10],[5,-14],[2,-8],[1,-2],[1,-1],[3,-2],[3,-2],[3,-1],[1,1],[1,1],[1,4],[10,5],[0,1],[-1,2],[0,1],[2,1],[-6,7],[-5,7],[-2,9],[-1,3],[0,5],[-1,2],[-2,1],[0,2],[0,2],[0,2],[-2,3],[-7,27],[0,2],[1,2],[3,1],[3,0],[2,1],[-2,1],[-2,3],[-1,1],[2,3],[9,-2],[6,-2],[10,-5],[2,0],[1,3],[2,1],[3,0],[10,-4],[11,-7],[8,-4],[5,-5],[3,-4],[3,-4],[0,-1],[-1,-1],[1,-2],[1,-3],[1,-2],[1,-4],[1,-5],[1,-3],[10,-25],[1,-5],[2,-2],[7,-9],[3,-7],[1,-5],[0,-2],[0,-2],[0,-3],[-1,-2],[-1,-2],[-2,-3],[-2,-7],[0,-2],[2,-2],[9,-8],[6,-9],[3,-2],[7,-6],[8,-3],[3,-2],[3,-2],[1,0],[1,0],[1,1],[0,1],[-3,4],[0,2],[1,0],[9,-7],[4,-3],[6,-4],[11,-7],[1,0],[6,0],[1,0],[1,-1],[1,-1],[0,-4],[2,-3],[9,1],[2,0],[2,0],[1,-2],[2,-5],[2,-9],[0,-3],[-1,-6],[-1,-2],[-2,0],[-5,0],[-3,2],[-2,2],[-1,5],[-1,1],[-1,-1],[-1,-4],[-2,-2],[-1,-2],[-2,1],[-4,2],[-6,5],[-3,1],[-1,0],[-3,-2],[-5,-3],[-2,-3],[1,-1],[0,-2],[1,-2],[-1,-2],[0,-1],[-2,-1],[-3,0],[-5,1],[-4,1],[-7,5],[-1,1],[-2,-1],[-1,-2],[1,-2],[4,-2],[4,-4],[1,-1],[1,0],[0,-1],[1,-2],[0,-4],[-2,-7],[-1,-2],[1,0],[6,8],[3,2],[6,3],[3,3],[8,0],[3,-1],[2,-2],[0,-1],[-2,-3],[0,-1],[-1,-2],[1,-2],[0,-1],[2,-1],[2,0],[1,0],[1,-1],[1,-2],[0,-3],[-2,-7],[-3,-2],[-11,-3],[-3,-2],[-7,-2],[-3,-2],[-1,0],[-8,0],[-8,-1],[-10,2],[-7,1],[-8,4],[-3,-1],[-3,-2],[-15,3],[-2,2],[1,1],[4,4],[0,1],[0,1],[-7,1],[-8,2],[-7,1],[-6,0],[-4,0],[-3,2],[-2,2],[0,2],[-1,1],[1,4],[-1,2],[-1,2],[-4,2],[-3,-1],[-3,-1],[-2,-4],[-5,-9],[-3,-2],[-6,-7],[-3,-2],[-11,-3],[-14,-1],[-6,-2],[-4,-4],[-6,-4],[-15,-5],[-14,-2],[-14,-1],[-10,-2],[-3,1],[-5,-1],[-5,-2],[-6,-1],[-22,-1],[-10,-2],[-5,0],[-5,0],[-3,1],[-2,2],[-3,4],[-6,10],[-2,4],[0,7],[0,4],[-2,9],[-11,4],[-7,1],[-10,0],[-13,-1],[-13,1],[-7,2],[-6,2],[-12,5],[-1,2],[-1,3],[-3,3],[-8,9],[-3,4],[-1,2],[0,3],[-1,6],[-1,4],[1,2],[1,0],[16,5],[29,4],[26,4],[12,-1],[6,-1],[7,-1],[13,0],[16,-2],[3,0],[7,1],[2,2],[12,-1],[2,1],[2,1],[-3,3],[-10,5],[-29,10],[-7,2],[-10,2],[-6,1],[-7,-1],[-3,0],[-7,-2],[-7,-2],[-13,-1],[-19,-1],[-3,1],[-4,1],[-2,1],[-19,-2],[-16,2],[-19,15],[-3,4],[0,2],[3,2],[9,6],[3,1],[14,4],[14,3],[11,4],[5,1],[5,0],[5,1],[-1,1],[-4,2],[0,1],[2,1],[7,1],[7,-1],[4,0],[1,2],[-1,1],[-7,2],[-33,-6],[-16,-1],[-10,-2],[-6,0],[-7,2],[-1,1],[0,1],[2,4],[7,2],[4,5],[-4,0],[-13,-1],[-6,1],[-8,2],[-2,2],[-1,2],[-1,3],[1,6],[0,3],[1,1],[10,11],[6,2],[4,3],[0,1],[-1,2],[-4,3],[-1,2],[-1,2],[0,2],[3,4],[6,5],[17,12],[8,5],[8,2],[11,6],[28,9],[25,9],[10,-2],[2,-2],[2,-2],[1,-2],[1,-3],[1,-6],[0,-4],[0,-3],[-1,-3],[-1,-3],[-2,-3],[-3,-4],[-6,-6],[0,-2]],[[2075,9384],[-1,0],[-3,1],[-4,3],[-6,6],[-8,6],[-1,3],[-2,3],[-9,6],[-6,3],[-5,1],[-1,2],[3,5],[4,4],[2,2],[7,1],[24,3],[5,0],[6,-2],[8,-5],[3,-1],[2,-1],[2,-2],[0,-2],[1,-5],[-1,-6],[-1,-3],[-5,-8],[-5,-4],[-1,-3],[-2,-3],[-3,-3],[-3,-1]],[[2790,9426],[5,-1],[30,2],[6,-1],[19,-7],[5,-2],[3,-3],[2,-4],[1,-1],[7,-3],[2,-3],[1,-2],[2,-3],[3,-2],[3,-2],[2,-1],[-1,-5],[2,-2],[3,-3],[1,-1],[-2,-3],[-7,-1],[-17,1],[-22,4],[-14,-1],[-6,-2],[-16,-5],[-6,0],[-5,-1],[-9,4],[-3,3],[-1,1],[-2,5],[-2,6],[-1,5],[-1,3],[-3,2],[-9,1],[-3,2],[-1,2],[-1,2],[0,3],[0,3],[1,0],[1,0],[-2,3],[-1,4],[0,4],[0,3],[1,1],[1,1],[4,1],[6,0],[8,-4],[7,0],[9,-3]],[[2594,9274],[2,-1],[6,1],[5,2],[9,5],[5,1],[15,0],[3,-1],[-2,-2],[0,-1],[0,-1],[2,-2],[3,-2],[2,2],[0,4],[3,15],[1,5],[0,4],[0,4],[-1,3],[-4,1],[-5,0],[-3,0],[-3,1],[-3,1],[-1,2],[-4,5],[-2,3],[-6,5],[-3,2],[2,2],[5,3],[3,2],[4,6],[3,1],[8,-1],[12,-5],[7,-4],[2,-1],[0,1],[-2,2],[-8,6],[-4,4],[-2,3],[1,1],[4,1],[1,2],[-6,1],[-3,0],[-3,-1],[-3,0],[-5,2],[-1,1],[-3,4],[-2,4],[-1,2],[-1,1],[0,5],[0,3],[0,3],[2,2],[3,4],[2,1],[3,1],[8,-2],[20,-7],[0,2],[-23,10],[-8,2],[-2,4],[12,13],[11,3],[6,4],[9,0],[8,-3],[1,1],[-4,5],[0,1],[5,3],[9,3],[11,2],[2,2],[3,1],[5,1],[12,0],[7,0],[10,-2],[5,-4],[2,-2],[3,-7],[3,-9],[3,-4],[6,-3],[4,-2],[2,-3],[0,-3],[-1,-4],[1,-4],[3,-4],[2,-2],[4,-3],[0,-1],[-1,-2],[-3,-2],[-7,-7],[-9,-8],[-7,-6],[0,-2],[13,10],[5,0],[0,-2],[-3,-5],[-3,-4],[-4,-3],[1,-1],[6,-5],[-1,-1],[-3,0],[-1,0],[-1,-1],[-1,-1],[0,-2],[1,-3],[0,-2],[-1,-1],[1,0],[2,0],[1,1],[3,3],[9,9],[5,4],[2,0],[5,-2],[2,0],[-6,7],[-1,2],[2,3],[0,1],[4,2],[2,1],[2,-1],[2,-3],[1,-3],[2,-1],[4,1],[3,3],[4,-2],[5,-4],[0,-5],[0,-5],[0,-4],[7,-6],[4,-3],[1,0],[0,1],[-1,2],[-3,2],[-2,4],[-2,4],[1,9],[4,5],[3,-1],[4,-3],[4,0],[5,0],[11,-6],[5,0],[0,2],[-4,2],[-7,3],[-10,4],[-5,4],[0,2],[0,2],[0,2],[1,2],[2,1],[10,5],[7,3],[5,0],[9,0],[10,-1],[5,-1],[6,-4],[8,-3],[3,-1],[3,0],[4,1],[4,0],[11,-5],[3,-3],[2,-3],[1,-4],[1,-3],[0,-2],[-10,-11],[-4,-2],[-2,-4],[-4,-7],[-4,-5],[0,-1],[3,2],[3,6],[3,4],[4,4],[8,5],[7,2],[6,-1],[5,0],[4,-1],[2,-1],[1,-1],[1,-3],[0,-3],[-1,-2],[-2,-3],[-8,-3],[-5,-3],[-3,-1],[-8,-1],[0,-1],[7,-1],[7,0],[0,-1],[-4,-5],[-1,-4],[1,-3],[0,-2],[-3,-6],[-3,-4],[1,-1],[7,7],[2,7],[3,7],[3,4],[2,1],[7,1],[4,3],[4,2],[1,0],[3,-2],[0,-1],[-4,-7],[-9,-11],[3,1],[3,3],[3,2],[4,4],[3,-3],[4,-3],[2,-6],[4,-3],[2,-2],[0,3],[-4,8],[1,3],[3,2],[8,6],[5,-2],[4,-2],[1,1],[5,-1],[6,-1],[7,-1],[7,-3],[5,-3],[3,-3],[2,-3],[1,-1],[1,-4],[-1,-2],[-5,-5],[-2,-3],[-3,-1],[-7,1],[-3,0],[-2,-2],[-8,-7],[-4,-3],[-4,-2],[-1,-1],[9,0],[2,2],[3,4],[3,4],[8,2],[10,-4],[5,0],[4,4],[5,3],[1,1],[1,-1],[4,-3],[1,-2],[0,-6],[-1,-2],[-3,-5],[-7,-6],[-5,-3],[-5,-1],[-6,-3],[-2,-2],[-2,-2],[-2,-2],[-2,-1],[3,-3],[1,0],[1,2],[4,5],[2,2],[2,0],[1,0],[1,-1],[2,-1],[0,-5],[-4,-17],[3,5],[7,18],[2,3],[4,4],[8,5],[6,3],[7,2],[4,1],[4,0],[3,-3],[3,-1],[5,1],[3,0],[3,-1],[3,-2],[5,-3],[11,-4],[1,-1],[2,-2],[1,-2],[0,-3],[-2,-2],[-2,-1],[-2,-1],[-2,-1],[-4,-4],[-2,0],[-6,-2],[-6,0],[-4,-2],[-7,-3],[-10,-7],[0,-2],[4,-1],[3,1],[4,5],[5,2],[6,1],[9,2],[4,-1],[1,0],[0,-1],[1,-2],[-2,-2],[-2,-2],[-4,-6],[3,-1],[4,-1],[3,2],[2,3],[2,2],[3,1],[2,1],[2,1],[1,1],[-3,2],[0,1],[1,3],[2,3],[2,2],[2,0],[6,-2],[4,-4],[9,-10],[2,-2],[3,-8],[1,-4],[-1,-2],[-1,-2],[-1,0],[-2,0],[-13,3],[-6,-1],[-2,0],[-2,-2],[-2,-2],[-1,-2],[-3,-1],[-8,0],[-4,-1],[-8,-3],[-3,-1],[-1,-2],[5,0],[8,3],[8,0],[12,-5],[4,-1],[3,0],[2,1],[11,-1],[3,0],[5,-3],[8,-5],[1,-1],[1,-1],[1,-2],[-1,-4],[0,-1],[-3,-1],[-11,1],[-4,1],[-4,-1],[-3,0],[-5,2],[-4,2],[-8,-2],[-5,1],[-6,-1],[-12,-6],[1,-1],[16,5],[3,0],[5,-2],[8,-4],[3,-2],[0,-6],[-2,-4],[-2,-4],[-4,0],[-8,3],[-4,0],[-2,0],[-4,-2],[-1,0],[-14,4],[-3,0],[0,-1],[13,-6],[9,0],[6,-1],[3,-2],[2,-1],[0,-4],[3,-4],[3,-1],[1,0],[3,1],[3,0],[3,-1],[3,-2],[4,0],[3,-2],[2,0],[8,1],[3,-1],[1,-1],[-2,-1],[-6,-3],[-1,-3],[3,-3],[2,-3],[0,-2],[-2,-5],[0,-2],[5,4],[1,-1],[0,-5],[1,0],[2,5],[-1,6],[3,2],[8,2],[-1,-9],[0,-5],[-4,-8],[-3,-3],[2,-1],[1,0],[2,1],[3,6],[7,6],[1,1],[0,-3],[-1,-4],[3,-2],[3,2],[2,2],[3,-1],[2,0],[0,-2],[-1,-8],[0,-2],[4,-5],[0,3],[-1,6],[1,3],[3,3],[6,5],[3,1],[1,-1],[3,-2],[-1,-2],[-3,-1],[-2,-3],[-1,-4],[2,-2],[5,0],[5,3],[3,-1],[4,-4],[7,-7],[3,2],[5,-6],[-6,-4],[2,-8],[-9,0],[-4,0],[-3,0],[-4,0],[4,-2],[5,-1],[1,-2],[5,0],[3,0],[6,0],[1,3],[4,2],[2,2],[2,-1],[6,-2],[8,-6],[-4,-3],[-1,-3],[-1,-3],[0,-3],[-2,-1],[-11,-10],[2,0],[5,2],[9,4],[5,1],[3,-1],[2,0],[2,1],[3,-1],[6,-2],[7,9],[4,-2],[4,-5],[9,-9],[4,-5],[2,-2],[0,-3],[-4,-2],[-2,-1],[-6,5],[-5,2],[-3,0],[-3,-2],[1,-1],[12,-7],[2,-5],[0,-2],[-8,-4],[-2,0],[-6,2],[-3,3],[-3,1],[-4,0],[-1,0],[4,-6],[0,-1],[-2,-1],[-1,-3],[8,-4],[6,-5],[1,-2],[-4,-1],[-3,0],[-7,0],[-3,1],[-1,-1],[4,-2],[1,-2],[1,-2],[1,-2],[0,-2],[-3,-2],[-3,-5],[-2,-4],[-3,-1],[-1,1],[-4,-1],[-6,2],[-2,2],[-6,9],[0,-1],[1,-5],[0,-2],[-6,-2],[0,-1],[4,-2],[4,-1],[0,-4],[0,-18],[-1,-6],[-3,-6],[-3,-5],[-4,3],[-1,4],[-1,1],[-2,2],[-2,1],[-3,0],[-2,-3],[-3,2],[-3,4],[1,8],[1,5],[-2,-2],[-3,-7],[-3,-8],[-3,3],[-2,4],[-3,4],[-3,4],[-4,5],[-2,6],[-1,2],[-2,5],[-1,1],[0,1],[-2,3],[1,3],[2,4],[3,3],[4,3],[5,1],[2,4],[3,6],[3,5],[4,3],[-2,0],[-4,-2],[-3,-3],[-4,-6],[-3,-3],[-8,-4],[-3,-1],[-4,0],[-8,0],[-2,1],[1,4],[6,7],[-1,1],[-2,-3],[-3,-2],[-2,0],[-3,0],[-4,4],[-2,1],[-4,2],[-2,1],[-6,11],[-2,3],[-1,2],[-2,3],[-3,1],[-1,0],[1,-2],[0,-2],[-3,-1],[-3,0],[-3,2],[0,-3],[3,-5],[0,-6],[-1,-1],[-2,0],[-2,1],[-5,4],[-5,4],[-4,2],[0,-2],[2,-6],[3,-5],[4,-5],[7,-6],[3,-3],[-2,-4],[-2,-2],[-1,0],[-5,0],[-7,2],[-4,3],[-5,7],[-9,7],[-2,0],[-6,-3],[1,-1],[4,0],[3,-1],[7,-5],[0,-2],[-1,-3],[0,-3],[2,-4],[2,-3],[4,-1],[2,-1],[1,-1],[-3,-8],[0,-3],[1,-1],[6,4],[2,1],[2,0],[2,-1],[2,-2],[2,-3],[0,-2],[1,-1],[5,-3],[0,-1],[-5,-4],[-1,0],[1,-1],[4,-2],[3,-3],[2,-4],[0,-2],[0,-2],[0,-1],[2,-1],[1,1],[1,-1],[1,-3],[2,-9],[1,-3],[1,0],[0,9],[1,2],[3,-2],[5,-4],[3,-3],[1,-1],[-3,-3],[1,-1],[1,-2],[2,0],[1,4],[3,3],[2,2],[5,-2],[4,-5],[0,-1],[3,-2],[2,1],[4,-6],[-2,-2],[-4,-4],[-1,-1],[2,0],[8,0],[3,-1],[0,-3],[-4,-7],[-3,0],[-5,0],[-2,0],[0,-1],[6,-4],[2,-2],[3,-3],[1,-3],[0,-1],[-1,-2],[5,-1],[3,1],[3,0],[3,0],[0,-1],[0,-3],[-3,-3],[1,0],[3,0],[2,-1],[2,-6],[2,-5],[-1,-1],[-3,0],[1,-7],[1,-6],[0,-6],[0,-5],[-2,-1],[-3,0],[0,1],[-6,16],[-1,3],[-2,3],[-5,7],[0,-2],[1,-3],[2,-5],[1,-9],[1,-6],[0,-3],[-1,0],[-1,-1],[1,-2],[4,-6],[2,-4],[2,-4],[1,-3],[1,-1],[0,-1],[-2,-1],[-3,0],[-2,0],[-6,4],[0,-1],[3,-14],[0,-3],[-2,-1],[-2,1],[-2,4],[-4,4],[-5,5],[-4,4],[-2,-1],[0,-1],[-1,0],[-1,1],[-1,3],[-2,2],[-7,6],[-1,0],[1,-2],[1,-4],[-1,-1],[-2,0],[-3,2],[-2,4],[-3,7],[-2,3],[0,-2],[1,-7],[0,-2],[-2,0],[-1,0],[0,2],[-1,3],[-2,2],[-2,2],[-2,1],[0,3],[-1,1],[-4,-1],[-3,2],[-6,8],[-6,9],[-4,5],[-1,1],[2,-6],[2,-8],[1,-4],[-1,0],[-3,1],[-11,11],[-7,5],[-4,1],[-6,1],[-2,-3],[4,-6],[3,-5],[3,-3],[5,-6],[5,-8],[2,-3],[6,-3],[3,-1],[4,0],[0,-1],[-2,-3],[0,-1],[8,-3],[2,-2],[3,-4],[2,-1],[6,-8],[2,-1],[6,-3],[1,-1],[4,-6],[2,-2],[2,-7],[3,-3],[5,-3],[2,-1],[1,-1],[-1,-3],[0,-1],[-3,-2],[0,-3],[2,-5],[0,-3],[-2,-1],[-4,-2],[-2,0],[-2,2],[-4,2],[-7,5],[-10,3],[-4,2],[-2,2],[-2,1],[-26,4],[-4,2],[-3,1],[-2,2],[-10,5],[-1,1],[-7,9],[-5,10],[-2,1],[-5,1],[-5,0],[-3,-1],[-4,0],[-3,1],[-7,5],[-6,2],[-6,4],[-2,2],[0,1],[4,5],[-1,0],[-8,-4],[-2,1],[-4,4],[-4,3],[-6,10],[-4,3],[0,1],[5,1],[3,-1],[2,1],[5,4],[2,2],[0,2],[-4,0],[-1,1],[0,2],[-2,2],[-3,2],[-3,1],[-10,-1],[-2,1],[0,2],[2,5],[1,2],[0,1],[-2,0],[-6,-4],[-1,0],[-3,4],[-1,5],[-1,2],[-2,1],[-5,5],[-7,9],[-3,3],[-3,3],[-2,1],[1,1],[4,8],[0,2],[-4,-1],[-5,2],[-3,-2],[-2,0],[-2,1],[-1,-1],[-1,-6],[-1,-2],[-2,-1],[-1,1],[-1,1],[0,1],[0,8],[-3,1],[-5,1],[-2,0],[-1,2],[-1,2],[-1,4],[-1,3],[-2,0],[-1,0],[-1,-1],[-1,-1],[-3,0],[0,-2],[2,-3],[3,-4],[2,-5],[-1,-3],[-6,-2],[-4,-1],[-5,1],[-3,1],[-4,3],[-6,-1],[-2,-7],[-1,-1],[-6,0],[-3,0],[-8,-4],[-2,-1],[-2,0],[-2,-1],[-2,-2],[-4,0],[-5,2],[-4,1],[-3,-1],[-3,1],[-4,3],[-3,1],[-3,0],[-1,0],[-6,6],[-1,2],[-4,7],[0,2],[-1,3],[1,2],[1,4],[1,7],[2,3],[1,2],[3,3],[12,5],[3,2],[0,1],[-3,7],[0,1],[1,1],[2,4],[1,1],[2,0],[4,-1],[4,-1],[5,0],[8,-3],[12,-5],[6,-3],[5,-5],[4,-5],[0,-3],[-1,-3],[-1,-1],[0,-2],[1,-1],[3,-2],[1,0],[-1,3],[1,2],[1,2],[0,2],[-1,3],[-1,2],[-2,2],[-7,8],[-1,2],[3,1],[11,-2],[4,0],[1,3],[2,2],[2,1],[4,0],[5,-1],[2,0],[2,0],[3,2],[5,5],[2,1],[4,0],[4,1],[5,-2],[4,0],[-1,3],[-2,6],[-3,7],[-2,2],[-6,4],[-7,8],[-3,5],[-1,2],[1,2],[1,2],[12,9],[10,8],[4,5],[2,3],[2,2],[2,2],[5,1],[1,2],[1,4],[0,3],[5,9],[3,2],[5,2],[4,2],[4,7],[-1,1],[-2,2],[-1,2],[-6,18],[-4,9],[-5,7],[-5,10],[-7,9],[0,2],[1,3],[-1,1],[-7,-4],[-2,-1],[-3,2],[-2,2],[-1,4],[0,2],[1,2],[1,5],[0,2],[0,2],[-1,2],[-1,1],[-2,0],[-4,1],[-1,-1],[4,-7],[-1,-2],[-5,-1],[-2,1],[-3,1],[-2,1],[-6,7],[-1,3],[0,2],[0,1],[-2,-1],[-1,0],[-3,1],[0,1],[4,4],[1,1],[-3,1],[-3,1],[0,1],[1,1],[4,2],[1,2],[-2,1],[-2,0],[-2,-2],[-5,-5],[-3,-2],[-4,2],[-2,1],[-2,-1],[-3,-3],[-6,-3],[-11,-7],[-5,-2],[-5,1],[-1,1],[0,2],[1,2],[0,2],[1,1],[-1,8],[1,2],[2,1],[3,1],[8,-1],[4,0],[3,2],[2,2],[3,3],[0,3],[-2,5],[-1,1],[-8,4],[-4,2],[-3,0],[-3,1],[-1,2],[-2,3],[0,2],[0,2],[2,2],[6,2],[-5,2],[-3,-1],[-2,-1],[-2,-4],[-2,-1],[-5,2],[-3,1],[-2,1],[-1,1],[1,1],[2,1],[4,3],[1,2],[-3,3],[-2,0],[-6,1],[-7,-1],[-3,1],[-1,3],[-1,4],[0,4],[-1,8],[-2,3],[-2,1],[-8,-2],[-2,0],[-2,1],[-6,5],[-2,2],[-1,0],[-4,5],[-2,1],[-2,3],[-2,4],[-3,1],[-2,-1],[-3,-3],[-2,-3],[-2,-2],[0,-2],[2,-2],[9,-3],[2,-1],[2,-3],[2,-4],[1,-4],[-1,-4],[-1,-2],[-2,-2],[-5,-3],[-6,-1],[-6,-1],[-3,1],[-15,5],[-3,1],[-3,0],[-8,3],[-4,0],[-8,2],[-13,1],[-2,-1],[3,-3],[3,-1],[3,0],[3,-2],[5,-5],[3,-3],[2,-3],[0,-1],[-2,-3],[-18,12],[-11,-4],[-5,-1],[-4,-1],[-6,2],[-12,6],[-4,2],[-2,0],[-11,-2],[-9,0],[-18,2],[-7,2],[-2,1],[-2,1],[-4,0],[-10,2],[-10,-4],[-12,4],[-3,2],[-1,2],[-4,6],[0,4],[1,3],[1,2],[1,1],[-6,-3],[-3,-1],[-3,0],[-8,1],[-2,0],[1,-2],[2,-1],[0,-2],[-5,0],[-7,0],[-3,0],[-2,0],[-3,-3],[-1,-1],[-2,0],[-8,7],[-6,4],[-7,2],[-3,1],[-2,2],[-10,13],[-2,3],[-3,11],[-1,2],[-1,2],[2,0],[10,-1],[9,0],[5,-1],[6,-3],[7,-2],[6,0],[8,1],[10,2],[1,1],[-6,2],[-6,3],[-5,5],[-3,1],[-5,1],[-15,1],[-14,3],[-9,4],[-8,4],[-3,2],[-1,2],[-1,5],[-1,9],[-2,6],[-1,3],[0,3],[3,6],[7,6],[0,1],[-1,0],[-3,2],[-1,2],[-1,4],[0,3],[1,3],[1,3],[3,6],[5,7],[5,6],[0,2],[1,6],[1,4],[0,3],[1,3],[3,4],[4,4],[6,3],[1,2],[0,2],[0,1],[1,1],[15,11],[6,4],[6,3],[7,2],[20,5],[10,1],[12,-1],[24,-2],[2,-2],[1,-1],[1,-2],[-1,-1],[-6,-6],[-8,-4],[-5,-4],[-9,-9],[-3,-3],[-11,-17],[-2,-3],[-2,-2],[-1,-6],[1,-2],[1,-4],[6,-8],[2,-4],[0,-3],[-1,-8],[0,-4],[0,-4],[2,-6],[2,-7],[5,-7],[8,-8],[6,-5],[6,-3],[6,-6],[2,-2],[-3,-3],[-8,-5],[-9,-2],[-6,-1],[-6,-4],[-8,-3],[-4,-2]],[[2222,9443],[23,-12],[4,1],[7,0],[7,2],[10,2],[7,2],[2,1],[5,1],[2,0],[7,-2],[3,-1],[2,-1],[1,-2],[3,-5],[0,-2],[-2,-3],[-2,-1],[-4,-2],[-3,0],[-2,-2],[-3,0],[-1,-2],[0,-1],[1,0],[2,0],[1,1],[4,-1],[1,-1],[2,-2],[-1,-2],[-6,-3],[-9,-3],[-10,-10],[-6,-4],[-1,-1],[-1,-2],[1,-2],[0,-1],[1,0],[6,3],[3,2],[3,1],[6,0],[3,-1],[4,-2],[4,-3],[1,-1],[0,-1],[-2,-2],[4,-2],[4,-4],[0,-3],[-2,-2],[0,-2],[1,-1],[2,1],[5,2],[5,2],[3,0],[1,-1],[2,-4],[1,-4],[0,-4],[-1,-3],[-1,-2],[-4,-3],[-3,-2],[-1,0],[4,-2],[1,-2],[1,-2],[-1,-2],[0,-2],[-4,-5],[0,-1],[1,-1],[3,-3],[0,-8],[-9,-2],[-2,-2],[-3,-3],[-3,-2],[-6,-2],[-4,0],[-16,1],[-2,2],[-1,2],[-1,2],[0,3],[0,1],[0,1],[-2,-1],[-2,-3],[1,-3],[5,-10],[1,-3],[0,-2],[0,-1],[-6,-6],[-3,-1],[-4,-1],[-3,0],[-3,3],[-3,1],[-5,-1],[-1,2],[-2,2],[-3,7],[-5,6],[-5,6],[-10,9],[-6,5],[-8,9],[-3,2],[-2,0],[-5,1],[-1,1],[-2,3],[-4,2],[-1,0],[-2,0],[-5,-2],[-6,2],[-1,2],[-1,2],[-1,1],[-2,2],[-2,3],[-12,6],[-7,7],[-1,3],[0,1],[0,3],[2,4],[2,4],[1,2],[5,3],[4,1],[5,0],[3,-1],[2,-2],[1,-3],[1,-2],[4,-2],[2,-1],[3,-4],[2,-4],[3,-2],[5,0],[5,1],[12,2],[0,1],[1,1],[1,10],[1,0],[4,-4],[1,-1],[1,1],[1,2],[0,1],[-2,6],[-2,2],[-1,1],[-1,1],[-3,-1],[-3,1],[0,2],[0,2],[1,2],[2,1],[3,1],[3,-1],[4,-2],[3,-1],[4,1],[-5,1],[-7,6],[-3,1],[-4,-2],[-2,-1],[-5,-1],[-4,-1],[-15,9],[-1,1],[-1,2],[0,2],[1,1],[4,2],[6,2],[4,0],[3,-2],[5,-4],[5,-3],[0,1],[-1,3],[-2,4],[-1,1],[-4,1],[-3,2],[-1,2],[-1,2],[0,3],[0,1],[2,1],[12,2],[8,-2],[5,-1],[2,3],[0,1],[-3,-1],[-3,0],[-2,2],[0,1],[2,2],[4,1]],[[2270,9439],[-8,-2],[-4,1],[-2,-2],[-1,0],[-4,-1],[-9,3],[-3,1],[-1,1],[1,1],[1,1],[7,1],[3,1],[1,1],[1,1],[3,1],[6,1],[15,4],[7,1],[3,-1],[1,-1],[0,-1],[0,-1],[-3,-3],[-3,-2],[-8,-4],[-3,-1]],[[2412,9455],[11,-2],[5,-2],[3,-1],[4,-4],[3,-2],[10,3],[6,1],[16,-1],[12,-4],[5,-2],[3,-2],[-1,-3],[-2,-4],[-3,-4],[-5,-6],[-5,-3],[-1,-2],[-1,-2],[-2,-3],[-5,-6],[-1,-1],[-7,-3],[2,-1],[1,-1],[-1,-3],[-4,-7],[-5,-6],[-3,-4],[-6,-6],[-3,-1],[-5,-1],[-26,5],[-7,0],[-17,-3],[1,-1],[7,-2],[4,-2],[6,-6],[0,-2],[1,-1],[-1,-4],[0,-1],[-9,-10],[-3,-7],[-1,-5],[-3,-2],[-10,2],[-3,0],[-11,-1],[-5,0],[0,9],[0,10],[-2,9],[-8,16],[-1,3],[-1,3],[0,3],[0,3],[0,7],[1,4],[-1,8],[-1,14],[0,4],[0,2],[0,2],[2,1],[3,2],[2,0],[11,-4],[5,-1],[3,0],[-2,1],[-3,2],[-5,5],[-2,4],[0,2],[0,1],[0,2],[1,1],[2,2],[2,1],[6,3],[7,2],[15,1],[5,-1],[6,3],[4,0],[7,-1]],[[1674,9453],[0,-1],[7,6],[5,0],[3,-1],[1,0],[0,-1],[0,-3],[1,-5],[0,-1],[1,0],[2,2],[7,8],[4,2],[2,1],[10,1],[6,0],[7,0],[6,-2],[8,-3],[7,-4],[7,-4],[21,-16],[9,-5],[3,-3],[2,-2],[1,-2],[0,-3],[0,-2],[-1,-1],[-2,-2],[-13,-5],[-7,-2],[-7,-2],[-16,-8],[-11,-4],[-14,-8],[-28,-13],[-3,-2],[-1,-2],[-8,-14],[-3,-4],[-7,-3],[-9,-1],[-2,-1],[-1,-5],[-3,-8],[-2,-6],[-2,-14],[0,-2],[-2,-3],[-3,-3],[-8,-3],[-7,-2],[-8,-1],[-2,1],[-3,2],[-2,0],[-1,0],[-11,-10],[-11,-5],[-5,-3],[-3,-2],[-3,-1],[-4,1],[-4,1],[-3,3],[-2,3],[-5,12],[-3,4],[-2,2],[-5,7],[-2,1],[-21,9],[-10,5],[-2,2],[-3,1],[-13,0],[-1,0],[-1,1],[2,2],[0,2],[1,2],[-1,2],[0,1],[5,2],[0,1],[-1,1],[0,2],[0,1],[2,0],[1,3],[2,4],[2,2],[2,2],[4,4],[3,2],[2,2],[0,1],[-1,0],[0,2],[0,5],[0,3],[1,2],[0,1],[2,2],[9,3],[1,1],[0,1],[0,2],[-1,1],[-1,1],[-3,0],[-2,2],[-1,1],[1,3],[4,4],[2,2],[5,11],[8,6],[3,7],[6,7],[0,1],[-2,2],[-6,2],[-3,2],[-2,3],[-9,17],[-1,2],[-1,2],[-1,1],[0,1],[34,5],[24,2],[24,4],[7,0],[5,0],[5,-3],[7,-4],[9,-4],[17,-5],[11,-2],[-5,-4],[0,-1],[0,-1]],[[2295,9476],[-8,-3],[-2,1],[-1,1],[7,6],[3,1],[2,-1],[1,-2],[0,-1],[-2,-2]],[[2352,9475],[-1,0],[-2,0],[-10,3],[-1,1],[-1,1],[2,1],[1,1],[3,1],[4,0],[4,-3],[2,-3],[0,-1],[-1,-1]],[[2108,9506],[-6,-1],[-9,2],[-5,4],[-2,1],[0,1],[1,1],[2,2],[3,6],[1,2],[5,3],[3,1],[8,0],[4,-2],[2,-1],[1,-1],[2,-4],[0,-2],[2,-2],[1,-2],[0,-1],[-1,-1],[-1,-2],[-3,-2],[-8,-2]],[[2401,9505],[2,-4],[0,-2],[1,-4],[-1,-4],[-1,-1],[0,-1],[-1,-1],[0,-2],[0,-1],[-2,-1],[-10,-1],[-6,0],[-9,0],[-5,0],[-3,1],[-4,2],[-9,6],[-5,0],[-11,2],[-7,6],[-2,1],[-2,-2],[-1,0],[-1,2],[0,2],[-2,1],[-4,-1],[-1,1],[-1,2],[1,1],[0,2],[5,7],[3,0],[3,2],[2,3],[0,3],[4,5],[3,2],[5,3],[18,5],[4,1],[7,0],[6,-2],[5,-3],[9,-7],[5,-4],[2,-5],[2,-2],[3,-5],[-1,-3],[-1,-2],[0,-2]],[[2331,9533],[-2,-2],[-2,0],[-3,2],[-4,-1],[-4,-3],[-2,-3],[-1,0],[-4,-1],[-1,1],[-2,1],[-1,4],[1,2],[3,2],[10,2],[2,2],[1,1],[0,1],[1,0],[6,-2],[3,-2],[2,-1],[0,-1],[-3,-2]],[[1637,9547],[-3,-1],[-2,1],[1,1],[5,4],[0,2],[0,1],[0,1],[1,1],[2,1],[1,-1],[0,-1],[0,-4],[-1,-1],[-1,-2],[-1,-1],[-2,-1]],[[2374,9547],[-3,0],[-3,1],[-1,1],[-1,2],[0,2],[-1,2],[-1,1],[0,1],[0,1],[1,1],[3,0],[6,2],[1,0],[1,-1],[0,-3],[1,-2],[2,-4],[1,-2],[0,-1],[-6,-1]],[[1713,9537],[-8,-4],[-6,1],[-7,2],[-6,1],[-2,1],[-1,1],[2,3],[3,2],[6,4],[11,8],[7,3],[6,2],[7,5],[4,2],[3,0],[4,-1],[0,-1],[-4,-7],[-2,-2],[-5,-7],[-9,-11],[-3,-2]],[[2804,9557],[0,-3],[-2,0],[-7,-2],[-5,-1],[-2,1],[-2,3],[4,4],[5,3],[5,5],[5,3],[2,-1],[3,-2],[-3,-4],[-3,-3],[0,-3]],[[2160,9562],[6,-3],[0,-1],[-1,-1],[-7,-2],[-3,-1],[-3,-4],[-2,-1],[-10,-1],[-10,0],[2,3],[6,6],[-5,2],[-16,-4],[-6,2],[5,6],[-5,1],[-7,0],[-4,4],[1,4],[10,2],[12,2],[13,3],[10,0],[4,-1],[2,-5],[1,-6],[2,-1],[5,-4]],[[2110,9595],[2,0],[4,1],[3,0],[3,-2],[0,-2],[11,-3],[4,-2],[1,-1],[-2,-1],[-3,-2],[-3,-2],[-4,-1],[-23,0],[-2,1],[-1,1],[-3,7],[-2,3],[-1,3],[1,1],[2,2],[8,2],[4,0],[2,-1],[1,-1],[0,-1],[-2,-2]],[[2286,9588],[0,-2],[0,-2],[-1,-2],[0,-1],[1,-2],[3,-5],[2,-2],[0,-3],[0,-1],[-3,-4],[-1,-4],[0,-2],[2,-4],[0,-1],[-3,-3],[-5,-3],[0,-1],[12,-3],[1,-1],[0,-7],[2,-7],[-1,0],[-3,2],[-5,3],[-6,-5],[1,-9],[4,-4],[1,-3],[0,-1],[-4,-1],[-1,1],[-4,2],[-2,2],[-1,-1],[0,-2],[3,-2],[1,-3],[-1,-1],[-4,0],[-5,0],[-7,-2],[-4,0],[-4,1],[-4,0],[-5,0],[-2,0],[-2,2],[-3,-1],[-6,-3],[-9,1],[-8,0],[-1,1],[-2,3],[-3,7],[0,1],[9,1],[0,1],[-6,2],[-7,2],[-3,2],[0,2],[0,1],[12,3],[9,6],[5,3],[1,1],[4,1],[11,1],[0,2],[-20,-1],[-27,-4],[-9,-1],[-7,1],[-30,-6],[-1,0],[-3,2],[-3,3],[2,2],[9,5],[4,3],[0,2],[3,4],[6,1],[10,-3],[5,-3],[4,-2],[4,1],[4,2],[-1,0],[-7,-1],[-1,0],[-3,3],[-2,2],[-1,3],[0,1],[2,3],[-8,1],[-3,2],[-1,2],[0,1],[3,3],[7,4],[-1,1],[-10,0],[-2,0],[-4,3],[1,2],[3,4],[3,3],[2,0],[3,0],[8,-1],[2,-1],[5,-4],[2,-2],[0,-2],[1,-2],[4,-2],[19,-11],[3,-3],[2,-1],[5,-1],[2,0],[2,1],[1,1],[-8,4],[-2,2],[-2,3],[1,1],[2,0],[6,0],[7,1],[-8,1],[-5,2],[-5,0],[-6,2],[-1,1],[2,1],[9,1],[1,1],[1,0],[-3,2],[-3,1],[-13,2],[-5,2],[-1,2],[-1,1],[2,2],[7,4],[5,2],[9,1],[7,0],[4,-1],[10,-6],[4,-4],[8,1],[-2,4],[-2,5],[2,1],[7,3],[5,-1],[7,-4],[1,-2],[7,-2],[5,-1],[2,-1],[1,-2]],[[2188,9595],[-7,-1],[-4,1],[0,1],[3,1],[10,3],[5,4],[2,0],[8,1],[4,-1],[6,0],[-14,-5],[-13,-4]],[[1992,9565],[3,-1],[4,1],[5,0],[2,-2],[1,-2],[1,-1],[-1,-1],[0,-1],[-6,-6],[-2,-2],[2,0],[1,0],[6,4],[5,2],[3,0],[6,-1],[2,-1],[1,-1],[1,-1],[2,-4],[2,-5],[0,3],[1,3],[5,1],[0,1],[-2,1],[-1,2],[-2,3],[1,1],[1,2],[4,3],[4,1],[3,1],[14,-3],[5,-3],[3,-1],[0,-1],[1,-3],[3,-7],[0,-3],[-1,-4],[-5,-7],[0,-6],[-5,-12],[-3,-4],[-3,-2],[-14,-4],[-10,-5],[-3,0],[-3,-1],[-8,2],[-10,3],[-6,-1],[-5,-2],[-4,-1],[-3,1],[-4,0],[-4,2],[2,1],[1,1],[-1,1],[-4,1],[-5,-3],[-14,-7],[-19,-3],[-5,-1],[-5,-2],[-2,-2],[-4,-3],[-5,-3],[-10,-3],[-12,-5],[-22,-5],[-14,-1],[-13,2],[-5,1],[-4,2],[-10,5],[-2,2],[-3,4],[1,2],[5,3],[8,3],[15,3],[13,6],[5,1],[13,1],[7,0],[5,0],[3,1],[5,2],[6,4],[5,4],[2,2],[-2,1],[-3,1],[-8,-4],[-4,-2],[-4,0],[-6,-1],[-6,-1],[-1,0],[-7,4],[-3,1],[-1,-1],[-2,-1],[-3,-2],[-1,-1],[-3,-1],[-11,-1],[-10,-1],[-2,1],[-2,1],[0,1],[0,3],[-1,2],[1,3],[1,2],[2,1],[7,5],[1,1],[-3,-1],[-8,-2],[-2,1],[-1,2],[-1,1],[-1,-1],[-1,-2],[-1,-6],[-2,-3],[-3,1],[-4,2],[-1,0],[-1,0],[0,-1],[4,-5],[0,-2],[-2,-3],[-12,-5],[-4,-2],[-2,1],[-1,1],[-1,2],[-3,4],[-2,0],[-2,0],[-2,0],[-2,-2],[-1,-1],[-1,-3],[-2,-2],[-1,0],[-11,4],[-10,8],[-10,-2],[-4,1],[-14,2],[-2,2],[-1,2],[0,2],[1,1],[2,2],[3,4],[2,1],[2,1],[3,1],[7,0],[19,0],[3,1],[21,7],[2,1],[3,3],[1,1],[-25,-5],[-11,-2],[-17,1],[-3,1],[-1,2],[4,4],[2,2],[4,1],[12,2],[15,2],[10,0],[9,2],[5,1],[-17,0],[-21,-1],[-3,1],[-6,2],[0,2],[2,2],[1,1],[-1,4],[0,1],[4,3],[7,2],[4,1],[8,-1],[23,-1],[5,0],[-3,2],[-4,0],[-18,2],[-4,1],[0,1],[-1,1],[0,2],[2,2],[5,4],[16,4],[7,0],[6,0],[7,-1],[3,-2],[1,-1],[1,-2],[0,-3],[0,-1],[2,-1],[3,-5],[3,-1],[13,3],[5,0],[6,-1],[7,-2],[10,-8],[13,-7],[0,-2],[-5,-2],[-1,-2],[1,0],[5,-1],[5,1],[4,-1],[1,-1],[2,-2],[2,-5],[3,-4],[3,-2],[3,-2],[5,0],[4,1],[7,0],[39,-3],[2,0],[1,2],[1,2],[1,3],[-1,3],[0,1],[-24,9],[-2,4],[11,6],[1,1],[0,1],[0,3],[-1,2],[-7,4],[-5,0],[-8,4],[-2,1],[-1,1],[0,3],[0,1],[1,1],[8,4],[3,2],[10,10],[5,4],[3,2],[3,1],[8,1],[7,-4],[2,0],[1,-1],[0,-2],[-1,-2],[-3,-2],[-1,-2],[0,-1],[2,-3],[1,-2],[0,-3],[1,0],[4,-3],[4,-4],[2,-5],[-1,-2],[-4,-3],[-2,-2],[0,-2],[0,-1],[3,0]],[[2507,9591],[-1,-1],[-4,0],[-2,-1],[-2,1],[-3,1],[-3,4],[-4,4],[-4,5],[0,1],[1,2],[3,1],[8,1],[5,0],[5,-3],[1,-1],[1,-1],[0,-1],[0,-1],[-2,-3],[-1,-1],[0,-2],[0,-2],[1,-2],[1,-1]],[[1845,9604],[-4,-2],[-29,3],[-1,1],[-1,1],[5,3],[6,2],[15,1],[5,-1],[4,-2],[2,-1],[0,-3],[-2,-2]],[[2380,9614],[6,-1],[4,1],[4,0],[6,-2],[5,-4],[4,-2],[1,0],[1,-1],[0,-3],[0,-1],[0,-1],[-2,-3],[-1,-3],[-3,-2],[-2,-2],[-1,-3],[3,2],[12,8],[7,-1],[12,1],[14,3],[7,1],[7,-1],[5,-1],[10,-4],[4,-2],[1,-2],[1,-1],[-3,-2],[-6,1],[-11,1],[-2,1],[-2,0],[-1,-1],[0,-2],[3,-1],[13,-1],[44,-7],[1,-3],[0,-1],[-2,-1],[-3,-2],[-25,-2],[-14,2],[-12,3],[-4,-1],[3,-4],[7,-1],[6,-2],[3,-1],[13,-2],[2,-1],[4,-3],[3,-1],[3,-2],[3,-4],[1,-1],[4,1],[7,-4],[2,-1],[0,-2],[-2,-2],[-3,-3],[-7,-4],[0,-1],[8,1],[2,-1],[10,-6],[1,0],[1,0],[1,3],[0,2],[-2,3],[1,2],[2,1],[1,1],[2,0],[2,-1],[11,-8],[13,4],[2,-2],[2,-3],[1,0],[5,6],[3,1],[12,-7],[8,-2],[3,-1],[5,-2],[8,-1],[2,3],[-5,4],[3,1],[10,3],[6,0],[11,4],[7,0],[4,0],[13,7],[3,1],[2,2],[5,-1],[15,-3],[4,0],[15,4],[5,1],[6,0],[14,-3],[10,-2],[4,-1],[-2,-3],[1,-1],[1,0],[4,-1],[13,0],[6,-1],[4,-3],[1,-1],[0,-1],[-4,-3],[0,-1],[5,0],[10,-1],[2,0],[2,-4],[2,-5],[0,-2],[-3,-4],[-10,-4],[-10,-4],[-1,-1],[3,-2],[4,-1],[2,0],[9,2],[2,0],[4,-2],[1,-2],[2,-2],[-3,-2],[-12,-3],[-7,4],[-3,0],[-1,0],[1,-1],[3,-3],[1,-2],[-1,-1],[0,-2],[0,-2],[-1,-3],[-1,-4],[-27,-1],[-3,-1],[-7,-3],[-6,-1],[-3,-1],[-4,1],[-10,3],[-6,-1],[-2,1],[-6,2],[-1,1],[-2,2],[-2,4],[0,2],[1,3],[-1,2],[-1,0],[-2,1],[-5,3],[-3,1],[-1,-1],[1,-2],[1,-1],[3,-2],[1,-2],[-2,-5],[0,-1],[-4,-4],[-2,-1],[-7,0],[-10,-3],[-5,-1],[-7,1],[-4,1],[-3,2],[-3,2],[-1,0],[-1,-5],[-1,0],[-2,0],[-4,1],[-3,4],[-1,0],[0,-2],[-1,-2],[-8,-2],[-4,0],[-4,2],[-3,0],[-4,-1],[-8,2],[-2,0],[1,-4],[-3,0],[-6,0],[-10,1],[-6,-2],[-12,1],[-11,1],[-3,0],[-1,2],[0,2],[0,2],[2,3],[3,5],[1,2],[-3,1],[-1,2],[-2,0],[-4,-2],[-2,-5],[-2,-1],[-1,1],[-1,3],[-1,2],[-1,-1],[-1,0],[-1,-2],[-2,0],[-2,0],[-1,-1],[1,-2],[0,-2],[0,-1],[-2,-2],[-5,-2],[-3,-1],[-8,0],[-5,0],[-9,3],[-6,0],[-6,5],[-5,1],[0,2],[2,3],[0,1],[-7,-5],[-1,-1],[1,-3],[-1,-1],[-4,2],[-5,-1],[-1,0],[-4,2],[-5,3],[-3,3],[-4,9],[-2,6],[1,1],[3,1],[-1,2],[-4,3],[-3,3],[-2,2],[0,2],[-1,3],[0,2],[1,1],[2,4],[6,8],[1,1],[0,2],[-1,4],[-1,4],[-1,2],[-3,4],[-5,5],[-6,7],[-5,6],[-6,8],[-3,0],[-3,0],[-7,-3],[-2,-1],[-1,-1],[-5,0],[-15,1],[-6,0],[-4,0],[-7,-2],[-8,1],[-5,5],[-10,3],[-4,2],[-2,2],[1,2],[6,1],[3,2],[1,1],[-6,-1],[-3,0],[-19,8],[-5,1],[-1,1],[-1,1],[0,1],[1,2],[5,-3],[3,0],[4,1],[1,1],[-1,1],[-6,3],[-3,1],[-1,2],[1,2],[0,1],[2,1],[4,0],[5,1],[8,3],[6,1],[6,0],[14,-3],[15,-4],[8,-2]],[[1790,9640],[2,-2],[0,-1],[-1,-1],[-3,-2],[-16,-5],[-4,-2],[2,-2],[6,-4],[6,-4],[1,-2],[-3,-1],[-5,0],[-2,0],[-2,-1],[0,-1],[6,-6],[2,-2],[0,-2],[-1,-1],[-3,-2],[-4,-3],[-6,-1],[-15,-3],[-1,-2],[0,-2],[0,-3],[0,-2],[-2,-3],[-1,-2],[-3,-1],[-3,0],[-4,0],[-7,3],[-3,1],[-4,4],[-1,2],[1,3],[1,4],[2,5],[2,5],[1,2],[-1,2],[-2,0],[-5,-2],[-4,-1],[-2,-1],[-2,-2],[-1,-3],[-1,-4],[-1,-2],[-3,-1],[-4,0],[-2,-1],[-1,-2],[1,-1],[4,-3],[1,-3],[-1,-1],[-4,-4],[-2,-1],[-2,-5],[-2,-1],[-2,-2],[-2,1],[-3,1],[-3,4],[-2,3],[-1,3],[-1,1],[-2,-1],[-2,-3],[0,-2],[1,-3],[0,-2],[-3,-2],[0,-1],[5,-3],[1,-1],[0,-2],[-1,-1],[-2,0],[-1,-2],[-2,-2],[-5,-3],[-7,0],[-6,-2],[-1,0],[-1,3],[-2,5],[-1,3],[-2,1],[-3,6],[-1,2],[-1,1],[-1,0],[-1,-1],[-4,-9],[-5,-2],[-3,0],[-3,0],[-8,2],[-5,1],[-5,-1],[-6,-3],[-3,-1],[-4,0],[-1,2],[-2,2],[0,1],[1,1],[2,2],[0,1],[-2,1],[0,1],[1,1],[-1,1],[-2,0],[-6,-2],[1,2],[2,3],[8,8],[2,2],[2,0],[21,3],[1,0],[10,10],[3,2],[3,2],[14,6],[1,1],[3,4],[1,1],[3,2],[10,8],[10,6],[4,4],[7,3],[7,2],[23,3],[16,-4],[4,0],[2,1],[2,2],[2,-1],[6,-1],[2,1],[2,2],[-2,1],[-7,2],[0,1],[0,1],[2,2],[3,1],[9,1],[5,0],[4,-1],[5,-4],[13,-5]],[[2504,9634],[-7,-3],[-4,0],[-21,7],[-4,3],[-1,2],[0,4],[0,4],[1,3],[1,1],[2,1],[5,1],[5,-1],[7,-1],[7,-2],[9,-6],[4,-3],[0,-3],[0,-3],[0,-1],[-1,-1],[-3,-2]],[[2095,9627],[-4,-1],[-8,2],[-6,1],[-4,5],[-5,5],[-4,6],[-2,4],[-2,2],[-1,4],[-5,6],[5,1],[8,-1],[3,-2],[5,-3],[6,-6],[2,-2],[0,-3],[1,-2],[6,0],[6,-5],[1,-1],[1,-4],[0,-1],[-1,-4],[-2,-1]],[[2347,9664],[7,-2],[8,1],[8,1],[18,-1],[12,0],[3,0],[5,-2],[3,-1],[2,-3],[-6,-2],[-5,-9],[-1,0],[-5,0],[-3,-1],[-16,1],[-44,1],[-1,1],[-6,5],[-1,2],[1,3],[2,1],[1,1],[13,4],[5,0]],[[2175,9659],[-4,-1],[-7,1],[-8,2],[-2,2],[-1,4],[0,2],[1,1],[5,0],[10,1],[7,-1],[9,-2],[4,-1],[2,-1],[2,-2],[1,-1],[0,-2],[-11,0],[-5,-1],[-3,-1]],[[1838,9662],[-8,-2],[-5,0],[-9,3],[-10,9],[-1,3],[3,0],[3,1],[2,1],[3,2],[8,2],[1,-1],[0,-2],[0,-1],[3,-1],[3,-1],[5,-3],[4,-1],[1,-1],[1,-1],[2,-2],[0,-1],[-3,-2],[-3,-2]],[[1932,9682],[22,-1],[1,0],[0,-1],[-2,-4],[-2,-2],[-12,-3],[-16,-3],[-3,-1],[0,-1],[2,-1],[2,-1],[12,0],[3,0],[1,-1],[1,-1],[0,-2],[0,-5],[-1,-3],[-1,-3],[-5,-2],[-9,-2],[-6,-2],[-4,1],[-5,0],[-20,-5],[-6,0],[-6,1],[-7,4],[-8,2],[-3,2],[-4,1],[-1,2],[0,1],[1,1],[1,1],[1,1],[-2,3],[0,2],[-3,4],[0,2],[0,1],[0,1],[2,3],[1,0],[4,1],[6,1],[14,4],[31,5],[9,-1],[4,1],[8,0]],[[2139,9685],[-4,-1],[-3,0],[-1,1],[0,1],[0,1],[5,4],[3,1],[3,0],[2,-1],[1,-2],[-6,-4]],[[1949,9714],[5,-3],[2,0],[2,-1],[1,-1],[3,-4],[1,-2],[0,-3],[-1,-2],[-1,-2],[-2,-1],[-7,-1],[-8,1],[-8,-1],[-3,-1],[-10,1],[-2,1],[-5,3],[-4,1],[-2,-1],[-2,-2],[-4,-3],[-2,-1],[-7,1],[-10,5],[-12,-2],[-12,-3],[-5,0],[-1,1],[-2,2],[0,1],[4,3],[8,3],[6,2],[12,3],[14,2],[5,1],[3,3],[9,3],[6,2],[7,1],[6,0],[7,-3],[6,-1],[3,-2]],[[2327,9707],[7,-1],[11,0],[4,-1],[11,-4],[3,-2],[1,-2],[0,-1],[-4,-2],[-7,-2],[-1,-3],[6,-2],[3,-3],[2,-1],[0,-2],[-5,-5],[-3,-1],[-4,0],[-3,-1],[-6,-2],[-9,-2],[-13,-1],[-4,-1],[-6,-2],[-4,-1],[-2,2],[0,1],[0,2],[1,1],[-2,2],[-10,2],[-5,4],[-1,2],[0,1],[12,0],[5,1],[2,1],[1,1],[-2,1],[-9,2],[-13,2],[-1,2],[-6,3],[0,4],[-2,1],[-4,1],[0,1],[-1,2],[0,1],[0,1],[7,3],[-1,1],[-5,6],[-2,4],[0,1],[4,2],[4,0],[13,-1],[6,0],[6,-2],[6,-2],[10,-2],[3,-1],[6,-4],[0,-2],[0,-1],[1,-1]],[[2127,9752],[6,-1],[8,-4],[7,-7],[1,-1],[0,-2],[-1,-1],[-1,-2],[-1,-2],[4,-1],[0,-1],[0,-2],[0,-1],[3,1],[2,2],[0,1],[1,4],[5,1],[6,3],[3,0],[5,0],[11,-6],[4,0],[2,-1],[1,-1],[0,-2],[-2,-3],[-1,-2],[1,-1],[6,-1],[13,2],[12,-6],[6,-6],[5,-2],[1,-1],[-2,-1],[-1,-3],[-4,-2],[-1,-1],[2,-3],[0,-2],[0,-2],[1,-1],[5,-1],[12,-10],[2,-2],[2,-4],[0,-1],[-2,-2],[-2,-5],[-1,-1],[-5,-1],[-9,-1],[-8,-1],[-9,2],[-8,3],[-3,2],[-2,3],[-1,1],[0,5],[-1,1],[-4,2],[-3,4],[-6,0],[-15,4],[-6,1],[-6,-1],[-9,-1],[-2,0],[-2,1],[-1,2],[0,1],[1,3],[-26,-3],[-8,-4],[-10,1],[-5,1],[-7,4],[-4,3],[-2,3],[-1,3],[3,2],[2,1],[3,1],[14,-2],[12,-2],[6,2],[2,3],[-3,1],[-12,1],[3,2],[10,1],[5,3],[-1,1],[-3,1],[-13,-1],[-5,1],[0,1],[1,1],[7,5],[0,1],[-3,2],[-3,2],[-1,0],[-7,-1],[-10,-8],[-2,-1],[-2,0],[-2,1],[0,2],[2,2],[4,6],[0,2],[-4,1],[-11,-1],[-7,0],[-1,2],[0,3],[0,3],[2,4],[2,3],[1,2],[15,-1],[25,2],[7,0],[8,-2]],[[2256,9791],[0,-8],[0,-4],[-2,-2],[-1,-1],[-2,0],[-7,2],[-3,1],[0,1],[0,2],[-6,3],[-9,0],[-4,0],[-2,1],[-1,1],[0,5],[0,1],[1,3],[1,1],[6,3],[2,0],[9,-1],[8,0],[3,-1],[4,-2],[2,-2],[1,-3]],[[2447,9857],[4,-5],[13,-11],[6,-5],[11,-5],[1,-2],[0,-3],[3,-1],[9,-2],[10,-3],[1,1],[4,1],[4,1],[5,-1],[3,-1],[2,-2],[1,-1],[0,-1],[-2,-2],[0,-1],[1,-1],[0,-1],[-2,-4],[1,-1],[5,-4],[4,-2],[9,-2],[6,0],[4,-1],[0,1],[-2,2],[-3,4],[-7,1],[-1,2],[0,4],[0,2],[4,2],[3,0],[8,0],[4,0],[8,-3],[1,-1],[1,-3],[0,-5],[0,-2],[-7,-3],[-2,-2],[2,0],[6,-1],[9,-2],[3,0],[4,-4],[3,-4],[-2,-6],[-3,-8],[-2,-2],[-2,-3],[1,0],[9,1],[2,1],[6,2],[8,0],[3,-1],[2,-1],[2,-3],[3,-4],[1,0],[4,5],[2,1],[2,2],[1,-1],[4,-4],[9,-9],[3,-3],[0,-3],[-3,-2],[-3,-2],[-23,-6],[-10,-4],[-5,-2],[-2,-1],[-6,0],[-1,0],[-1,-5],[-2,-2],[-5,-3],[-6,-5],[-4,-3],[-7,2],[-2,3],[0,6],[-1,2],[1,1],[0,2],[3,5],[0,1],[-1,-1],[-5,-2],[-2,-1],[-1,-3],[-1,-4],[1,-7],[-1,-2],[-2,-2],[1,-1],[5,-1],[1,-1],[1,-1],[0,-2],[0,-2],[-2,-2],[-3,-1],[-4,1],[-8,6],[-3,0],[-1,-1],[0,-2],[3,-5],[0,-4],[-1,-3],[-2,-6],[-2,-2],[-1,-1],[-4,0],[-3,2],[-11,9],[-5,4],[-7,7],[-2,2],[-1,0],[-1,-3],[2,-3],[6,-7],[5,-5],[2,-5],[1,-2],[-1,0],[-2,0],[-2,2],[-6,2],[-2,2],[-2,1],[-3,2],[-5,0],[-4,1],[-5,-1],[0,-1],[5,-2],[1,-1],[2,-2],[1,-2],[-2,-1],[-6,-1],[-9,1],[-13,1],[-14,3],[-13,4],[-9,5],[-3,2],[-1,2],[3,2],[12,1],[12,2],[-2,1],[-22,2],[-7,1],[-4,-1],[-4,1],[-3,1],[-5,4],[-2,3],[0,1],[2,0],[10,0],[1,0],[-5,2],[-16,4],[-6,3],[-1,1],[0,2],[0,1],[6,2],[18,6],[7,1],[6,0],[4,2],[4,5],[19,2],[14,3],[2,1],[-11,-1],[-16,1],[-6,3],[-5,1],[-5,0],[-5,-1],[-10,-4],[-5,-1],[-10,-3],[-3,0],[-2,1],[2,3],[2,1],[0,1],[-4,0],[-5,0],[-4,0],[-12,-4],[-5,-2],[-2,0],[-6,4],[-9,2],[-2,1],[1,6],[3,2],[7,1],[22,6],[1,1],[2,2],[-4,0],[-11,-3],[-9,-1],[-7,0],[-6,0],[-3,1],[-4,2],[-13,8],[-3,4],[-1,3],[-1,3],[-3,6],[27,-4],[11,0],[21,-1],[1,1],[0,1],[0,2],[0,1],[0,1],[8,2],[1,1],[-9,0],[-16,-4],[-6,0],[-7,6],[-7,-1],[-4,0],[-5,2],[-2,1],[-2,2],[-1,1],[0,1],[2,1],[6,2],[3,0],[7,-1],[6,0],[-2,1],[-8,5],[-7,5],[0,7],[6,2],[6,0],[6,-2],[8,0],[5,-2],[4,-4],[4,0],[7,-1],[16,0],[-3,1],[-5,2],[-11,2],[-5,6],[-12,3],[-8,2],[0,1],[6,8],[8,3],[13,-1],[9,2],[10,2],[11,-1],[3,0],[1,1],[2,2],[0,1],[-2,2],[-3,1],[-13,1],[-6,0],[-3,1],[0,2],[-1,1],[0,1],[1,1],[1,1],[3,0],[13,0],[7,1],[8,-1],[18,-4],[5,-2],[6,-3],[3,-3]],[[3069,9965],[23,-1],[7,1],[9,-3],[5,0],[8,0],[6,0],[23,-1],[5,-1],[0,-1],[-5,-3],[-7,-2],[-42,-8],[-3,-1],[8,-1],[12,0],[10,1],[11,3],[3,0],[7,2],[14,3],[11,2],[5,0],[4,-2],[3,0],[1,1],[3,3],[1,1],[4,1],[2,0],[3,-2],[4,-3],[4,-2],[2,0],[8,2],[4,1],[10,-1],[4,-1],[1,-2],[-3,-1],[-2,-1],[0,-1],[1,-1],[6,-2],[8,-6],[0,-1],[-4,-4],[0,-1],[21,4],[22,-2],[6,-1],[2,-2],[3,-2],[2,-3],[-1,-4],[-10,-6],[-10,-4],[-5,-4],[-9,-2],[-31,-9],[-15,-3],[-8,-3],[-4,0],[-18,0],[-5,-2],[-3,-2],[-5,-2],[-9,0],[-17,-1],[-4,-3],[-1,-2],[-2,-2],[-1,-1],[-49,-11],[-1,-2],[5,0],[6,0],[72,14],[13,1],[13,-1],[-1,-3],[-18,-9],[-23,-8],[-12,-6],[-29,-11],[-24,-10],[-9,-6],[-12,-9],[-4,-2],[-5,-1],[-6,0],[-6,2],[-7,3],[-6,4],[-3,1],[2,-2],[12,-13],[-1,-3],[-23,-3],[-11,-2],[-5,0],[-4,0],[-3,0],[-4,-1],[0,-1],[3,-1],[9,-1],[21,3],[3,0],[5,-2],[1,-1],[-6,-4],[-16,-5],[2,-1],[5,-1],[-1,-2],[-5,-4],[-2,-1],[-16,-4],[-7,0],[-6,0],[-29,8],[-9,1],[-10,2],[-7,-1],[-7,-2],[3,-1],[14,-2],[11,-1],[5,0],[2,-2],[5,-5],[0,-3],[-1,-2],[-1,-2],[-2,-1],[-3,0],[-11,0],[-4,-1],[-5,-1],[-6,-1],[-11,0],[-13,-2],[-7,0],[-7,1],[-8,2],[-9,2],[-14,1],[1,-2],[5,0],[10,-4],[5,-5],[5,-1],[10,-4],[7,-1],[7,-1],[10,2],[7,-1],[-2,-10],[-3,-1],[-16,0],[-8,2],[-3,1],[-8,2],[-7,-1],[-6,0],[-4,-1],[-7,0],[-17,-2],[-9,0],[-7,1],[-8,1],[-9,-1],[1,-1],[3,0],[6,-2],[5,-3],[4,-1],[5,0],[6,2],[19,2],[8,0],[7,-1],[5,-1],[4,-1],[4,-4],[11,-1],[9,-1],[13,-6],[4,0],[1,-2],[-3,-4],[0,-2],[-9,-4],[-15,-1],[-15,0],[-12,-1],[-1,0],[8,-1],[18,-5],[7,-3],[1,-2],[-10,-6],[-9,-12],[-3,-1],[-3,0],[-7,0],[-10,-3],[-7,-1],[-14,1],[-15,0],[-2,-2],[0,-3],[0,-6],[1,-8],[-1,-5],[-3,-4],[-3,-2],[-6,-3],[-6,-1],[-4,-1],[-8,0],[-21,-2],[-10,0],[-8,1],[-9,3],[-14,7],[-4,1],[-4,1],[1,-1],[4,-4],[3,-3],[3,-1],[-1,-1],[-6,-2],[-7,-1],[-8,0],[0,-1],[3,-2],[3,-2],[3,0],[6,0],[7,3],[4,0],[9,0],[4,-1],[11,-5],[1,-1],[9,3],[11,0],[5,-2],[1,-4],[1,-4],[-2,-2],[3,-3],[7,-2],[5,-1],[4,2],[5,3],[3,1],[2,0],[3,-3],[5,-5],[1,-5],[-4,-7],[-5,-4],[-18,-7],[-5,-2],[-5,-3],[-6,-3],[-12,-3],[-7,-1],[-14,-4],[-3,0],[-4,1],[-1,2],[1,3],[1,3],[2,3],[0,2],[-4,3],[-2,2],[-3,1],[-5,-1],[-3,-1],[-4,0],[-3,1],[-3,1],[-6,7],[-2,0],[-3,0],[-3,1],[-2,2],[-4,2],[1,-2],[4,-3],[3,-4],[1,-3],[-1,-3],[-32,-1],[-13,0],[-3,3],[-7,10],[-1,-18],[-24,-3],[-6,0],[-9,2],[-12,5],[-5,4],[-2,3],[-2,2],[-1,0],[-3,-4],[-3,-8],[-8,2],[-11,2],[-4,8],[0,-11],[-17,1],[-8,0],[-2,10],[0,11],[-4,-7],[2,-6],[0,-7],[-7,2],[-16,1],[-5,1],[0,9],[2,10],[20,9],[6,5],[4,2],[7,1],[9,1],[6,-1],[7,1],[8,1],[6,1],[1,1],[-1,0],[-7,7],[-2,1],[-2,1],[-5,0],[-4,3],[-3,2],[-3,3],[-4,6],[-4,7],[2,4],[7,3],[7,2],[8,1],[6,0],[7,-1],[10,-4],[6,-3],[7,-8],[5,-6],[4,-3],[18,-5],[6,0],[7,0],[14,1],[7,2],[3,1],[2,3],[2,1],[6,5],[10,8],[5,7],[1,2],[2,3],[0,3],[-3,-2],[-16,-16],[-4,-3],[-9,-5],[-5,-1],[-6,0],[-9,2],[-10,-3],[-7,1],[-5,2],[0,12],[-8,9],[8,5],[7,3],[11,8],[3,0],[8,-1],[-4,1],[-5,3],[-10,-1],[4,17],[-7,-13],[-7,-6],[-4,-3],[-5,-2],[-17,-2],[4,6],[4,9],[-4,-3],[-10,-5],[-7,-3],[-7,-1],[-11,0],[-6,3],[1,6],[0,8],[4,3],[6,5],[5,6],[4,6],[16,3],[15,1],[13,3],[7,1],[6,-2],[24,-2],[10,-2],[4,-2],[4,0],[3,2],[4,2],[16,0],[4,0],[4,1],[4,2],[6,3],[1,2],[-4,0],[-4,-1],[-6,-2],[-5,-1],[-6,0],[-11,2],[-20,0],[-11,1],[-4,1],[-3,1],[-2,2],[-2,2],[1,2],[4,1],[3,0],[6,-1],[6,-3],[7,0],[-2,2],[-9,4],[-6,4],[-5,4],[-4,5],[-9,7],[-7,6],[-5,3],[-5,2],[-16,2],[-3,1],[-8,6],[-2,10],[-3,6],[3,8],[5,3],[32,-3],[14,1],[17,-1],[9,-2],[11,-5],[9,-5],[9,-4],[8,-5],[10,-7],[5,-3],[5,-2],[6,-2],[12,-3],[10,0],[5,0],[6,2],[4,2],[-4,0],[-12,0],[-9,1],[-4,2],[-5,3],[-8,6],[-6,4],[-13,6],[-10,7],[-8,6],[0,2],[5,2],[7,1],[43,4],[26,5],[11,6],[1,1],[34,8],[25,3],[9,0],[9,1],[0,1],[-7,1],[-8,1],[-17,0],[-15,1],[-5,1],[1,3],[2,3],[4,4],[5,3],[21,9],[14,3],[4,3],[-30,-6],[-11,-4],[-10,-6],[-6,-2],[-4,1],[-3,-1],[-3,-2],[-3,-3],[-2,-4],[-2,-3],[-2,-2],[-4,-2],[-10,-4],[-24,-7],[-9,-1],[-7,0],[-22,-4],[-7,0],[-8,1],[4,3],[12,6],[3,2],[-8,0],[-8,-2],[-17,-1],[-7,-3],[-6,-4],[-6,-2],[-4,-1],[-5,-1],[-20,0],[-5,0],[-12,3],[-10,-1],[-4,0],[-8,3],[-2,1],[0,2],[5,4],[5,3],[17,8],[11,4],[16,3],[36,3],[2,3],[-37,-3],[-32,-4],[-5,-1],[-8,-4],[-23,-12],[-7,-4],[-11,-1],[-8,2],[-6,1],[-11,4],[-8,2],[-4,1],[-2,2],[-2,1],[-2,2],[3,2],[21,3],[28,0],[13,0],[13,2],[18,5],[20,7],[4,3],[-7,0],[-6,0],[-13,-3],[-20,-7],[-19,-2],[-44,-1],[-15,-2],[-6,0],[-4,2],[-6,3],[1,3],[11,3],[8,1],[2,1],[-12,3],[-1,1],[7,4],[15,5],[7,1],[14,1],[14,0],[0,1],[-14,1],[-10,1],[-14,-2],[-37,-8],[-3,1],[-5,1],[1,2],[20,9],[1,1],[-14,0],[-5,0],[-4,1],[-5,-1],[-8,-3],[-5,-1],[-3,1],[-8,3],[1,3],[6,3],[6,3],[8,2],[12,3],[9,1],[15,0],[7,1],[6,2],[8,4],[9,2],[14,2],[11,0],[7,-2],[5,-3],[6,-3],[0,2],[5,3],[5,1],[7,-1],[6,-1],[8,-3],[7,-1],[3,0],[3,2],[10,0],[0,1],[-3,1],[-4,1],[-35,9],[-1,1],[12,2],[7,2],[4,1],[8,4],[6,2],[10,3],[5,-1],[5,-2],[5,-2],[15,-1],[7,-1],[11,-8],[5,-3],[6,-3],[4,-1],[8,0],[1,1],[-9,4],[-3,2],[1,2],[2,1],[3,0],[7,-2],[19,-5],[29,-7],[11,-1],[7,-3],[6,-3],[6,-2],[1,0],[-5,5],[-14,6],[-37,9],[-15,5],[-7,3],[-5,4],[-1,1],[5,3],[7,1],[9,1],[1,1],[-8,2],[-4,3],[0,1],[9,1],[6,0],[10,-3],[10,-1],[1,1],[-9,7],[-1,2],[1,1],[3,1],[10,-1],[16,-3],[29,-2],[8,0],[-1,1],[-11,2],[-13,3],[-5,2],[-4,2],[-4,2],[-1,1],[8,2],[19,0],[18,-3],[16,1],[10,-1],[4,0],[7,-3],[22,-9],[2,-2],[3,-2],[3,-3],[3,-1],[8,2],[5,2],[-2,2],[-13,5],[-3,2],[-6,3],[-14,6],[-3,3],[-3,2],[39,2],[37,-2],[6,-1],[4,-2],[3,-3],[6,-3],[12,-5],[17,-3],[-3,2],[-13,5],[-5,4],[0,2],[1,2],[2,1],[14,5],[21,2],[2,-1],[16,-7],[8,-3],[5,-1],[-7,4],[-6,2],[0,1],[9,3],[6,1],[25,1],[3,0],[2,-1],[6,-4],[2,-1]],[[5264,7907],[-1,-6],[0,-4],[0,-2],[3,-1]],[[5290,7883],[-1,-7],[-1,-4],[1,-3],[1,-2],[-1,-2],[-2,0],[-2,1],[-2,3],[-2,0],[-1,-1],[-1,-3],[-1,-4],[1,-2],[1,-1],[0,-4],[1,-4],[0,-2],[0,-1],[-2,-1],[-1,1],[-2,5],[0,2],[-2,1],[-3,-2],[-4,-3],[-1,0],[-2,1],[-1,2],[-1,5],[-1,3],[-3,1],[-1,-1],[0,-5],[-1,-6],[-1,-4],[-4,-7],[-1,-3],[0,-2],[-1,-2],[1,-3],[1,-3],[-1,-2],[-2,0],[-1,1],[-1,4],[-3,4],[2,4],[-1,1],[-4,2],[-3,3],[-3,4],[0,3],[0,7],[0,1],[-1,1],[-1,0],[-2,-2],[-2,-4],[-4,-4],[0,-1],[1,-4],[0,-1],[-3,-7],[0,-2],[-4,-4],[-2,-1],[-6,3],[-1,0],[-3,-2],[-3,-2],[-5,-2],[-3,2],[0,1]],[[5195,7829],[-1,2],[-1,3],[-2,2],[-1,2],[-1,3],[-1,2],[1,6],[-1,2],[-1,4],[1,2],[-1,0],[-5,2],[-4,-1],[-3,-2],[-2,-4],[-1,0],[1,-1],[1,-3],[-2,-4],[-3,-2],[-3,0],[-1,0],[0,4],[2,1],[2,2],[0,4],[1,2],[-2,3],[0,2],[1,3],[1,3],[1,3],[3,4],[4,4],[0,4],[0,6],[1,1],[5,3],[1,1],[0,2],[4,6],[4,6],[0,2],[1,2],[-1,1],[-1,1],[-1,2],[2,3],[2,2],[3,0],[1,-1],[0,-1],[1,-1],[1,-1],[2,1],[3,1],[1,3],[1,2],[3,3]],[[5211,7925],[2,-1],[7,-1],[4,1],[3,2],[4,0],[2,-1],[1,0],[1,1],[2,1],[1,1],[-1,0],[0,1],[-3,-1],[-1,1],[0,2],[1,2],[2,2],[2,1],[1,-1],[3,-4],[1,0],[0,1],[1,0],[1,-1],[1,-2],[7,1],[2,0],[4,-5],[5,-4]],[[3123,1965],[-1,0],[-3,1],[-4,0],[0,1],[0,1],[2,1],[6,-1],[1,0],[0,-1],[-1,-2]],[[3131,1971],[-1,0],[-1,1],[-1,1],[-5,1],[0,1],[0,2],[1,1],[2,1],[2,3],[1,-1],[1,-5],[1,-3],[0,-1],[0,-1]],[[3153,2003],[-2,-3],[-2,0],[0,1],[0,1],[0,2],[1,1],[1,1],[1,0],[2,-1],[-1,-2]],[[3136,2007],[0,-2],[-2,-3],[-3,-2],[-2,-1],[-2,1],[0,2],[-1,2],[0,1],[-1,1],[-1,0],[-2,-1],[-3,-3],[-1,-1],[-1,0],[-8,2],[-1,1],[-1,2],[-1,6],[-4,5],[6,3],[6,0],[13,-2],[5,-1],[4,-5],[0,-3],[0,-2]],[[3064,2021],[22,-6],[7,3],[5,0],[2,-5],[-6,-5],[0,-1],[1,-1],[5,-1],[2,-2],[1,-2],[-1,-3],[0,-1],[0,-2],[5,-4],[1,-3],[1,-2],[1,-4],[-1,-3],[0,-1],[-3,1],[-2,2],[-1,5],[-2,1],[-3,1],[-4,2],[-2,0],[-3,1],[-2,-1],[-1,1],[-1,4],[0,1],[1,5],[0,1],[-1,0],[-2,-1],[-1,1],[-3,3],[-1,1],[-3,0],[-2,-6],[0,-1],[2,-4],[3,-6],[-2,-1],[-4,2],[-2,1],[-1,4],[-3,1],[-1,1],[0,2],[0,4],[-1,0],[-4,-1],[-1,1],[0,2],[-1,1],[-2,1],[0,1],[1,1],[0,3],[1,11],[6,-2]],[[3028,2023],[1,-3],[0,-1],[4,-1],[1,1],[4,0],[2,1],[4,1],[3,-9],[0,-3],[-3,-3],[-2,0],[-2,1],[0,1],[0,1],[-1,2],[-2,0],[-1,-1],[-1,0],[-2,1],[-4,1],[-1,2],[0,1],[0,1],[-4,3],[-2,3],[-2,0],[-1,0],[-1,-1],[-1,-1],[-1,0],[0,1],[-1,1],[1,3],[1,0],[5,0],[3,-1],[3,-1]],[[3017,2072],[6,-5],[4,0],[0,-3],[0,-5],[0,-2],[-2,-2],[-1,-3],[-5,3],[-5,5],[-2,-1],[-3,2],[-3,-1],[-1,-2],[-4,-2],[-1,6],[-3,5],[-3,4],[2,6],[2,1],[2,2],[8,-2],[4,-2],[5,-4]],[[2974,2103],[1,-4],[0,-1],[2,1],[4,0],[5,-2],[1,0],[2,-6],[2,-2],[3,-4],[-3,-4],[-1,-4],[-1,-2],[-1,-2],[-1,-1],[-3,-3],[-3,0],[-3,-1],[-2,-2],[-1,1],[-2,1],[0,2],[2,1],[3,5],[0,5],[-3,1],[-1,0],[-2,0],[-1,1],[-1,-2],[0,-3],[0,-3],[0,-1],[-1,-1],[-3,1],[-3,3],[0,1],[1,5],[0,2],[-1,4],[-1,0],[-3,0],[-3,4],[-2,5],[-6,2],[5,6],[7,1],[2,-3],[7,-2],[0,3],[0,2],[1,1],[1,-1],[2,0],[0,-1],[1,-3]],[[2933,2136],[1,-1],[1,0],[2,-1],[5,-1],[6,-3],[2,-2],[4,-1],[3,-3],[1,-1],[1,0],[4,-6],[1,-1],[4,-5],[-2,-1],[-5,3],[-3,0],[-2,0],[0,1],[-1,3],[0,1],[-5,6],[-2,2],[-4,1],[-4,-1],[-2,1],[-1,-1],[-4,5],[-4,5],[-2,5],[-3,3],[0,2],[2,0],[2,-2],[3,-3],[1,-2],[1,-3]],[[3093,2024],[-5,0],[-1,-1],[-6,-2],[-11,3],[-3,3],[-4,5],[-1,-1],[-4,-3],[-4,-1],[-3,-1],[-2,3],[-1,1],[-1,0],[-6,-3],[-6,3],[-5,2],[-9,2],[-6,4],[-11,-1],[-2,2],[0,4],[0,2],[3,1],[0,2],[3,0],[3,-3],[1,0],[2,3],[3,2],[1,1],[5,-3],[2,0],[3,1],[1,2],[0,2],[1,1],[3,1],[3,-2],[0,-3],[0,-4],[3,-2],[5,1],[3,-2],[0,3],[-5,6],[-2,4],[-2,2],[-4,2],[-3,7],[0,7],[0,6],[6,4],[-1,5],[2,4],[2,2],[3,-15],[2,-6],[-3,-1],[-4,0],[2,-7],[5,-3],[3,-5],[0,-5],[3,-1],[5,0],[3,0],[2,3],[1,1],[4,-3],[5,-3],[2,-2],[1,-3],[0,-3],[0,-1],[2,0],[2,5],[1,1],[2,1],[1,1],[0,1],[-4,3],[-22,14],[-3,6],[-2,7],[0,7],[2,3],[4,2],[7,4],[8,6],[1,1],[0,4],[-1,3],[-3,1],[-4,1],[-3,0],[-3,-1],[-6,-4],[-4,0],[-3,2],[-2,5],[-2,5],[0,4],[1,3],[1,4],[2,1],[2,0],[2,1],[1,1],[1,1],[-1,2],[0,1],[-3,2],[-1,3],[-2,3],[1,1],[4,1],[3,-3],[2,-3],[2,0],[1,2],[4,4],[3,4],[2,6],[2,3],[3,1],[6,-11],[3,0],[8,5],[1,0],[2,-3],[1,-1]],[[2940,2193],[-1,-1],[-3,1],[-1,2],[-3,3],[0,3],[-1,3],[1,1],[2,-2],[1,-1],[1,-2],[4,-4],[1,-1],[0,-1],[-1,-1]],[[2921,2210],[1,-11],[1,-2],[3,-1],[3,-5],[0,-2],[-3,-10],[-1,-6],[-5,0],[-1,7],[-3,7],[-1,7],[-2,7],[3,4],[3,-1],[0,5],[2,1]],[[2929,2230],[0,-5],[-1,-1],[-1,-1],[-2,2],[-1,0],[-2,-2],[-2,-2],[-2,1],[-3,1],[-3,-7],[-1,-2],[-3,-4],[0,4],[2,6],[1,4],[1,6],[3,-2],[5,2],[4,4],[3,0],[1,-2],[1,-2]],[[2908,2265],[-1,-6],[-2,1],[-1,1],[0,4],[-1,1],[1,4],[1,3],[0,3],[3,0],[4,-1],[1,-1],[-1,-2],[-1,-2],[-3,0],[0,-5]],[[2915,2287],[-6,-5],[-1,2],[-4,0],[1,5],[0,4],[1,1],[0,3],[1,6],[4,-2],[2,0],[3,-2],[4,-1],[1,-5],[-4,-3],[-2,-3]],[[2913,2371],[0,-5],[-4,-8],[-3,-6],[-4,-4],[-2,0],[-1,2],[1,3],[3,4],[-1,4],[-1,1],[-1,1],[-1,2],[0,3],[1,2],[2,1],[1,-1],[5,2],[2,2],[3,1],[0,-4]],[[2931,2353],[0,-8],[0,-9],[-1,-10],[0,-3],[1,0],[0,-1],[0,-6],[-1,-4],[-1,-3],[-1,-5],[0,-1],[-3,0],[-2,0],[-1,5],[-1,3],[0,4],[-1,5],[0,2],[0,3],[2,2],[0,5],[0,1],[2,2],[0,1],[0,1],[-1,0],[-6,-6],[0,-2],[0,-2],[0,-9],[-1,-5],[-1,-1],[-3,0],[-4,1],[-4,4],[-3,-1],[0,5],[1,5],[5,-1],[1,8],[-2,2],[-2,3],[-1,3],[1,2],[3,3],[2,0],[1,-1],[4,1],[0,5],[-3,2],[0,4],[4,3],[3,4],[0,4],[-1,4],[0,1],[2,4],[3,1],[1,0],[3,-2],[2,0],[1,-1],[0,-3],[2,-19]],[[2902,2375],[-3,0],[-1,10],[4,15],[0,6],[-1,4],[0,4],[0,1],[5,3],[1,-3],[2,-9],[3,-11],[0,-12],[-2,-3],[-6,-2],[-2,-3]],[[2928,2385],[0,-1],[-4,0],[-5,-1],[-3,5],[-1,9],[-1,1],[-1,5],[-1,3],[-2,5],[0,5],[0,2],[1,3],[6,3],[2,4],[2,0],[0,-10],[1,-3],[2,-3],[0,-1],[1,-4],[1,-5],[1,-3],[0,-1],[0,-2],[0,-1],[1,-10]],[[2913,2428],[-2,0],[0,2],[-2,3],[2,2],[3,2],[2,0],[2,-2],[1,-2],[-4,-2],[-1,-2],[-1,-1]],[[2935,2552],[-1,-3],[-3,-1],[-2,2],[-4,-1],[0,5],[1,3],[3,5],[1,5],[0,8],[2,2],[0,3],[4,2],[0,-6],[-1,-11],[2,-6],[1,-2],[-1,-3],[-2,-2]],[[2915,2598],[0,-1],[-1,1],[-1,1],[-1,3],[1,2],[1,0],[1,-2],[0,-3],[0,-1]],[[2954,2602],[-1,-1],[0,1],[-1,2],[0,2],[-2,4],[-1,2],[0,2],[1,3],[2,1],[1,0],[1,-4],[0,-4],[1,-4],[-1,-4]],[[2972,2605],[-6,-5],[-4,1],[-1,4],[-1,3],[0,5],[1,2],[2,4],[1,2],[1,3],[-1,3],[1,2],[1,1],[5,-3],[5,-4],[2,-3],[0,-2],[-2,-5],[-1,-5],[-3,-3]],[[2952,2627],[-2,-3],[-2,0],[-3,-3],[-1,-3],[0,-3],[2,-3],[2,-5],[1,-6],[1,-6],[0,-2],[0,-3],[2,-5],[0,-2],[0,-2],[-1,-4],[0,-1],[-2,0],[0,-3],[-1,-1],[-4,0],[-3,1],[1,8],[-3,3],[-2,4],[-3,9],[-1,3],[-3,6],[-3,6],[4,4],[-1,6],[2,2],[4,3],[2,-2],[2,1],[1,1],[0,7],[1,5],[2,2],[3,1],[1,-3],[1,-3],[3,-2],[0,-3],[0,-4]],[[2949,2659],[1,-2],[-1,-1],[-2,1],[-1,-3],[-1,0],[-4,2],[-1,1],[0,3],[5,0],[3,2],[1,0],[0,-3]],[[2926,2672],[-4,-1],[-1,2],[0,1],[0,1],[2,1],[2,-1],[0,-1],[1,-1],[0,-1]],[[2950,2687],[-2,-1],[-2,0],[-2,1],[-3,-1],[-3,3],[-4,3],[-1,2],[1,2],[2,6],[2,12],[2,17],[-1,6],[0,3],[0,3],[1,3],[-1,3],[1,3],[2,7],[1,2],[0,4],[1,6],[-1,2],[-1,2],[1,1],[9,-4],[5,-1],[1,-5],[1,-4],[0,-7],[1,-1],[0,-5],[-3,-2],[0,-5],[2,-4],[-2,-2],[-3,-1],[0,-1],[-2,-1],[-2,-2],[1,-2],[2,-5],[3,-3],[2,-5],[2,-5],[-1,-4],[-2,-4],[-3,-3],[-3,-2],[0,-8],[-1,-3]],[[2811,3246],[-5,-1],[0,1],[1,2],[1,2],[1,0],[1,-1],[1,-1],[1,-1],[0,-1],[-1,0]],[[1964,3621],[-4,-2],[0,3],[1,3],[3,-2],[2,0],[-2,-2]],[[3098,2168],[-15,6],[-4,3],[-3,0],[-5,-4],[-4,-9],[-1,-2],[-4,-2],[-4,-1],[-14,-8],[-4,-1],[-4,-2],[-3,-4],[-1,-7],[0,-4],[-3,-15],[-1,-8],[0,-5],[1,-7],[-1,-12],[-3,-2],[-6,-4],[-4,3],[-7,2],[-5,4],[-6,4],[-2,2],[-6,9],[0,3],[-1,4],[3,5],[2,1],[4,0],[4,1],[3,-3],[0,-7],[-1,-3],[-1,-2],[1,-2],[2,2],[2,15],[9,7],[3,4],[3,7],[1,2],[0,2],[-2,2],[-4,3],[-14,-14],[-7,-4],[-4,-4],[-5,-7],[-1,-2],[-1,-4],[-1,-5],[-4,2],[-8,7],[-2,3],[2,4],[2,3],[0,11],[1,3],[2,3],[2,4],[2,1],[1,-2],[0,-2],[5,0],[9,9],[4,0],[5,-2],[6,2],[1,1],[1,2],[-4,2],[-4,2],[-12,1],[-2,-1],[-3,-5],[-2,1],[0,2],[-4,2],[-2,0],[-2,-3],[0,-3],[-1,-4],[-3,-4],[-3,-7],[0,-5],[0,-2],[-1,-2],[-1,-1],[-6,1],[-4,5],[-1,4],[-4,3],[8,5],[3,3],[3,6],[2,4],[-2,3],[-1,0],[0,-5],[-2,-3],[-4,1],[-5,-5],[-4,2],[-5,-2],[-3,3],[-1,3],[1,4],[-1,6],[-1,2],[-2,0],[-1,3],[-1,7],[-1,2],[-1,3],[1,1],[2,-1],[1,-2],[3,0],[6,-5],[2,1],[1,1],[1,4],[0,3],[1,0],[3,-4],[2,0],[4,-1],[2,1],[3,1],[5,5],[3,5],[2,1],[1,-1],[1,-1],[0,-4],[2,-3],[1,-3],[1,-3],[-1,-3],[-3,-4],[0,-2],[1,-1],[1,0],[2,2],[1,3],[0,2],[0,2],[0,3],[-2,8],[-1,1],[0,4],[3,3],[1,2],[0,5],[-1,4],[-6,7],[-11,8],[-1,-1],[-1,-1],[1,-1],[2,-1],[9,-6],[2,-4],[2,-1],[2,-2],[-1,-4],[-9,-3],[-7,-8],[-6,-4],[-3,1],[-2,5],[-2,6],[-3,3],[-2,0],[-1,1],[-1,2],[-2,-2],[-5,4],[-1,2],[3,6],[4,-2],[1,16],[-1,4],[-5,4],[-3,-1],[-3,1],[-2,2],[-3,1],[-2,1],[-3,2],[-3,2],[-5,10],[-2,6],[-1,6],[7,0],[4,1],[1,2],[-1,5],[-2,4],[1,3],[2,3],[2,-1],[6,-6],[1,-4],[4,-13],[1,-1],[0,-1],[8,-7],[2,0],[-1,6],[2,8],[3,2],[1,0],[0,2],[-2,3],[1,5],[-1,0],[-2,-3],[-4,-14],[-2,-3],[-4,7],[-1,4],[-1,2],[0,7],[7,-2],[-3,3],[-7,4],[-2,2],[-2,1],[-2,5],[-3,4],[5,7],[3,5],[9,-2],[1,1],[-1,4],[-2,-1],[-3,2],[-4,7],[0,4],[1,7],[2,1],[3,1],[4,-2],[2,-1],[2,0],[-2,5],[-3,2],[-2,4],[0,4],[1,3],[1,3],[0,5],[0,4],[1,2],[1,1],[0,1],[-3,0],[-1,-5],[0,-4],[-2,-4],[-1,-4],[0,-5],[-1,-5],[-2,2],[-2,2],[0,1],[0,3],[0,18],[0,14],[1,12],[3,4],[1,2],[2,-1],[2,0],[1,2],[-5,2],[-2,-1],[-2,-2],[-4,1],[-1,6],[-2,5],[0,7],[0,9],[5,-1],[4,-2],[11,1],[9,-9],[4,1],[0,2],[-3,2],[-2,5],[-1,1],[-1,3],[0,4],[-2,13],[-1,0],[-1,-5],[-2,-7],[-2,-4],[-4,-1],[-4,-1],[-4,1],[0,3],[0,4],[-2,2],[-4,1],[-1,1],[-1,3],[2,5],[1,3],[2,-1],[2,-1],[2,-4],[2,0],[3,3],[0,2],[-1,1],[-2,0],[-2,2],[-4,6],[2,6],[5,7],[2,1],[-2,6],[2,6],[-2,5],[-3,6],[-3,1],[-1,-2],[0,-2],[0,-2],[0,-1],[-1,0],[-5,2],[-3,3],[-6,4],[0,2],[-1,4],[2,7],[-1,0],[-4,-5],[-5,-3],[-4,-1],[-2,-2],[0,-2],[1,-1],[2,0],[2,-6],[-1,-3],[-1,-2],[-1,0],[-4,5],[-2,5],[0,4],[1,5],[6,7],[2,4],[4,3],[4,8],[4,4],[-2,4],[-2,5],[1,7],[8,3],[4,-1],[4,0],[3,2],[2,1],[4,2],[1,3],[1,2],[0,2],[-1,2],[0,6],[0,2],[2,3],[2,1],[1,-1],[3,-2],[-1,-3],[-1,-4],[-2,-15],[-1,-4],[-2,-3],[2,-6],[-2,-4],[-8,-5],[-1,0],[1,-2],[4,0],[4,1],[3,4],[1,6],[2,12],[1,2],[3,0],[1,-3],[-1,-6],[0,-6],[-3,-17],[-3,-8],[0,-1],[0,-3],[2,1],[3,3],[1,5],[2,7],[-1,5],[1,3],[0,10],[1,5],[0,7],[-1,3],[-3,1],[-1,5],[2,8],[5,0],[4,6],[4,2],[1,-1],[7,-5],[1,0],[0,2],[-1,1],[-3,2],[-4,6],[-6,1],[1,8],[1,7],[3,1],[5,2],[9,11],[2,8],[0,9],[-4,3],[-5,6],[-4,3],[-3,4],[0,6],[1,9],[4,2],[2,14],[-3,10],[1,7],[4,7],[0,4],[1,5],[4,1],[0,2],[-1,5],[-2,6],[0,8],[2,10],[4,-1],[-2,6],[-2,6],[0,3],[2,2],[2,1],[2,-3],[4,-10],[0,2],[-1,11],[-1,13],[-4,-2],[-3,1],[-1,2],[-1,3],[1,3],[1,3],[2,3],[5,2],[4,4],[1,9],[-1,-1],[-2,-8],[-3,-3],[-2,1],[-2,1],[-4,7],[-2,1],[-2,1],[-1,-2],[-5,-12],[-2,-2],[-8,-1],[-2,2],[-3,1],[0,3],[1,3],[2,2],[0,2],[-3,0],[-3,3],[-1,5],[0,7],[-3,11],[0,9],[1,6],[4,23],[1,12],[2,10],[0,7],[6,6],[2,4],[4,21],[1,12],[-7,34],[-2,7],[0,8],[2,14],[0,5],[-1,7],[-4,12],[-1,7],[2,6],[-1,8],[0,5],[1,4],[7,-2],[2,1],[2,2],[1,7],[1,10],[0,4],[1,7],[3,2],[1,6],[2,9],[3,23],[3,6],[2,7],[-1,10],[2,5],[2,3],[1,6],[2,6],[4,8],[2,10],[3,18],[1,11],[1,8],[0,7],[2,9],[2,7],[0,4],[5,9],[1,8],[-2,5],[0,8],[-1,12],[3,4],[1,3],[4,18],[0,7],[1,8],[-3,11],[0,23],[-2,18],[-2,18],[0,11],[-1,13],[0,8],[1,17],[7,11],[2,12],[1,16],[-1,12],[0,5],[-4,9],[-1,16],[1,4],[3,4],[2,6],[1,10],[2,7],[1,18],[2,15],[1,5],[3,6],[1,2],[0,5],[0,11],[0,7],[3,13],[0,7],[3,14],[0,10],[1,5],[0,6],[1,14],[-2,7],[-1,5],[3,13],[1,4],[3,6],[1,7],[0,5],[-3,23],[-1,7],[1,18],[1,12],[0,9],[0,5],[1,6],[2,7],[0,5],[0,3],[-3,2],[-2,7],[0,6],[0,5],[1,7],[3,1],[1,4],[2,7],[2,17],[1,21],[1,12],[1,6],[1,13],[1,9],[0,8],[0,6],[-3,30],[0,11],[1,18],[0,24],[0,6],[-1,5],[-1,7],[-1,13],[-2,25],[0,14],[-1,11],[-1,3]],[[3044,4127],[1,1],[2,0],[3,0],[4,3],[3,4],[3,7],[1,6],[0,5],[-1,6],[-1,5],[2,2],[3,1],[3,5],[2,3]],[[8079,6335],[2,-2],[1,-4],[0,-7],[1,-6],[-3,-4],[-2,-2],[-5,-15],[-1,-5],[-1,-2],[-1,-2],[0,-2],[-1,-8],[-1,-9],[-1,-3],[-1,-3],[-2,-2],[-1,0],[-1,-1],[-3,-5],[-3,-3],[1,-2],[0,-2],[-2,-1],[-1,0],[-4,-2],[-2,-2],[-2,-6],[-3,-1],[-2,-1],[-3,4],[-2,1],[-4,1],[-4,3],[-3,3],[-6,6],[-1,13],[-1,6],[0,3],[0,20],[1,3],[0,2],[3,4],[3,4],[5,8],[3,3],[3,5],[-2,0],[-1,0],[1,5],[1,2],[2,1],[3,-1],[2,1],[2,4],[2,1],[7,-1],[5,1],[3,4],[1,0],[3,-1],[2,-4],[0,3],[0,2],[5,-5],[0,6],[0,1],[2,3],[1,0],[1,-5],[2,-2],[2,-2]],[[8065,6399],[1,-2],[3,1],[1,-2],[0,-2],[-1,-2],[-3,2],[-2,-1],[-1,0],[-1,2],[1,3],[2,1]],[[8128,6430],[-3,-1],[1,3],[2,2],[0,-4]],[[8132,6428],[0,-1],[-1,2],[0,3],[-1,2],[1,2],[1,2],[2,-1],[-1,-3],[0,-1],[-1,-5]],[[8154,6497],[0,-2],[-2,4],[-1,0],[-1,1],[-1,3],[2,0],[2,-3],[1,-3]],[[8282,6595],[-1,-4],[-2,1],[0,2],[0,1],[1,2],[0,1],[2,-2],[0,-1]],[[8328,6650],[-3,-3],[-1,2],[0,3],[1,3],[-1,3],[1,3],[1,0],[1,-1],[1,-1],[0,-1],[0,-2],[-1,-3],[1,-2],[0,-1]],[[8367,6802],[-2,-2],[-1,0],[0,4],[2,4],[1,-1],[0,-2],[0,-3]],[[8393,6893],[0,-1],[-3,4],[-1,1],[1,2],[1,0],[2,-4],[0,-2]],[[8399,6906],[0,-3],[-1,0],[-1,5],[1,1],[1,0],[0,-3]],[[8396,6910],[0,-1],[-4,3],[-3,1],[-2,2],[0,5],[4,0],[5,-4],[1,-2],[-1,-4]],[[8384,6998],[-2,-2],[-7,5],[-5,5],[-3,7],[-1,3],[4,-1],[3,-2],[1,-4],[1,-1],[1,-2],[7,-5],[1,-1],[0,-2]],[[8625,7634],[-1,2],[-1,0],[-3,3],[-2,3],[-1,4],[0,7],[0,1],[-3,2],[0,2],[-1,1],[-2,-1],[-1,1],[-1,1],[-2,0],[-1,-1],[0,-5],[-2,-6],[0,-4],[-1,-6],[-1,-8],[0,-1],[-2,0],[-1,-1],[-1,-2],[-1,-1],[-1,2],[-2,1],[-1,0],[-2,-1],[-2,-3],[0,-3],[-1,-2],[0,-3],[-2,-3],[-1,-2],[-4,-4],[-1,-2],[-2,0],[-2,0],[-4,-1],[-5,0],[-4,0],[-4,0],[-3,-2],[0,-2],[0,-3],[0,-2],[1,-1],[1,-4],[2,-4],[2,-3],[1,-3],[0,-2],[-1,-3],[-2,-5],[-1,-2],[-1,0],[-2,1],[-1,2],[-3,1],[-6,-1],[-3,1],[-2,1],[-2,0],[-5,2],[-2,1],[-1,1],[-1,3],[-1,2],[0,3],[-2,3],[-1,2],[-2,0],[-1,-2],[-2,-1],[-1,0],[-1,0],[0,-2],[-3,-3],[-1,-2],[-1,-6],[-1,-6],[0,-2],[-1,0],[-1,-2],[-3,-6],[-2,-5],[-3,-3],[-1,-3],[-1,-3],[-2,-4],[-3,-1],[-3,-1],[-1,0],[-2,-2],[0,-2],[-1,-1],[-1,0],[-2,-2],[-3,-5],[-3,-1],[-3,-3],[-4,-3],[-1,-1],[0,-2],[-1,-1],[-1,-1],[-2,0],[-3,-4],[-2,-4],[-6,-8],[-3,-4],[0,-6]],[[8454,7488],[-1,0],[-2,-5],[-4,-4],[-10,-1],[-3,3],[-1,-2],[-1,-4],[-3,-1],[-4,0],[-2,-2],[-1,-2],[-5,-1],[-2,-3],[-4,-1],[-14,-14],[-3,-5],[-3,-7],[-2,-3],[-1,-3],[-2,-1],[-2,-2],[-1,0],[-2,1],[-2,-1],[-1,-2],[1,-4],[-1,-2],[-3,-2],[-6,-1],[-2,-2],[-1,-2],[-1,0],[-1,4],[-1,7],[3,1],[2,1],[11,8],[-1,7],[1,3],[2,4],[2,2],[-1,1],[-7,-1],[-5,0],[-2,0],[1,4],[-1,4],[0,2],[4,4],[1,1],[2,0],[0,3],[-2,4],[2,5],[8,6],[1,5],[4,6],[5,12],[1,3],[1,6],[1,2],[-3,3],[-1,5],[-8,9],[-1,8],[-1,-6],[-1,-2],[-4,0],[-2,2],[-10,2],[-2,-4],[-3,-5],[-2,-4],[-2,-2],[-2,-3],[-8,-21],[-3,-2],[-15,-12],[-7,-5],[-5,-9],[-2,-5],[-2,-6],[-1,-8],[-5,-11],[-2,-2],[-2,-1],[-2,0],[-2,-1],[-4,1],[-4,-3],[-5,-3],[-4,7],[-3,2],[-5,-2],[-2,-3],[-5,-16],[-1,-10],[0,-3],[2,-12],[3,-7],[7,-7],[15,-5],[3,2],[4,0],[4,-5],[2,-8],[1,-5],[0,-2],[1,-2],[0,-3],[-1,-2],[-2,-1],[-1,-9],[0,-9],[2,-3],[3,-4],[5,-4],[4,-1],[9,2],[3,6],[0,2],[0,3],[8,8],[4,8],[-1,2],[0,1],[0,1],[3,0],[10,8],[9,-6],[4,-7],[5,-2],[3,-3],[4,-4],[5,0],[4,0],[1,2],[2,2],[1,0],[2,-4],[4,-3],[5,0],[3,2],[2,-2],[-3,-5],[0,-8],[-2,-2],[-2,-4],[2,-3],[1,-1],[-1,-3],[-1,-2],[-3,-5],[-2,0],[-1,1],[-1,2],[0,3],[-1,2],[-4,0],[-3,0],[-7,-7],[-7,-6],[-8,-5],[-2,-2],[-2,-1],[-3,2],[-2,0],[0,-2],[2,-4],[1,-3],[-1,-2],[-1,-1],[-2,2],[-2,-3],[-1,-4],[0,-10],[-1,-2],[-3,-1],[-4,-4],[-1,2],[0,2],[0,4],[0,2],[-2,0],[-2,-1],[-2,-3],[-1,-2],[3,-6],[2,0],[0,-2],[-1,-2],[-5,-5],[-1,-3],[-1,-4],[-2,-2],[-1,-3],[-2,-2],[-2,-1],[-3,-7],[-3,-7],[-2,-3],[-2,-11],[-4,-6],[-2,-9],[1,-6],[4,0],[3,-2],[4,-7],[5,-5],[5,-3],[7,-7],[2,-3],[1,-6],[3,-18],[2,-8],[1,-5],[3,-8],[3,-15],[4,-13],[0,-9],[-1,-5],[0,-6],[4,-5],[8,-7],[2,-2],[1,-3],[0,-9],[2,-3],[1,-2],[5,-4],[2,-3],[2,-6],[1,-5],[0,-6],[-3,0],[-2,0],[-9,9],[-2,0],[-4,-1],[-4,1],[-6,10],[-3,3],[-4,1],[-9,-8],[-3,1],[0,-1],[-1,-2],[4,-1],[4,2],[4,4],[6,-2],[1,-3],[1,-6],[5,-4],[3,-2],[4,-5],[4,-9],[9,-9],[3,-9],[1,-6],[2,-8],[-3,-3],[-3,0],[-4,-2],[-3,-3],[-3,-5],[-9,-8],[-1,-5],[-2,-5],[-2,-2],[-5,2],[-5,0],[-6,-6],[-1,-2],[1,0],[1,1],[2,-1],[4,3],[4,-10],[8,2],[7,8],[2,0],[3,-1],[2,-3],[7,-14],[4,-2],[4,-3],[2,-1],[1,-1],[-5,-5],[-6,-11],[-3,-3],[-2,-3],[5,2],[4,5],[2,1],[1,-1],[1,-7],[-1,-20],[-2,0],[-2,5],[-2,2],[-2,-1],[-3,0],[-1,-3],[-1,-3],[2,-1],[4,-6],[0,-4],[-1,-2],[-3,1],[4,-4],[-1,-5],[-1,-2],[-2,-1],[-2,-5],[2,-6],[2,-9],[0,-5],[-3,2],[-4,-5],[-2,-1],[-2,7],[-2,-1],[-1,-2],[-2,-7],[-2,-7],[-2,-2],[-2,0],[-2,0],[1,-2],[2,-2],[0,-3],[-4,-8],[-1,-3],[0,-3],[-2,-4],[1,-5],[-1,-4],[-2,-6],[-1,-3],[-3,-6],[-3,-3],[-4,-13],[-1,-6],[0,-6],[-1,-2],[-2,-3],[-3,2],[0,4],[-1,0],[0,3],[-1,3],[1,3],[-1,-1],[-1,-3],[-2,-3],[-1,1],[-2,3],[0,-4],[1,-3],[0,-3],[3,-1],[2,-3],[1,-6],[0,-2],[1,-2],[0,-2],[-2,-2],[-3,-4],[-4,-6],[-2,-4],[-3,-1],[-2,1],[-2,2],[-2,1],[3,-8],[2,-2],[2,1],[3,3],[3,0],[1,-5],[-1,-6],[-2,-7],[0,-6],[2,-9],[0,-3],[-1,-1],[-2,2],[-3,3],[-2,-1],[-2,2],[-2,-1],[-1,-2],[0,-4],[2,-3],[2,-4],[-2,-1],[-6,1],[-1,-1],[-2,-5],[1,-7],[-1,-4],[-2,-1],[-3,-4],[-2,-1],[0,-1],[1,-2],[1,-2],[-2,-7],[-2,-2],[-5,1],[-3,-2],[-3,3],[-3,0],[-2,-4],[0,-4],[-2,-1],[-1,1],[-1,-1],[0,-2],[1,-2],[4,-1],[0,-3],[1,-5],[-5,-8],[-2,-5],[-2,0],[-2,-4],[-1,-6],[-2,1],[-3,-1],[-1,-3],[1,-1],[0,-2],[-1,-7],[-2,-2],[0,3],[-1,4],[-1,1],[-2,-4],[-2,-3],[-2,-1],[-1,2],[-3,2],[-2,-11],[-2,-4],[-2,-2],[-2,0],[1,-2],[1,-2],[-1,-3],[-2,-1],[-2,-2],[0,-10],[-2,-4],[-3,0],[-3,2],[0,-1],[-1,-2],[-1,-2],[-3,0],[-6,-5],[-2,1],[-4,2],[-2,-2],[-1,-3],[-1,-3],[-3,0],[-2,4],[-3,2],[-3,-2],[-2,-4],[-3,-2],[0,-2],[-1,-2],[-3,1],[-1,7],[-2,0],[-2,-3],[0,-2],[-1,-2],[0,-6],[-1,0],[-2,4],[-3,0],[-2,-3]],[[8173,6482],[-1,1],[-1,1],[-2,0],[0,-1],[-2,-1],[-1,-1],[0,-1]],[[8166,6480],[-2,2],[-3,4],[-2,7],[-3,4],[-1,4],[0,6],[-1,3],[1,3],[0,3],[-2,-2],[-3,-2],[1,-4],[-1,-3],[-3,-2],[0,-1],[1,-1],[2,-5],[1,-3],[1,-2],[1,-6],[0,-11],[1,-3],[0,-3],[-1,-4],[0,1]],[[8153,6465],[-1,0],[-1,-2],[0,-1]],[[8151,6462],[-1,-1],[-2,-1],[-1,-1],[-2,-3],[-3,-1],[-1,8],[-3,-5],[0,-11],[-1,-1],[-2,-2],[-2,4],[-3,-3],[-1,-2],[-1,-2],[-1,-3],[-3,3],[-2,3],[1,3],[-1,2],[-1,1],[-1,0],[1,-4],[0,-6],[-1,-2],[-1,-2],[-3,1],[-2,3],[-3,2],[-2,0],[-1,-4],[-1,-3],[-2,-1],[-1,1],[-2,-4],[-1,-3],[-2,-2],[-6,-2],[-2,-3],[-2,1],[-2,-1],[-2,0],[-1,2],[-1,0],[-1,-5],[-3,-2],[-3,0],[-3,-7],[-2,-3],[-2,-1],[-2,2],[0,5],[-1,1],[0,-5],[-1,-5],[-1,-2],[-4,-5],[-1,-6],[1,-5],[5,-1],[1,-3],[-1,-2],[-1,-2],[-1,-3],[6,-8],[0,-4],[-1,-2],[-1,-4],[-3,-3],[-6,-2],[-5,2],[-2,4],[1,3],[1,-1],[1,0],[0,3],[-1,1],[-2,2],[-2,7],[0,5],[-1,4],[-1,3],[-1,2],[-1,3],[2,7],[-1,5],[2,6],[1,6],[4,2],[0,6],[-3,0],[-2,5],[0,-2],[-2,0],[-3,8],[0,1],[-2,0],[1,-9],[-3,-3],[-2,-1],[-4,-1],[-2,-1],[-2,1],[1,2],[1,4],[-1,2],[-2,2],[-3,0],[-2,1],[-2,0],[-1,1],[-2,4],[-2,3],[0,2],[0,3],[0,2],[-3,0],[0,-4],[0,-5],[1,-4],[-1,-2],[-1,-2],[-2,4],[-1,2],[-1,-1],[0,-4],[-2,-3],[-3,0],[-2,-2],[-3,-1]],[[7998,6423],[-1,3],[-3,5],[-1,0],[-4,-2],[-4,-1],[-2,2],[-2,-2],[-2,6],[-3,1],[-3,4],[-1,2],[0,4],[-1,2],[-2,-1],[-1,2],[-2,2],[-2,1],[-1,-1],[-1,0],[0,2],[0,7],[0,6],[-1,3],[-1,2],[-1,1],[0,3],[0,6],[1,4],[1,1],[2,3],[1,4],[1,4],[-4,5],[-2,2],[-3,-1],[-3,-1],[-2,-1],[0,1],[-2,5],[-1,1],[-2,0],[-2,0],[-1,-2],[-2,-1],[-2,0],[-1,3],[-3,3],[-4,3],[0,3],[-1,3],[-2,3],[-2,4],[-2,2],[-1,-1],[-2,-2],[-5,-5],[-3,-2],[-1,-2],[-1,-2],[0,-5],[-1,-6],[-1,-2],[-2,-3],[-1,0],[-2,0],[-1,-1],[-5,-5],[-2,0],[-1,3],[-1,3],[-2,-1],[-2,-3],[-2,-5],[0,-4],[-1,-2],[-1,-1],[-8,13],[0,1],[-2,-3],[-1,-7],[-1,-1],[-1,0],[-3,9],[-1,1],[-1,-3],[-2,-4],[-2,-3],[0,-3],[-2,-2],[-2,-3],[-1,1],[-2,3],[-1,4],[-3,3],[-4,3],[-2,3],[-1,0],[-2,-1],[0,-1],[-1,-4],[-2,-6],[-2,-4],[-2,-3],[-1,-2]],[[7836,6473],[-1,2],[-2,1],[-2,0],[-3,-3],[-2,6],[-1,0],[-1,0],[-1,-1],[0,-4],[-1,-4],[-1,-3],[-2,-1],[1,-3],[0,-3],[0,-2],[1,-4],[1,-4],[2,-6],[1,-3],[0,-3],[1,-10],[-1,-4],[0,-8],[0,-4],[1,-3],[1,-2],[0,-1],[0,-1],[-2,-3],[-1,0],[-1,1],[-1,1],[-1,1],[-1,2],[-3,0],[-4,-3],[-1,1],[-1,1],[0,3],[0,4],[-1,2],[0,2],[0,6],[-1,3]],[[7809,6426],[0,1],[-1,7],[0,2],[-1,1],[-2,-1],[-5,-5],[-4,-9],[-2,-1],[-2,-1],[-3,1],[-2,1],[-4,-2],[-2,1],[-1,2],[-1,3],[1,3],[0,2],[-2,2],[-2,1],[-1,3],[0,4],[0,4],[1,5],[-1,3],[-3,1],[-6,2],[-6,1],[-2,0],[-2,0],[-1,1],[-1,2],[0,2],[1,5],[1,5],[3,8],[0,5],[0,6],[1,7],[2,6],[1,2],[0,3],[-1,2],[-1,2],[-2,1],[-4,1],[-4,1],[-6,4],[1,6],[0,4],[-1,4],[-1,2],[0,3],[1,6],[-2,6],[-1,3],[-2,3],[0,4],[1,3],[4,7],[0,2],[-1,0],[-1,0],[-5,-3],[-1,2],[-2,1],[-3,0],[-5,0],[-5,-3],[-5,-5],[-2,-3],[-2,-2],[-2,0],[-2,1],[0,4],[4,9],[0,5],[-1,5],[0,4],[-1,3],[-2,1],[-1,2],[0,9],[2,8],[2,2],[2,2],[0,1],[-1,6],[1,4],[1,7],[1,5],[3,-1],[1,2],[2,2],[1,3],[1,4],[1,9],[1,1],[4,-1],[1,1],[2,5],[1,6],[3,2],[2,0],[1,3],[0,3],[-2,5],[-1,4],[0,2],[3,1],[0,3],[0,7],[1,7],[1,9],[0,7],[0,5],[0,5],[-1,10],[-1,8],[0,3],[0,10],[0,9],[-2,1],[-3,3],[-1,1],[-1,-1],[-1,-3],[-1,-3],[-1,1],[-1,2],[-1,4],[-3,18],[0,5],[-1,5],[-1,2],[-1,2],[-2,6],[-2,2],[-2,0],[-1,0],[-1,3],[-1,4],[-1,1],[-2,1],[-1,0],[-1,-3],[-1,-2],[-1,-4],[-2,-6],[-1,-2]],[[7703,6809],[-1,1],[-4,6],[-2,2],[-3,-2],[-4,1],[-2,1],[-3,4],[-1,1],[-5,-3],[-1,-2],[-1,0],[-1,1],[-1,1],[0,1],[1,3],[0,1],[0,2],[2,4],[5,10],[-1,3],[-2,8],[0,3],[-1,2],[-2,-1],[-6,-7],[0,1],[0,2],[-1,7],[2,2],[2,2],[2,3],[1,3],[-1,0],[-3,-1],[-1,2],[-2,6],[-1,3],[-1,1],[-4,-3],[-5,-5],[-6,-6],[0,-3],[0,-1],[-1,-2],[-1,-3],[-1,-1],[-1,0],[-2,1],[-4,3],[-4,3],[-1,-1],[-5,2],[0,2],[-1,3],[-2,2],[-1,1],[-5,-5],[-4,-5],[-3,-4],[-3,-5],[-2,-1],[0,-3],[-1,-3],[-2,-3],[-4,-4],[-3,-3],[-8,-2],[-3,-1],[-2,-2],[-1,-6],[-1,-5],[-2,-5],[-5,-5],[-5,-5],[-1,-3],[0,-2],[0,-1],[1,-1],[0,-2],[-1,-2],[-3,-4],[-2,-2],[-2,-2],[-2,0],[-2,1],[-1,0],[-2,-1],[-1,-1],[-4,-4],[-2,0],[-2,1],[-3,1],[-2,0]],[[7468,6757],[-1,3],[-2,4],[0,5],[2,14],[0,6],[0,2],[-1,6],[-1,2],[-4,3],[-1,0],[-2,-2],[-1,-1],[-1,-2],[-5,-2],[-3,-1],[-1,-1],[-1,-2],[1,-2]],[[7447,6789],[-3,1],[-2,0],[-2,0],[-5,-4],[-2,0],[-2,0],[-2,0],[-5,0],[-4,1],[-4,5],[-2,3],[-2,2],[-3,1],[-1,3],[-1,1],[-2,0],[-1,-1],[-1,-7],[-1,-1],[-2,-1],[-3,2],[-3,4],[-1,4],[-1,1],[-2,-2],[0,-5],[0,-3],[-2,-2],[-1,1],[-1,4],[-2,8],[-3,5],[-2,4],[-7,-1],[-6,1],[-2,2],[-1,3],[1,6],[1,5],[0,2],[-1,0],[-2,1],[-6,-4],[-1,1],[-1,1],[-2,1],[-1,1],[0,3],[-5,5],[-2,3],[-3,4],[-2,2],[-2,7],[-1,7],[-1,4],[-2,2],[-2,1],[-4,-3],[-4,-2],[-2,0],[-3,7],[-3,7],[-4,7],[-2,3],[-4,1],[-4,4],[-6,8],[-4,6],[-8,7],[-2,3],[0,3],[-1,5],[-2,5],[-5,2],[-6,1],[-6,-3],[-5,-14],[-2,-3],[-2,0],[-1,3],[-1,4]],[[7250,6921],[-1,4],[-3,3],[-4,5],[-2,3],[-2,2],[-1,0],[-4,3],[-4,3],[-2,0],[0,3],[0,4],[0,4],[-1,2],[-2,0]],[[7224,6957],[-5,6]],[[7219,6963],[0,0]],[[7219,6963],[-1,2],[-2,3],[-4,-1],[-3,-1],[-2,3],[-2,4],[-1,1]],[[7204,6974],[-1,1]],[[7203,6975],[-3,8],[-3,10],[-2,1],[-1,-1],[-1,-5],[-1,1],[-1,-1],[-2,-1],[-1,-1],[-1,1],[0,1],[0,6],[-1,3],[1,4],[1,4],[-1,3],[-2,4],[0,4],[1,4]],[[7186,7020],[0,5],[0,1],[-1,2],[-5,11],[-1,2],[0,3],[-1,6],[0,4],[-1,3],[0,1],[0,1],[4,1],[2,0],[2,1],[1,-2],[1,-3],[0,-2],[2,-3],[2,-3],[3,0],[2,1],[1,5],[1,2],[2,0]],[[7200,7056],[0,3]],[[7200,7059],[0,8],[0,4],[-1,3],[1,3],[-1,4],[-1,4],[-1,1],[0,2],[0,3],[0,3]],[[7197,7094],[0,3],[0,1]],[[7197,7098],[-1,1],[-2,2],[-2,4],[-1,2],[-1,2],[-2,4],[0,9],[0,9],[-1,5],[-1,7],[0,2],[1,2],[5,6],[1,2],[0,2],[0,3],[-1,2],[-2,3],[-3,3],[-2,4],[-5,2],[-5,3],[-1,3],[-1,6],[-3,11],[-2,11],[-2,6],[0,3],[1,9],[0,1],[-1,1],[-2,-1],[-1,-1],[-1,0],[-1,2]],[[7161,7228],[-1,0]],[[7160,7228],[-2,-1],[-4,0],[-1,0],[-2,0],[-5,2],[-5,3],[-6,3],[-3,3]],[[7132,7238],[-1,1],[-3,3],[-2,2],[0,7],[-2,-1],[-3,-2],[-4,-2],[-2,0],[0,1],[-2,7],[-1,2],[-1,1],[-2,1],[-1,2],[0,2],[1,3],[1,2],[0,12],[-1,5],[0,3],[-2,5],[-1,3],[-2,2],[-3,3],[-2,1],[-4,-2],[-1,1],[-1,8],[-1,2],[-5,3],[-3,1],[-3,-1],[-1,-1],[-2,2],[-2,2],[-2,1],[-2,0],[-2,-1]],[[7080,7328],[0,1],[3,3],[2,3],[1,2],[-1,4],[-3,4],[-2,3],[0,2],[0,5],[1,4],[-1,2],[0,2],[0,5],[-2,7],[-1,4],[-1,5],[0,4],[2,8],[-1,3],[-1,3],[-7,5],[-6,4],[-3,-1],[-1,1],[-2,-3],[-1,-4],[-2,-1],[-3,2],[-2,2],[-1,6],[-1,7],[-1,2],[1,2],[0,1],[2,2],[0,1],[0,2],[-1,3],[-2,3],[-2,7],[0,4],[1,6],[0,3]],[[7045,7456],[2,1],[3,1],[1,3],[1,2],[0,2],[0,6],[-2,3],[0,2],[1,2],[1,3],[1,6],[2,3],[0,1],[2,1],[5,1],[4,3],[6,7],[2,3],[2,1],[2,0],[0,1],[-1,4],[0,2],[1,2],[1,0],[4,-2],[3,0],[3,1],[8,9],[1,0],[1,-1],[1,-6],[1,-10],[0,-2],[6,0],[4,4],[1,1],[3,-1],[1,2],[2,2],[1,-5],[2,2],[3,4],[1,3],[1,4],[2,5],[0,4],[1,3],[1,2],[3,9],[3,3],[2,1],[5,-2],[3,0],[8,-1],[4,2],[3,2],[4,-1],[4,2],[7,12],[0,2],[0,3],[2,2],[3,3],[6,6],[11,9],[4,3],[2,0],[4,3],[7,4],[2,6],[2,1],[9,1],[0,1],[0,4],[-1,4]],[[7227,7614],[1,1],[1,1],[0,3],[-2,7],[-1,7],[0,6],[0,2],[1,4],[1,4],[5,3],[3,1],[1,2],[-3,2],[-2,2],[0,1],[0,2],[0,1],[4,2],[3,3],[3,-2],[1,1],[0,3],[0,2],[-1,4],[-2,2],[0,3],[1,4],[-1,8],[-2,7],[-3,12],[-2,3],[-1,6],[-1,3],[0,4],[1,3],[-1,6],[0,6],[0,7],[1,4],[0,2],[1,1],[1,1],[1,1],[-1,2],[-2,1],[-3,3],[-4,-1],[-4,0],[-1,2],[-2,2],[0,1],[2,4],[3,3],[5,2],[5,2],[3,2],[3,1],[4,1],[2,-1],[5,2],[9,5],[7,4],[3,2],[1,-2],[1,-5],[2,-3],[3,-1],[1,0],[3,2],[4,1],[2,0],[2,-3],[2,-2],[2,0],[1,2],[1,3],[0,5],[0,4],[0,3],[-1,1],[-3,2],[-4,3],[0,2],[0,2],[1,4],[2,8],[2,12],[1,8],[4,14],[3,13],[5,20],[1,4],[0,6],[1,3],[1,1],[3,-1],[7,-5],[5,-4],[3,-1],[3,-1],[5,-2],[3,1],[3,1],[3,0],[5,-1],[2,-1],[2,0],[2,-2],[0,-4],[1,-2],[2,1],[5,4],[2,3],[4,4],[3,1],[4,1],[1,2],[1,5],[3,4],[0,4],[-1,4],[-1,5],[0,4],[-1,11],[-1,10],[1,8],[2,8],[0,3],[2,3],[1,5],[2,1],[7,1],[6,2],[3,2],[3,1],[1,1],[4,6],[1,4],[1,9],[-1,5],[1,4],[2,2],[2,2],[1,1],[3,0],[5,0],[3,-1]],[[7425,8011],[3,0],[1,0],[1,2],[2,1],[2,1],[3,1],[2,-1]],[[7439,8015],[0,-2],[0,-2],[0,-3],[1,-2],[0,-2],[-2,-1],[-1,-2],[0,-2],[1,-2],[1,-3],[3,-1],[2,-2],[1,-2],[0,-2],[-1,-2],[-1,-2],[0,-1],[0,-2],[2,0],[3,-2],[4,-2],[3,-4],[3,-1],[1,-4],[1,-6],[3,-3],[4,-4],[2,0],[2,-3],[2,-2],[2,-1],[2,-1],[4,3],[4,0],[2,-1],[2,-6],[2,-1],[1,-2],[1,-1],[2,-1],[2,2],[1,2],[2,-1],[1,-1],[0,-3],[1,-3],[3,-3],[3,-1],[0,-1],[1,-4],[1,-2],[1,-3],[1,-6],[0,-4],[1,-3],[2,-4],[2,-6],[2,-6],[2,-1],[2,-2],[2,-4],[2,-8],[0,-5],[0,-3],[1,-2],[0,-2],[-2,-8],[-1,-4],[0,-3],[1,-5],[1,-5],[0,-4],[-1,-3],[-2,-3],[-1,-2],[-2,-2],[-2,-7],[-1,-8],[0,-4],[1,-3],[1,-3],[0,-3],[3,-6],[1,-4],[1,0],[1,1],[2,0],[3,-1],[2,-3],[3,-1],[3,0],[2,-2],[2,-1],[5,0],[3,0],[5,0],[4,-2],[7,-2],[4,0],[6,2],[3,-1],[11,-2],[6,-2],[4,-3],[3,-4],[3,-6],[2,-3],[7,-2],[4,-7],[4,-3],[6,-7],[4,-2],[6,-3],[8,1],[0,-1],[0,-4],[-1,-5],[0,-4],[1,-2],[3,-1],[2,-2],[1,-3],[1,-2],[2,-11],[5,-16],[0,-7],[1,-4],[5,-6],[3,-5],[3,-5],[1,-4],[1,-6],[1,-2],[6,2],[6,1],[10,1],[15,-3],[14,-3],[13,-2],[7,-2],[14,-2],[8,3],[7,3],[2,0],[12,-4],[7,-1],[9,-2],[6,-1],[6,0],[2,-1],[2,-1],[2,-2],[4,-10],[3,-5],[5,-3],[12,-4],[6,-2],[7,-3],[5,-4],[6,-4],[7,-6],[8,2],[9,3],[5,2],[0,-13],[8,-1],[2,0],[3,-2],[2,1],[2,3],[2,4],[4,2],[5,5],[2,1],[8,7],[12,8],[6,4],[2,1],[3,2],[2,2],[4,1],[5,0],[6,2],[12,3],[2,0],[7,2],[3,1],[4,-1],[6,0],[4,-1],[5,0],[8,1],[5,0],[3,1],[5,3],[2,3],[5,3],[5,3],[4,3],[3,2],[3,1],[1,3],[1,2],[1,2],[3,6],[2,5],[2,2],[2,5],[2,3],[3,5],[2,2],[3,1],[7,5],[2,1],[1,0],[2,4],[3,3],[1,3],[3,1],[1,2],[1,2],[-1,3],[-1,4],[-1,3],[-4,6],[-3,4],[-2,5],[-1,5],[-2,3],[0,2],[0,3],[2,6],[1,3],[1,6],[2,9],[1,4],[2,4],[4,5],[4,1],[2,-1],[5,0],[4,0],[2,-3],[3,-5],[3,-2],[9,-4],[5,-1],[2,0],[5,-2],[1,0],[2,-1],[2,1],[3,4],[3,4],[2,1],[3,1],[1,2],[3,5],[3,3],[3,5],[2,4],[1,3],[0,3],[1,1],[3,2],[2,0],[5,-2],[7,0],[2,1],[6,1],[3,1],[4,1],[3,5],[4,5],[3,3],[1,0],[3,3],[1,4],[0,2],[-1,3],[2,4],[2,8],[3,3],[2,3],[1,5],[2,1],[2,1],[2,3],[2,1],[4,-2],[5,0],[3,0],[1,0],[1,2],[0,2],[1,6],[0,2],[1,1],[3,0],[2,-2],[2,-2],[2,0],[2,1],[2,5],[5,3],[2,0],[5,3],[2,-1],[5,-1],[2,1],[2,-1],[2,3],[1,1],[4,-1],[2,-3],[3,-3],[5,-1],[4,0],[4,-1],[2,0],[1,1],[4,3],[1,4],[-1,3],[1,4],[-1,3],[-2,4],[-1,2],[0,4],[-2,4],[-3,4],[-2,2],[-4,7],[-1,2],[-1,1],[0,2],[-2,1],[-2,2],[-1,2],[-1,3],[0,3],[-2,1],[-2,1],[-2,2],[-3,2],[-2,3],[-3,7],[-2,3],[-7,0],[-3,2],[-3,0],[-2,-1],[-3,0],[-2,-1],[-3,-5],[-3,-6],[-3,-3],[-2,-4],[-1,-2],[-2,1],[-2,5],[-4,3],[-3,2],[-2,1],[-3,1],[-3,0],[-4,-2],[-4,1],[-2,0],[-2,0],[-5,-4],[-2,-4],[-2,-2],[-3,3],[-3,4],[-2,4],[-2,4],[-1,11],[3,3],[4,4],[1,5],[0,7],[0,7],[4,6],[2,6],[0,3],[2,5],[2,6],[2,8],[5,14],[5,16],[2,8]],[[8240,8054],[6,-5],[4,-3],[6,-4],[6,-1],[7,-4],[3,-1],[1,0],[9,10],[7,9],[9,7],[6,1],[5,1],[3,4],[2,5],[0,7],[-1,4],[-3,2],[-1,1],[2,2],[1,3],[1,4],[1,4],[3,4],[2,5],[0,4],[2,5],[3,5],[1,5],[1,4],[1,5],[5,9],[2,10],[5,7],[8,7],[4,7],[2,7],[0,7],[-2,5],[0,6],[1,5],[-1,5],[-4,2],[-4,1],[-6,-1],[-3,1],[0,5],[1,4],[4,3],[5,8],[8,11],[8,7],[12,2],[9,4],[10,4],[6,1],[2,-1],[3,0],[7,1],[6,1],[5,3],[4,1],[4,-2],[1,0],[2,0],[2,1],[3,-2],[7,-6],[5,-3],[2,1],[2,-2],[2,-4],[3,-2],[4,-1],[5,-5],[2,0],[1,2],[2,2],[2,0],[5,-2],[5,-5],[4,-2],[1,1],[1,-1],[2,-2],[0,-3],[-1,-1],[2,-3],[1,0],[3,-1],[2,-4],[1,-2],[1,-1],[1,-2],[0,-1],[-1,-1],[0,-2],[0,-2],[0,-2],[4,-2],[1,-1],[0,-2],[1,-2],[2,-3],[1,-2],[-1,-2],[1,-1],[1,-2],[0,-4],[0,-2],[2,-3],[0,-5],[1,-6],[4,-9],[2,-4],[-1,-6],[1,-2],[2,-1],[1,-3],[-1,-3],[1,-2],[1,-2],[-1,-4],[1,-3],[1,-1],[0,-4],[1,-4],[2,-6],[5,-10],[3,-7],[2,-4],[0,-5],[-2,-3],[0,-2],[1,-2],[1,-2],[-1,-2],[2,-3],[5,-5],[-2,-8],[0,-6],[0,-6],[1,-4],[3,-2],[1,-3],[1,-2],[3,-3],[5,-3],[6,-1],[8,2],[5,1],[2,-2],[1,-2],[-1,-2],[1,-2],[4,-1],[2,-2],[1,-2],[2,-1],[2,1],[1,0],[2,-1],[1,0],[1,2],[2,0],[1,0],[1,-4],[2,-2],[2,-1],[3,-4],[7,-13],[5,-5],[4,-2],[6,0],[1,-5],[-1,-5],[0,-5],[1,-1],[2,-6],[2,-3],[0,-2],[2,-3],[-1,-5],[-2,-7],[1,-6],[3,-6],[2,-5],[0,-4],[1,-3],[1,-1],[3,0],[6,2],[4,0],[2,-3],[7,0],[10,2],[6,1],[3,-1],[2,3],[2,7],[2,3],[2,0],[3,2],[4,5],[4,3],[4,-1],[5,0],[3,2],[2,4],[5,4],[10,5],[3,1],[1,0],[3,-1],[3,-2],[3,-4],[0,-2],[0,-4],[-1,-2],[-1,-2],[-1,-3],[1,-3],[1,-6],[2,-4],[1,-5],[0,-2],[-1,-3],[-3,-6],[-2,-2],[-1,-2],[-3,-1],[-1,0],[-2,-1],[0,-2],[-1,-2],[-2,-3],[0,-2],[1,-4],[0,-4],[-2,-3],[-1,-5],[-1,-2],[0,-4],[-1,-1],[0,-9],[-2,-5],[-2,-7],[0,-4],[1,-4],[-1,-1],[0,-2],[0,-3],[-1,-2],[-3,-2],[-1,-3],[0,-4],[0,-3],[-1,-3],[-2,-2],[-1,-2],[-1,-1],[-1,-4],[0,-3],[-1,-3],[1,-3],[-1,-2],[-3,-2],[-1,-1],[-1,-1],[-2,-3],[-2,-10],[-1,-6],[1,-5],[-3,-3],[-2,-3],[-2,1],[-1,1],[-3,1],[-2,1],[-3,2],[-5,2],[-5,2],[-3,2],[-3,1],[-2,1],[-1,4],[-2,-2],[-1,-3],[-3,-2],[-1,-4],[-1,-3],[-2,-5],[-2,-1],[-5,-3],[-1,-1],[-4,0],[-1,-2],[-1,-2],[-1,-3],[1,-2],[2,-6],[0,-4],[2,-7],[3,-23],[-1,-4],[-1,-17],[0,-3],[0,-5],[0,-3],[1,-1],[1,-1],[0,-3],[0,-3],[0,-2],[-1,-5],[-1,-6],[-1,-3],[-1,-2],[-1,-1],[0,-5],[0,-3],[-2,-1],[-2,-2],[-2,1],[-1,-1],[-3,-1],[-4,-1],[-2,-2],[-1,-2],[-1,-1],[0,-2],[0,-1],[3,0],[1,-3],[0,-3],[-1,-2]],[[4914,5479],[-1,-2]],[[4913,5477],[-4,1],[1,2],[4,-1]],[[4925,5730],[0,-3],[-1,-5],[0,-2],[1,-2],[0,-3],[-2,-7],[0,-3],[2,-1],[1,-4],[1,-7],[0,-2],[0,-2],[1,-16],[2,-16],[-1,-3],[-1,0],[-1,-1],[0,-1],[0,-3],[0,-2],[-2,-1],[-3,-5],[0,-2],[-1,-5],[-1,-3],[-1,-5],[-2,-13],[0,-11],[0,-3],[-1,-3],[-1,-3],[-4,-9],[-1,-8],[0,-3],[0,-4],[-1,-2],[1,-7],[0,-5],[1,-6],[2,-15],[2,-9],[0,-7],[1,-5],[1,-2],[0,-2],[4,-2],[1,-1],[1,-9],[0,-5],[-1,-1],[0,-4],[0,-5],[-1,-1],[-2,-1],[-1,-1],[-2,0]],[[4916,5479],[-1,1],[-1,1],[-3,2],[1,9],[-1,0],[-1,-1],[-2,-10],[-1,-2],[-15,6],[-3,4],[-4,1],[-7,-1],[-5,-1],[-2,-3],[14,2],[2,0],[0,-2],[-17,-3],[-7,-2],[-2,0],[-1,4],[-7,0],[-2,-1],[-1,-3],[3,1],[5,0],[1,-2],[-14,-2],[-10,-5],[-4,-3],[-13,-11],[-9,-5],[-2,-2],[-4,-5],[-4,-4],[-6,-6],[-3,-2]],[[4790,5434],[-1,2],[0,11],[0,15],[0,5],[0,5],[0,4],[2,2],[0,2],[1,5],[1,5],[0,9],[1,2],[0,3],[-1,5],[-1,11],[0,1],[0,-1],[-1,0],[-4,4],[-2,1],[-2,3],[0,4],[-1,2],[-1,4],[-1,5],[-2,3],[-3,1],[-1,-1],[-2,0],[-3,2],[-1,2],[-2,3],[-1,3],[-1,0],[-2,0],[-1,2],[0,1],[5,11],[2,6],[0,3],[0,3],[1,4],[0,5],[-3,20],[-1,6],[-1,1],[0,1]],[[4764,5619],[1,3],[3,-1],[3,-2],[1,2],[2,10],[0,3],[0,3],[1,7],[1,2],[1,3],[0,4],[-1,1],[-1,0],[-2,1],[-2,2],[-1,2],[1,9],[0,3],[0,1],[2,1],[3,0],[3,-1],[2,0],[1,0],[1,-3],[2,-3],[1,0],[0,2],[0,9],[-1,5],[-2,4],[-4,4],[0,5],[0,6],[1,2],[3,4],[0,2],[-1,2],[-2,2],[0,7],[0,6],[-2,-1],[-2,0],[-1,2],[-1,4],[-1,10],[0,12],[0,5],[1,3],[1,3],[2,3],[1,2]],[[4778,5769],[3,1],[1,3],[2,6],[3,5],[2,0],[1,1],[1,0],[1,-3],[2,-3],[1,-4],[5,-2],[2,-1],[2,-4],[1,0],[0,1],[1,1],[0,1],[-1,3],[1,3],[0,3],[2,0],[2,0],[2,0],[2,0],[0,2],[0,7],[0,4],[0,3],[1,2],[2,-4],[2,-2],[2,0],[1,1],[-1,4],[0,1],[1,1],[1,1],[3,1],[0,-7],[0,-2],[1,-5],[1,-4],[0,-2],[-1,-3],[-1,-2],[0,-1],[1,-2],[3,-2],[2,0],[1,3],[2,2],[0,1],[1,3],[1,2],[4,3],[4,0],[1,-1]],[[5449,5315],[0,-1],[0,-3],[-2,-2],[-1,-4],[0,-5],[0,-6],[2,-7],[0,-4],[-1,0],[-1,-2],[0,-1],[-3,5],[-2,3],[-4,6],[-4,2],[-5,1],[-2,-1],[-2,2],[-2,2],[-1,1],[-2,-2],[-1,0],[-2,1],[-3,0],[0,3],[0,1],[-3,-1],[-1,3],[-1,0],[-1,1],[-3,3],[-2,-2],[-6,0],[-7,0],[-7,0],[-7,0],[-6,0]],[[5369,5308],[-1,4],[-1,2],[-3,0],[-7,-1],[-6,1],[-1,0],[-2,1],[-5,1],[-6,-1],[-1,1],[-5,-1],[-10,1],[-6,0],[0,-2],[-1,-2],[0,-3]],[[5314,5309],[-6,0],[-9,0],[-8,0],[-5,0],[-9,0],[-3,2],[-1,2],[0,2],[-1,1],[0,1]],[[5272,5317],[0,13],[2,11],[0,11],[2,9],[-1,9],[-1,4],[-6,14],[3,5],[-4,-1],[0,5],[-2,6],[1,0],[1,4],[3,-1],[0,1],[-3,5],[1,3],[1,2],[-1,2],[-2,-3],[-1,0],[-1,2],[-1,0],[0,-4],[-1,-3],[-1,-1],[-1,0],[-2,1],[0,2],[-2,1],[-3,3],[-4,2],[0,8],[-1,4],[-1,4],[0,4],[0,7],[-1,1],[-1,1],[-1,-1],[-1,1],[-2,3],[-1,2],[1,-7],[-1,-2],[-2,1],[-1,2],[0,2],[1,9],[-1,0]],[[5237,5458],[1,4],[1,6],[3,6],[2,9],[2,16],[1,9],[1,9],[1,8],[2,5],[5,10],[4,8],[2,3],[1,3],[2,2],[3,4],[2,7],[1,6],[1,2],[2,1],[4,6],[3,5],[1,-2],[0,-3],[1,-1],[2,-1],[4,0],[2,1],[1,2],[1,6],[0,1],[1,1],[4,-5],[3,-6],[3,-6],[1,-2],[1,-2],[1,-11],[1,-3],[1,-1],[3,0],[2,2],[2,3],[2,4],[2,3],[0,3],[1,9],[0,2],[2,3],[4,6],[2,4],[0,1],[-2,4],[-1,4],[2,4],[1,3],[4,11],[0,4],[1,4],[3,12],[2,17],[0,3],[2,8],[3,10],[5,2],[2,2],[2,5],[2,4],[0,4],[1,7],[1,9],[0,8],[2,7],[2,3],[4,3],[1,2],[1,4],[0,10],[0,6],[1,2],[0,5],[4,8],[2,12],[1,13],[5,15],[5,15],[3,5],[2,1],[2,1],[2,1],[6,7],[2,3],[2,3],[0,2],[1,3],[-1,8],[1,6],[1,9],[0,7],[0,3],[-1,3],[-1,1],[-1,4],[-3,3],[-4,1],[-2,1],[-1,4],[0,2],[0,2],[0,5],[-3,27]],[[5390,5937],[5,0],[6,-3],[2,-3],[0,-9],[3,-5],[3,-4],[3,-9],[1,-14],[2,-8],[0,-1],[3,-11],[0,-4],[1,-7],[-1,-5],[2,-5],[-2,-10],[-1,-6],[0,-9],[1,-15],[2,-12],[2,-9],[2,-8],[3,-8],[4,-7],[3,-5],[-3,-3],[-6,0],[-4,2],[-1,0],[-2,-1],[-6,-2],[-7,1],[-6,2],[-4,0],[-3,-5],[-2,-7],[-2,-5],[0,-6],[2,-3],[3,-7],[3,-7],[2,-5],[5,-10],[6,-10],[1,-1],[1,-2],[1,0],[3,-6],[4,-8],[4,-14],[3,-14],[2,-13],[2,-2],[1,-2],[1,-3],[-1,-4],[0,-3],[-2,-5]],[[5761,5478],[1,-4],[1,-4],[5,-7],[1,-4],[2,-4],[0,-4],[2,-2],[2,-2],[2,-2],[1,-3],[1,-3],[4,-5],[1,0],[2,0],[1,-1],[2,0],[3,3],[3,4],[2,3],[6,-1],[4,-2],[2,-3],[2,0],[5,6],[2,6],[2,2],[4,-3],[3,-6],[2,-9],[2,-3],[2,-6],[5,-11],[6,-5],[3,-3],[1,-3],[0,-4],[0,-4],[1,-1],[2,0],[1,1],[2,-1],[1,-3],[0,-3],[1,-2]],[[5856,5385],[2,-2],[0,-3],[-1,-4],[-1,-3],[-2,-7],[0,-7],[1,-2],[1,-2],[0,-2],[0,-3],[0,-2],[-2,-10],[-1,-8],[0,-5],[3,-3],[3,0],[2,-2],[1,-3],[1,-1],[1,0],[1,-1],[1,-3],[1,-2],[1,-3],[0,-3],[0,-2],[-3,-7],[-6,-14],[-13,-26],[-4,-3],[-3,-5],[-1,-7],[-4,-6],[-3,-3],[0,-2],[0,-6],[0,-10],[-1,-5],[-2,-9],[-1,-6],[-1,-1],[-1,-3],[-1,-9],[0,-3],[-1,-19],[0,-5],[-1,-9],[0,-5],[-1,-6],[0,-5],[0,-9],[0,-13],[0,-2]],[[5821,5104],[-1,-1],[-2,-4],[-2,-2],[-1,-1],[-3,-6],[-2,-5],[-1,-6],[0,-2],[0,-8],[0,-8],[0,-4],[-1,-2],[-3,-4],[-2,-4],[-1,-1],[-1,-3],[1,-6],[0,-5],[1,-3],[2,-2]],[[5816,4928],[0,-3],[-1,-10],[-1,-10],[0,-3],[1,-5],[2,-11],[1,-8],[1,-5],[1,-6],[1,-9],[1,-4],[0,-3],[-3,-11],[-1,-3],[1,-9],[1,-8],[1,-5],[4,-12],[2,-5],[5,-6],[4,-6],[1,-4],[2,-4],[2,-9],[2,-8],[1,-7],[2,-10],[2,-8],[3,-11],[2,-8],[1,-5]],[[5854,4712],[-5,-2],[-7,-2],[-8,-2],[-8,-3],[-8,-2],[-7,-3],[-7,-2],[-2,-1],[1,-6],[0,-6],[-2,-5],[-2,-6],[-1,-3],[-2,-4],[-2,-4],[-3,-5],[-3,-4],[0,-2],[4,-14],[2,-10],[1,-8],[0,-6],[0,-10],[-1,-12],[0,-5],[1,-9],[0,-7],[-3,-7],[0,-8],[-2,-10],[-2,-14],[-1,-8],[1,-4],[1,-4],[0,-4],[2,-7],[1,-3],[1,-2],[6,-8],[2,-4],[3,-8],[3,-5],[3,-2],[5,-2],[2,-1],[1,1],[1,1],[0,4],[0,3],[0,2],[2,2],[3,0],[2,2],[1,1],[0,-9],[0,-8],[0,-10],[0,-12],[0,-10],[0,-10],[0,-11],[0,-2],[0,-2],[-2,-1],[-2,2],[0,3],[-1,4],[0,2],[-2,1],[-2,-1],[-2,-4],[-4,-2],[-1,-2],[-3,0],[-3,2],[-2,3],[0,6],[-2,5],[-2,8],[-2,3],[-1,4],[-2,0],[-1,1],[-2,6],[-1,7],[0,2],[-1,4],[-2,2],[-3,3],[-5,3],[-6,5],[-3,0],[-3,1],[-2,3],[-1,1],[-1,7],[-2,8],[-5,9],[-1,10],[-1,2],[-2,-1],[-1,-1],[-1,-3],[-1,-9],[-1,-5],[0,-1],[-2,-1],[-1,-1],[-3,-1],[-4,0],[-4,2],[-3,1],[-7,1],[-2,1],[-2,2],[-2,2],[-7,4],[-3,0],[-1,3],[-2,1],[-1,3],[-1,4],[-1,9],[0,4],[1,6],[-1,1],[-1,0],[-2,-2],[-3,-1],[-6,-2],[-1,-1],[-3,-1],[-1,-1],[-4,-5],[-2,-1],[-2,2],[-2,3],[2,3],[0,4],[-1,7],[-1,3],[-4,2],[-1,1],[-1,4],[-1,3],[-2,1],[-1,1]],[[5362,4846],[-1,2],[-4,-1],[-2,-2],[-3,-5],[-5,-2],[-2,0],[-1,1],[-2,5],[-3,5],[0,3]],[[5363,4917],[0,2],[1,0],[1,-1],[0,-2],[2,-3],[2,-4],[2,-3],[1,-1],[2,2],[2,3],[3,2],[1,2],[0,4],[0,4],[0,5],[1,1],[1,0],[2,-1],[1,-2],[2,0],[1,2],[2,2],[2,1],[3,3],[2,3],[1,0],[2,-4],[1,-3],[0,-1],[-1,-4],[-1,-4],[1,-6],[0,-5],[0,-3],[1,-2],[1,0],[2,0],[2,-2],[2,1],[2,2],[4,8],[5,14],[5,9],[3,3],[2,5],[2,4],[2,4],[4,2],[3,3],[4,10],[4,17],[1,16],[1,9],[0,33],[-1,11],[1,5],[2,4],[4,9],[3,7],[2,8],[5,19],[1,6],[1,2],[3,5],[4,4],[4,4],[8,13],[6,13],[-1,16],[1,13],[3,16],[1,18],[-1,18],[1,15],[3,18],[1,6],[0,11],[0,17],[4,23],[4,14],[4,15],[2,10],[2,12],[-1,10]],[[5333,4896],[0,1],[-1,1],[-2,6],[-2,6],[-1,3],[0,1],[0,7],[-3,7],[-8,14],[-1,4],[-6,12]],[[5309,4958],[1,9],[2,4],[1,3],[6,7],[1,0],[4,-9],[1,-1],[2,0],[2,0],[0,2],[1,2],[-2,3],[0,2],[1,3],[1,4],[1,4],[0,2],[-1,2],[-3,3],[-2,3],[-1,3],[1,3],[1,3],[0,2],[-1,3],[-1,3],[-1,1],[-3,1],[1,4],[1,6],[0,4],[-1,12],[0,2],[1,1],[2,-1],[1,-2],[5,2],[1,1],[2,-2],[2,-2],[10,5],[0,4],[1,5],[0,3],[0,2],[-1,2],[0,3],[0,4],[1,1],[3,5],[1,-1],[3,-2],[2,-3],[2,-8],[1,-7],[2,-7],[5,-4],[6,-2],[2,1],[5,7],[2,5],[1,3],[1,-2],[2,-7],[1,-2],[0,-3],[0,-3],[0,-2],[3,-2],[3,2],[1,3],[2,3],[0,3],[-1,2],[0,3],[1,2],[1,6],[0,5],[1,2],[2,2],[1,2],[1,10],[0,4],[0,3],[1,4],[0,6],[-1,11],[0,7],[0,8],[1,10],[1,10],[0,3],[-2,3],[-2,3],[-4,2],[-2,4],[-1,4],[-1,1],[-4,2],[-2,2],[1,7],[0,9],[0,7],[1,5],[1,4],[2,4],[1,5],[1,2],[4,1],[1,2],[1,2],[1,3],[1,4],[1,4],[1,2],[-1,3],[-1,6],[-1,5],[-1,1],[-2,12],[-2,3],[-3,1],[-6,2],[-3,-3],[-6,-3],[-4,-3],[-3,-2],[-1,1],[-1,1],[1,2],[0,4],[0,5],[-1,4],[-1,7],[0,8],[1,7],[3,10],[0,4]],[[563,3960],[-1,0],[-1,0],[-1,1],[0,2],[1,0],[1,0],[1,-1],[0,-2]],[[2830,5330],[-1,-1],[-1,2],[-1,3],[1,2],[1,0],[1,-2],[0,-4]],[[3019,5867],[-1,-1],[-2,-1],[-3,-3],[-6,-3],[-6,-3],[-2,-4],[-6,-23],[-6,-5],[-2,-4],[-1,-4],[-3,-8],[-2,-6],[-3,-14],[-2,-17],[-1,-10],[-1,-13],[-2,-7],[-2,-7],[-2,-6],[-2,-7],[-2,-6],[0,-2],[1,-1],[4,1],[1,2],[2,2],[2,-1],[1,-6],[2,-1],[1,1],[2,-2],[2,-15],[1,-12],[4,-8],[3,-6],[1,-6],[1,-8],[0,-3],[-1,-3],[-2,-4],[0,-9],[0,-3],[-1,-9],[1,-5],[0,-4],[2,-2],[2,-1],[3,-2],[1,-7],[2,-8],[3,-4],[3,-3],[2,1],[5,2],[5,0],[6,-3],[3,0],[3,1],[6,4],[2,1],[2,0],[3,-3],[2,-2],[2,-2],[4,-1],[2,0],[2,0],[1,-1],[5,-13],[5,-12],[4,-10],[4,-11],[2,1],[1,-1],[2,-2],[2,1],[3,4],[4,1],[5,-3],[8,0],[9,3],[6,2],[2,3],[3,0],[5,-3],[2,-3],[0,-4],[1,-5],[-1,-6],[-2,-5],[-2,-7],[0,-9],[-2,-6],[-2,-5],[-1,-6],[0,-8],[0,-11],[-1,-15],[0,-10],[1,-3],[0,-4],[0,-5],[1,-5],[1,-7],[2,-13],[2,-5],[1,-2],[2,-3],[4,-13],[1,-2],[0,-3],[-1,-2],[0,-1],[-5,-8],[-9,-17],[0,-2],[0,-3],[2,2],[3,-2],[1,0],[1,-2],[1,-4],[1,-1],[1,-2],[3,-5],[2,-5],[2,-2],[1,-3],[0,-3],[0,-3],[1,-8],[1,-2],[0,-3],[0,-3],[1,-3],[1,-7],[2,-8],[0,-5],[1,-2],[0,-6],[2,-6],[-1,-4],[1,-4]],[[3056,4940],[-1,4],[-2,4],[-2,3],[-1,3],[-1,6],[-2,2],[-1,2],[-1,0],[-1,-2],[-2,-1],[-1,0],[-5,5],[-1,0],[3,10],[6,18],[3,12],[4,13],[2,6],[0,2],[0,1],[0,3],[-2,1],[-3,2],[-1,3],[-2,1],[-1,2],[-3,3],[-2,2],[-2,0],[-1,4],[-6,7],[-2,1],[-1,-1],[-3,-2],[-2,-3],[-3,-2],[-3,0],[-1,3],[-1,1],[-2,3],[-3,2],[-2,2],[-2,-1],[-2,-4],[-1,-3],[-2,-2],[-2,0],[-2,-3],[-2,-1],[-3,-1],[-2,-1],[-3,2],[-3,2],[-1,0],[-1,0],[-1,-2],[-3,-1],[-2,0],[-1,1],[-2,3],[-2,2],[-2,2],[-1,4],[0,3],[1,4],[0,4],[-1,7],[-1,3],[0,3],[-1,1],[-3,-1],[-2,3],[-2,2],[-1,3],[1,6],[-1,5],[-1,3],[-1,5],[-2,4],[-2,2],[-1,0],[-2,1],[-2,4],[-1,2],[-2,4],[-4,1],[-2,2],[-1,2],[-1,5],[0,2],[-1,3],[0,4],[-1,6],[-2,4],[-1,3],[-1,2],[-2,3],[-2,2],[-2,3],[-1,3],[0,2],[-1,0],[-2,0],[-1,1],[-2,2],[-1,2],[-2,4],[-2,0],[-1,0],[-2,-3]],[[2908,5178],[-5,4],[-4,5],[-4,2],[-3,3],[-3,6],[-1,4],[-1,2],[-6,5],[-1,1],[-2,-3],[-1,-1],[0,-5],[0,-2],[-2,-2],[-3,1],[-2,1],[-2,0],[0,-1],[-1,0],[-1,0],[-3,1],[-2,2],[-3,3],[-2,0],[-3,1],[-3,1],[-1,2],[-1,12],[-1,1],[-1,1],[-2,2],[-1,1],[-1,4],[-1,3],[-3,-1],[-6,5],[-4,4],[-4,4],[-5,9],[-2,2],[-3,3],[-1,4],[-3,4],[-1,2]],[[2809,5268],[-1,4],[-3,5],[1,8],[5,5],[6,-4],[1,9],[-2,7],[0,15],[1,3],[1,3],[2,3],[1,1],[3,-1],[1,2],[5,-1],[1,1],[1,2],[1,2],[2,3],[1,4],[1,2],[1,-1],[0,2],[1,2],[3,6],[0,2],[-1,5],[1,2],[1,1],[2,1],[1,5],[2,4],[1,6],[2,1],[1,7],[2,6],[5,19],[-2,0],[-1,-3],[-1,1],[-1,1],[0,9],[-1,1],[-2,-7],[-2,7],[0,4],[1,4],[-1,2],[-3,-2],[1,3],[1,3],[1,2],[2,3],[1,5],[0,6],[1,8],[-1,3],[-1,3],[0,14],[0,8],[-1,6],[0,6],[-4,7],[6,8],[2,6],[-3,12],[-3,11],[0,6],[1,-1],[1,0],[1,13],[0,5],[-2,6],[-3,0],[-2,9],[-1,1],[-1,6],[-3,10],[-3,5]],[[2836,5600],[2,12],[2,3],[0,3],[-1,7],[1,2],[0,1],[1,-1],[2,-3],[1,-4],[1,-2],[1,2],[5,8],[0,2],[0,5],[2,4],[2,2],[0,2],[0,4],[-2,8],[-2,5],[-1,5],[0,4],[-2,4],[0,4],[2,5],[0,1]],[[2850,5683],[1,-2],[3,-8],[3,-5],[4,-9],[2,-6],[1,-1],[1,-2],[-1,-2],[-1,-1],[0,-4],[1,-2],[1,-1],[2,1],[1,4],[-1,17],[-1,9],[-2,3],[-1,4],[1,2],[2,1],[3,4],[12,17],[4,15],[3,6],[3,4],[4,-1],[4,2],[1,5],[-1,7],[-2,4],[2,6],[1,9],[0,8],[1,5],[0,1],[-2,-3],[-2,-2],[1,3],[3,8],[2,11],[1,5],[5,7],[0,3],[4,5],[6,11],[2,3],[11,-7],[3,0],[-1,-1],[-1,-1],[-3,-1],[0,-5],[1,-4],[2,-1],[1,3],[2,8],[2,8],[1,10],[1,3],[3,1],[4,-2],[3,-2],[3,0],[10,1],[17,24],[7,6],[5,5],[3,9],[1,8],[2,3],[3,0],[1,2],[0,2],[6,6],[3,1],[3,0],[6,-6],[3,-10],[1,-6],[-4,-8],[-1,-3]],[[6216,4475],[2,-4],[-6,2],[-1,3],[0,2],[2,0],[3,-3]],[[6235,4488],[1,-8],[0,-6],[0,-2],[-2,1],[-2,5],[-4,5],[2,0],[1,0],[1,0],[1,3],[0,1],[1,2],[1,-1]],[[6207,4498],[-1,0],[-2,3],[-2,1],[-2,5],[1,18],[1,3],[0,1],[1,0],[2,-2],[-1,-12],[2,-8],[1,-6],[0,-3]],[[4324,6039],[-2,-2],[-1,1],[-2,3],[0,3],[0,3],[3,3],[2,-1],[1,-5],[-1,-5]],[[4356,6056],[-1,-1],[-1,3],[0,4],[0,1],[1,3],[2,0],[0,-3],[0,-6],[-1,-1]],[[4348,6048],[-1,-5],[-4,0],[-2,3],[-2,6],[0,5],[1,5],[0,4],[0,1],[1,-1],[0,-3],[4,-6],[1,-1],[2,-8]],[[4363,6119],[2,-1],[1,0],[2,0],[1,-3],[1,-3],[-1,-4],[-3,-3],[-2,0],[-2,3],[1,6],[0,5]],[[4330,6141],[2,-1],[0,-2],[-2,0],[-4,2],[-1,-1],[-1,-5],[-2,7],[0,3],[3,-1],[5,-2]],[[4364,6143],[-1,-3],[-1,5],[-1,1],[0,6],[2,2],[0,-6],[1,-5]],[[4308,6152],[-2,-1],[-1,0],[-2,2],[0,3],[2,2],[2,0],[1,-4],[0,-2]],[[4300,6160],[-2,-1],[-1,0],[-1,5],[0,3],[0,1],[6,6],[2,-1],[2,-5],[-1,-2],[-5,-6]],[[2676,5813],[1,-3],[1,-3],[0,-5],[4,-15],[3,-9],[6,-16],[2,-3],[5,-12],[1,-3],[1,-3],[5,-3],[1,-3]],[[2706,5735],[0,-1],[0,-1],[-1,-1],[-1,-1],[-2,3],[-2,2],[-1,-1],[-1,-3],[-1,-2],[-1,-1],[0,-1],[0,-11],[0,-11],[1,-1],[3,-3],[1,-3],[1,-2],[-1,-1],[-2,-2],[-2,-3],[-1,-4],[2,-6],[1,-4],[-1,-4],[0,-2],[-4,-5],[-1,-2],[1,-1],[2,-4],[1,-3],[0,-4],[1,-3]],[[2698,5649],[-2,6],[-3,6],[-2,4],[0,9],[-1,4],[-4,5],[-3,3],[-2,-1],[1,-5],[4,-6],[0,-3],[0,-3],[-2,0],[-2,2],[-3,0],[-2,2],[-3,8],[2,7],[1,4],[0,9],[-1,4],[-2,7],[-5,7],[-6,6],[-3,5],[-7,3],[-3,3],[-2,4],[0,4],[1,5],[-2,6],[-9,12],[-5,5],[-1,3],[-1,1],[1,-9],[2,-5],[6,-5],[1,-3],[1,-4],[-3,-7],[-2,-1],[-1,-4],[-1,-1],[-1,2],[-4,11],[-9,5],[-1,3],[-3,10],[-2,10],[1,6],[3,9],[1,4],[0,3],[0,4],[-1,2],[-4,4],[-2,2],[1,2],[4,4],[0,3],[0,1]],[[2618,5821],[1,0],[0,1],[0,1],[1,3],[1,2],[1,0],[2,-1],[4,-3],[6,-4],[7,-6],[3,4],[3,2],[2,0],[4,-3],[2,-1],[2,0],[2,-4],[2,-4],[0,-2],[1,-1],[2,-1],[5,-2],[3,1],[2,2],[2,3],[0,5]],[[2706,6426],[-2,-3],[-6,-4],[-3,0],[-3,1],[-2,4],[-1,4],[0,1],[2,-3],[2,-1],[1,1],[1,1],[-3,12],[0,2],[2,7],[7,-2],[1,-1],[1,-4],[1,-3],[2,-9],[0,-3]],[[2842,6448],[-1,-2],[-1,3],[-1,0],[-1,1],[-2,3],[-1,3],[2,0],[2,0],[4,-2],[0,-3],[-1,-3]],[[2836,6458],[-1,0],[-2,3],[-1,2],[1,2],[0,3],[1,-3],[2,-2],[1,-3],[-1,-2]],[[2832,6467],[0,-1],[-2,3],[-2,1],[-1,3],[-1,1],[-1,1],[2,1],[2,0],[1,-3],[1,-4],[1,-2]],[[2816,6483],[3,-1],[2,0],[1,0],[1,0],[2,-5],[-1,0],[-2,0],[-1,0],[-3,1],[-2,1],[-2,1],[0,2],[2,1]],[[2796,6489],[0,-1],[-5,4],[-2,4],[-1,1],[1,0],[6,-7],[1,-1]],[[2726,6518],[8,-3],[6,1],[2,2],[0,-2],[3,-4],[1,0],[4,2],[9,1],[1,-2],[2,-3],[3,-3],[2,-2],[3,0],[3,1],[2,-1],[4,-4],[1,0],[2,1],[0,-3],[4,-5],[4,-10],[3,-4],[2,-3],[3,-3],[2,-1],[8,1],[2,-1],[2,-1],[1,0],[1,0],[15,-15],[5,-8],[3,-4],[6,-6],[3,-1],[1,1],[0,1],[-2,3],[0,2],[2,-1],[4,-7],[2,-3],[2,-2],[2,-2],[-1,-2],[-2,0],[-3,1],[2,-5],[1,-3],[1,0],[2,3],[1,3],[5,-7],[2,-4],[0,-2],[0,-2],[2,2],[1,0],[1,-1],[2,-3],[2,-1],[3,0],[5,-3],[6,-5],[4,-1],[5,0],[3,-3],[1,-4],[-1,-3],[-1,-2],[2,-4],[-4,-1],[-1,-3],[0,-2],[1,-1],[3,1],[3,-1],[5,-1],[3,1],[7,-2],[3,-2],[4,-4],[2,-3],[4,-8],[3,-3],[4,-1],[1,1],[1,-1],[1,-1],[0,-4],[0,-4],[-2,-2],[-1,-3],[-4,0],[-6,-1],[-6,-3],[-3,-3],[-2,-1],[-3,-2],[0,1],[0,2],[-1,3],[-1,-3],[-1,-2],[-2,-1],[-7,-1],[-3,3],[-3,1],[-11,2],[-2,0],[-8,-2],[-7,-1],[-3,-1],[-3,-1],[-6,0],[-7,-2],[-7,-1],[4,13],[10,13],[2,3],[1,3],[0,3],[0,2],[-2,4],[-1,3],[-1,2],[-3,1],[-3,1],[-4,1],[-7,1],[-4,0],[-3,3],[-6,9],[-2,3],[-2,2],[-1,2],[-1,14],[-1,7],[-2,6],[-2,5],[-3,1],[-10,-4],[-2,1],[-3,1],[-15,9],[-6,5],[-3,3],[-2,3],[-2,6],[-3,5],[0,-2],[0,-1],[-13,-1],[-2,1],[-2,2],[-1,2],[0,4],[-1,3],[-1,-3],[0,-4],[-2,-2],[-2,0],[-3,5],[-10,0],[-1,1],[-3,5],[-3,5],[3,2],[6,3],[1,2],[1,2],[-1,3],[-1,2],[-1,2],[-2,1],[-1,0],[-24,1],[-1,-2],[-2,-4],[-4,-4],[-3,-5],[-1,-3],[-1,-2],[-3,-3],[-2,-4],[-3,-2],[-2,1],[-2,0],[-1,-1],[-1,-1],[-6,0],[-1,-1],[-1,-4],[-1,-6],[0,-2],[-3,-1],[-3,-2],[-6,-6],[-2,-1],[1,5],[-1,4],[-1,0],[-2,-1],[-2,-1],[-2,-3],[-2,-1],[-1,2],[0,2],[10,8],[1,0],[1,0],[2,0],[1,2],[-1,11],[0,7],[3,5],[4,9],[2,2],[22,18],[2,1],[14,3],[3,1],[6,5],[7,3],[7,-2]],[[3090,5878],[-2,0],[-5,5],[-4,9],[0,5],[1,-1],[1,-1],[2,-7],[5,-4],[2,-6]],[[2739,6298],[1,-1],[1,1],[1,1],[4,-1],[1,-2],[-4,0],[-1,-2],[-1,0],[-3,0],[0,6],[1,0],[0,-2]],[[2778,6319],[-1,0],[-2,-2],[-1,0],[1,1],[0,1],[1,0],[1,1],[1,0],[0,-1]],[[2782,6319],[-1,-1],[-1,1],[2,2],[1,1],[1,0],[1,0],[0,-1],[-3,-2]],[[5944,7204],[-1,-1],[-2,2],[-1,0],[-1,-1],[-1,-1],[-1,-1],[-1,0],[-1,-1],[-2,0],[-2,1],[-2,-2],[0,6],[-1,2],[-1,1],[-2,0],[-2,0],[-2,1],[-3,-2],[-2,-2],[-2,-1],[-2,0],[-2,1],[-2,2],[0,2]],[[5908,7210],[2,-1],[3,1],[1,6],[0,6],[6,-2],[5,-1],[4,0],[4,1],[13,7],[3,4],[2,2],[4,3],[4,2],[-2,-4],[-15,-17],[-1,-6],[1,-3],[2,-4]],[[5944,7204],[1,-2],[0,-3],[-3,-1],[-3,0],[-2,0],[-1,0],[-6,-9],[-2,-4],[-4,-2],[-3,-1],[-2,0],[-1,-1],[-1,-2],[0,-2],[-1,-2],[-2,0],[0,4],[-2,1],[-3,-1],[-1,1],[-6,3],[-1,1],[-1,3],[-3,10],[0,8],[2,-2],[2,2],[3,4],[2,1],[2,0]],[[5411,8113],[2,0],[3,2],[0,2],[0,5],[4,-1],[3,-2],[1,-4],[1,-3],[1,-2],[1,0],[2,-1],[5,-2],[2,-1],[3,-1],[2,-2],[1,-1],[1,-2],[1,-1],[2,1],[6,1],[2,-1],[1,-3],[1,0],[-1,-2],[-1,-2],[-2,-1],[-1,-2],[-1,-2],[0,-2],[2,-1],[1,0],[1,-1],[3,-6],[3,-7],[2,-1],[1,-1],[1,1],[2,3],[1,1],[2,1],[2,2],[0,2],[-2,5],[-1,4],[3,0],[5,-2],[7,-8],[2,0],[2,1],[3,1],[1,1],[1,0],[0,-4],[-1,-2],[-3,-2],[0,-1],[1,-2],[2,0],[1,-3],[2,-3],[1,-1],[1,-1],[3,2],[1,1],[0,1],[1,0],[1,-2],[0,-1],[3,-1],[2,-2],[1,-1],[1,1],[5,-2],[1,-1],[0,-2],[0,-2],[1,-3],[6,-9],[0,-4],[1,-1]],[[5523,8036],[-1,-1],[-2,0],[-2,-1],[-2,0],[-2,-1],[-1,-3],[-2,-1],[-1,-2],[0,-2],[-6,-4],[-1,-2],[0,-3],[-1,-3],[0,-3],[-1,-2],[-3,-1],[-1,-1],[-1,-2],[-1,-2],[-2,-2],[-4,-3],[-4,-1],[-5,1],[-3,1],[-2,-1],[-2,-4],[-2,-5],[-1,-5]],[[5383,7993],[-1,3],[-2,3],[-4,5],[-3,0],[-1,1],[-1,2],[-1,3],[-1,2],[-2,1],[-3,2],[-3,6],[-3,4],[-3,0],[-1,2],[-2,3],[-2,3],[-2,6],[-1,4],[-2,2],[-1,2],[0,2],[1,3],[1,2],[1,1],[0,2],[0,1],[-1,3],[-3,3],[-3,2],[-1,3],[-1,3],[0,2],[-2,2],[-1,3],[0,2],[1,1],[1,0],[1,-2],[1,-2],[2,-4],[0,2],[2,3],[2,5],[3,2],[2,1],[2,0],[2,2],[3,-1],[2,-1],[1,1],[0,2],[1,2],[5,1],[1,4],[1,0],[1,0],[1,2],[1,1],[1,-1],[1,-1],[1,1],[1,5],[1,0],[4,1],[6,3],[2,2],[3,1],[3,2],[5,2],[0,1],[-2,3],[-1,1],[-1,1],[1,2],[1,0],[2,0],[3,-1],[2,-1],[0,-2],[1,-2],[1,-1],[-1,-3],[2,-1],[1,-1],[2,0],[1,1],[0,1]],[[5394,8287],[-1,0],[-3,-1],[-4,1],[0,4],[0,3],[-1,2],[-1,2],[-1,1],[1,2],[5,-5],[5,-5]],[[5394,8291],[0,-2],[0,-2]],[[5313,8318],[-4,0],[-2,2],[-2,1],[1,3],[1,1],[5,-2],[1,-4],[0,-1]],[[5380,8316],[1,-4],[-1,-2],[-3,4],[-3,0],[-2,-6],[-1,0],[-5,5],[-1,2],[0,2],[1,6],[-1,2],[2,3],[0,3],[3,3],[2,0],[1,-2],[1,-2],[4,-3],[1,-1],[0,-1],[-2,-3],[0,-1],[0,-2],[3,-3]],[[5238,8335],[-1,-1],[-3,0],[-1,1],[0,2],[2,1],[1,0],[2,-1],[0,-2]],[[5270,8342],[0,-1],[4,-2],[2,-2],[2,-4],[0,-5],[-2,-4],[-2,-3],[7,1],[1,-2],[1,-2],[4,1],[11,-7],[6,4],[1,0],[2,-6],[-2,-5],[-5,-7],[1,-3],[2,-1],[5,1],[8,-4],[2,1],[6,9],[3,1],[9,2],[1,3],[4,3],[2,4],[6,7],[5,-1],[4,-2],[3,0],[4,-8],[8,-8],[8,1],[2,-8],[2,-9],[2,-3],[2,-2],[6,-2],[1,0]],[[5396,8279],[0,-2],[0,-4],[1,-4],[3,-16],[0,-4],[0,-1],[-1,-5],[-3,-5],[-2,-3],[-2,-2],[0,-3],[3,-6],[8,-8],[3,-7],[-2,-5],[0,-4],[0,-3],[1,-2],[2,-2],[1,-2],[0,-3],[0,-3],[1,-1],[0,-1],[-1,-2],[0,-5],[-1,-3],[-2,-4],[1,-3],[1,-4],[1,-3],[1,-2],[-1,-4],[0,-2],[6,-3],[0,-2],[1,-3],[2,-7],[-2,-9],[-1,-5],[-3,-8],[0,-1]],[[5211,7925],[-1,1],[-1,4],[0,5],[1,8],[1,6],[-1,3],[1,6],[3,7],[1,7],[1,8],[1,5],[3,4],[5,10],[1,1],[-1,5],[-1,0],[-2,2],[-6,2],[-5,1],[-2,1],[-3,4],[-1,0],[-2,-1],[-4,-1],[-2,0],[-1,0],[-1,0],[-1,3],[-1,1],[-2,1],[-1,0],[-1,-2],[-1,-1],[-1,0],[-4,8],[-1,2],[0,1],[-1,3],[-2,3],[-2,1],[-1,-1]],[[5176,8032],[0,4],[1,5],[0,2],[2,2],[1,2],[0,3],[0,2],[-2,1],[-3,1],[-2,2],[-1,3],[-2,3],[-1,4],[0,3],[0,2]],[[5166,8107],[2,9],[-2,2],[-1,2],[-2,0],[-1,2],[0,1],[0,1],[2,0],[1,1],[5,5],[0,1],[-1,0],[-1,1],[0,1],[0,1],[3,8],[1,3],[0,2],[0,2],[-2,4],[-1,3],[0,2],[-1,1],[-3,6],[0,3],[1,1],[3,2],[2,1],[3,-2],[2,-1],[2,2],[3,0],[6,3],[1,1],[0,2],[0,1],[-2,3],[0,1],[0,2],[1,1],[1,0],[2,2],[3,4],[1,3],[1,4],[0,3],[-1,2],[-1,1],[-1,0],[-3,0],[-2,2],[-1,2],[-1,1],[1,2],[0,1],[0,1],[0,2],[1,0],[7,0],[1,1],[0,6],[2,8],[2,5],[0,1],[0,11],[0,6]],[[5199,8253],[-1,2],[-3,3],[1,6],[1,5],[3,5],[2,2],[9,1],[11,-1],[4,-8],[-1,-5],[2,-2],[2,1],[0,4],[1,4],[1,1],[3,-3],[1,-2],[0,-7],[2,10],[-1,6],[0,7],[2,3],[1,2],[8,-2],[8,1],[3,-3],[8,-12],[2,-2],[3,-1],[-4,3],[-9,15],[-3,2],[-4,0],[-2,2],[-2,2],[0,2],[0,15],[-2,2],[-2,1],[-1,-1],[-2,0],[-1,4],[1,2],[5,2],[3,2],[0,4],[-2,3],[-2,6],[-3,6],[-1,6]],[[5240,8346],[6,0],[1,0],[8,-3],[2,-2],[2,0],[4,2],[4,0],[1,-1],[2,0]],[[5230,8339],[0,-1],[0,8],[3,9],[1,0],[-1,-2],[0,-2],[-1,-3],[0,-2],[7,-1],[-1,-1],[-7,-1],[-1,-4]],[[6201,5846],[-3,-8],[-3,-9],[-3,-12]],[[6192,5817],[-2,0],[-2,1],[-1,2],[-3,2],[-2,0],[-3,-2],[-4,-2],[-4,-1],[-3,-1],[-3,-2],[-2,1],[-3,1],[0,12],[0,13],[0,10],[0,6],[1,2],[4,8],[1,3],[4,13],[4,11],[3,8]],[[6177,5902],[0,1],[2,2],[6,-8],[1,0],[1,2],[2,9],[1,3],[1,0],[3,2],[3,3]],[[6197,5916],[0,-3],[5,-11],[2,-6],[1,-10],[-1,-6],[-1,-3],[-2,-4],[-6,-8],[-7,-5],[-4,-10],[-3,0],[0,-4],[1,0],[2,1],[4,3],[3,1],[4,0],[3,-1],[3,-4]],[[3297,6062],[-2,-1],[-1,10],[-2,7],[0,5],[1,1],[3,-3],[2,-3],[0,-9],[-1,-7]],[[5315,8345],[5,-3],[3,0],[3,-1],[0,-3],[0,-5],[-2,-1],[-3,0],[-3,-2],[-12,9],[0,7],[1,2],[5,1],[3,-4]],[[5291,8343],[-2,-1],[-2,2],[-4,4],[0,2],[2,-1],[2,-3],[2,0],[2,-2],[0,-1]],[[5348,8350],[-1,-1],[-4,1],[-5,-4],[-2,1],[1,2],[0,1],[2,1],[1,2],[0,2],[1,-1],[3,0],[2,-1],[1,-1],[1,-2]],[[5279,8345],[-3,-1],[-1,2],[-3,0],[-1,9],[0,1],[2,-1],[4,-4],[2,-5],[0,-1]],[[5298,8337],[-2,0],[-1,5],[0,1],[1,3],[2,4],[3,5],[2,6],[1,0],[-1,-6],[-4,-15],[-1,-3]],[[5419,8353],[-1,-1],[-5,2],[-6,4],[1,7],[2,4],[10,-9],[0,-3],[-1,-4]],[[5295,8387],[1,-3],[2,-7],[2,-7],[-1,-3],[1,-4],[-1,-4],[-4,-4],[-5,0],[-6,2],[-7,4],[-1,3],[-1,1],[-2,7],[0,9],[4,2],[8,4],[2,-1],[2,-2],[2,0],[4,3]],[[5351,8386],[-2,-2],[-1,0],[-1,3],[2,2],[0,2],[1,0],[1,-2],[0,-3]],[[5294,8397],[0,-1],[-2,1],[0,4],[0,3],[0,3],[0,2],[3,-5],[1,-2],[-1,-2],[-1,-3]],[[5349,8397],[0,-6],[-1,-2],[-1,-1],[-3,-1],[-2,-1],[-2,-3],[-1,-4],[1,-3],[4,-2],[0,-6],[-2,-3],[-7,-2],[0,-7],[0,-6],[0,-4],[-1,-5],[-5,-2],[-3,8],[0,3],[-1,4],[-1,3],[-1,5],[-5,2],[-2,0],[-2,-1],[-1,0],[-3,8],[0,8],[-1,4],[-1,1],[0,2],[-1,2],[-2,1],[-1,4],[2,1],[5,0],[2,0],[1,1],[4,7],[0,2],[0,2],[4,1],[2,-3],[0,-5],[0,-5],[3,-2],[1,0],[1,4],[1,2],[1,1],[0,4],[-1,3],[-1,1],[5,5],[5,4],[3,0],[3,-1],[2,-1],[2,-1],[1,-2],[-2,-4],[-1,-2],[2,-8]],[[5306,8481],[-1,-1],[-3,2],[1,3],[4,1],[3,0],[-3,-3],[-1,-2]],[[5240,8346],[0,5],[-1,3],[-1,5],[2,2],[0,10],[-1,5],[-8,5],[-6,5],[2,18],[0,4],[-2,9],[0,11],[1,16],[2,1],[2,0],[5,-3],[2,0],[2,-3],[1,-1],[2,3],[0,4],[4,7],[3,2],[2,1],[2,-2],[2,-3],[0,6],[2,12],[-4,1],[-4,-1],[-3,-8],[-3,-9],[-5,-1],[-3,-2],[-4,2],[-2,3],[0,3],[1,2],[4,8],[5,7],[5,0],[4,3],[2,0],[8,-1],[4,2],[3,3],[7,14],[4,6],[8,2],[8,7],[2,0],[-3,-5],[-1,-2],[0,-3],[2,-6],[0,-4],[0,-8],[-3,-4],[-2,-9],[-2,-1],[0,-10],[0,-3],[0,-9],[3,-4],[3,-2],[10,0],[1,-1],[1,-3],[-1,-5],[-1,-4],[-3,-3],[-3,-2],[-3,0],[-3,4],[-1,-1],[-2,-2],[-2,-12],[-2,-8],[0,-1],[-2,1],[-2,0],[-3,-2],[1,-1],[2,-3],[-1,-2],[-3,-2],[-2,-3],[-1,-2],[-3,-3],[-2,-4],[1,-4],[0,-4],[1,-5],[-1,-3],[-3,-6],[-2,-4],[3,0],[2,-1],[2,-1],[1,-2],[-1,-2],[1,-6]],[[3006,6223],[0,9],[1,4],[-1,4],[-3,5],[-2,5],[-1,5],[0,1],[3,0],[2,2],[2,5],[0,4],[0,3],[-1,4],[-1,3],[2,4],[2,5],[1,2],[0,1],[-3,6],[0,2],[1,5],[0,4],[-2,12],[0,2]],[[3006,6320],[1,1],[1,3],[1,3],[1,2],[2,1],[3,0],[5,-3],[1,0],[4,2],[4,2],[3,-2],[1,-2],[3,-3],[2,-1],[4,0],[1,0],[4,-6],[3,-2],[2,0],[3,2],[1,0],[2,-5],[1,-7],[1,-6],[2,-4],[12,2],[3,-3],[-1,-3],[-2,-1],[-5,0],[-3,0],[0,-3],[0,-2],[3,-1],[3,-1],[3,-2],[4,-1],[3,-1],[4,-1],[6,-5],[6,-11],[2,-3],[1,-3],[0,-4],[-3,-7],[-1,-3],[-2,-1],[-1,-3],[-1,-5],[-1,0],[-1,0],[-2,3],[-1,4],[-3,4],[-4,0],[-6,2],[-3,-1],[-3,0],[-4,1],[-3,0],[-4,-1],[-3,-3],[-2,-2],[-2,-3],[-1,-2],[-8,-2],[-2,3],[-3,4],[-3,0],[-4,-3],[-3,-1],[-1,-1],[-1,-2],[0,-5],[0,-3],[-5,-13],[-2,-9],[-2,-3],[-1,0],[-2,5],[-1,2],[-2,1],[-1,2],[0,4],[0,4],[-1,3],[-2,2]],[[5238,7311],[0,-3],[0,-3],[-2,-2],[-2,-2],[-2,-7],[-4,-5],[-1,-2],[1,-1],[2,-2],[1,-3],[0,-2],[-1,-11],[-1,-8],[0,-10],[0,-4],[1,-5],[1,-4],[0,-4],[-1,-10],[2,-6],[1,-6],[-3,-6],[-1,-6],[0,-9],[0,-6],[-2,-5],[-2,-4],[-2,-3],[-3,-3],[-3,-3],[-2,-9],[-6,-8],[-1,-2],[0,-6],[0,-9],[1,-6],[2,-10],[3,-11],[0,-5],[1,-2],[3,-4],[6,-4],[1,-2],[3,-8],[2,-13],[1,-9],[5,-7],[5,-6],[4,-6],[5,-6],[1,-2],[1,-13],[2,-13],[2,-14],[1,-14],[3,-17],[1,-10],[1,-11],[2,-14]],[[5264,6925],[-3,-3],[-3,-4],[2,-7],[5,-11],[2,-9],[1,-4],[2,-12],[2,-11],[0,-3],[1,-9],[-1,-23],[1,-30],[2,-15],[-3,-13],[-2,-13],[0,-6],[2,-10],[1,-8],[1,-4],[0,-12],[-1,-5],[-4,-6],[-6,-6],[-1,-6],[-1,-5],[1,-5],[4,-10],[5,-15],[6,-17],[1,-4],[0,-12],[3,-15],[2,-7],[1,-5],[2,-3],[2,-3],[1,0],[7,4],[12,-7],[11,-7],[1,-1],[2,-9],[4,-14],[3,-11],[3,-11]],[[5332,6538],[-14,-17],[-15,-18],[-14,-17],[-15,-18],[-14,-18],[-14,-17],[-15,-18],[-14,-17],[-10,-12],[-6,-10],[-7,-13],[-8,-13],[-5,-10],[-8,-13],[-3,-7],[-8,-14],[-3,-3],[-11,-4],[-10,-4],[-9,-4],[-6,-2],[-6,-3]],[[5117,6286],[-9,-3],[-6,-2],[-7,-3],[-1,0],[-1,-1],[-1,1],[-2,1],[-2,3],[-2,2],[0,3],[1,3],[1,4],[0,2],[1,2],[1,2],[0,2],[-1,3],[-1,5],[0,10],[0,3],[0,1],[-2,3],[-3,4],[-4,2],[-2,1],[-3,1],[-6,3],[-2,1],[-3,9],[-2,2],[-8,1],[-3,2],[-2,2],[-2,3],[-1,4],[0,4],[-1,2],[-9,9],[-2,3],[-1,3],[0,4],[0,5],[0,5],[-1,2],[-4,6],[-9,12],[-9,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-10,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-9,12],[-9,13],[-9,12],[-8,10],[-8,12]],[[4866,6624],[-7,8],[-6,8],[-7,8],[-4,6],[-5,6],[-6,6],[-5,7],[-5,6],[-5,6],[-5,7],[-6,6],[-5,6],[-5,7],[-5,6],[-6,7],[-5,6],[-5,6],[-5,7],[-5,6],[-6,6]],[[4758,6755],[0,12],[0,10]],[[4758,6777],[0,14],[0,12],[0,12],[0,9],[0,8],[0,4],[1,2],[3,3],[4,6],[2,3],[2,3],[7,9],[2,2],[7,10],[2,2],[4,1],[1,2],[2,4],[4,4],[2,2],[0,1],[1,0],[7,-1],[3,-1],[3,-1],[1,1],[1,1],[1,3],[1,4],[0,3],[0,2],[1,0],[1,0],[2,0],[4,0],[1,0],[5,1],[6,2],[5,3],[4,2],[4,6],[4,6],[3,10],[3,8],[5,5],[4,3],[3,1],[5,4],[5,6],[5,6],[3,1],[5,1],[1,1],[1,2],[0,4],[-1,3],[-2,1],[-1,2],[-1,0],[-1,2],[0,3],[1,3],[0,3],[0,5],[-1,4],[0,3],[0,3],[0,2],[2,2],[2,1],[2,-1],[5,1],[12,7],[1,3],[0,5],[1,4],[1,2],[1,0],[4,1],[5,2],[3,0],[6,0],[4,0],[7,-1],[5,0],[4,-1],[6,0],[1,1],[0,3],[-1,7],[1,3],[2,4],[3,4],[-1,5],[-2,3],[-4,4],[-1,1],[-3,5],[-1,5],[-2,12],[-2,6],[-1,8],[1,14],[-2,9],[0,4],[0,4],[0,8],[0,10],[-2,11],[1,4],[0,2],[0,2],[-2,3],[-1,3],[1,3],[1,4],[0,1],[-4,5],[-6,8],[-1,3],[-1,5]],[[4938,7206],[5,-1],[3,0],[7,5],[5,7],[4,4],[4,7],[3,5],[5,5],[14,11],[2,0],[4,-2],[4,1],[3,4],[3,9],[4,6],[6,5],[7,6],[5,5],[8,4],[20,3],[11,2],[7,0],[7,8],[3,3],[15,0],[7,6],[28,0],[3,-2],[3,-3],[6,-8],[3,-1],[3,1],[9,7],[9,4],[5,4],[2,7],[5,2],[2,-5],[10,-5],[6,2],[3,1],[-1,7],[6,-2],[5,-3],[5,-7],[3,-1],[6,3],[13,1]],[[2774,5013],[-1,-3],[-2,1],[-1,0],[0,3],[1,8],[0,3],[2,3],[2,2],[3,0],[2,-3],[-3,-6],[-1,0],[-1,-1],[-1,-7]],[[2488,5107],[-1,0],[-2,2],[2,4],[1,-1],[1,-1],[0,-2],[-1,-2]],[[2516,5131],[-3,-2],[-2,1],[0,1],[0,2],[1,3],[2,2],[2,4],[3,3],[1,-1],[0,-1],[0,-1],[-1,-3],[-1,-3],[-2,-5]],[[2490,5139],[-1,0],[-4,6],[0,5],[2,4],[5,2],[3,-4],[-1,-6],[-1,-5],[-2,-1],[-1,-1]],[[2460,5157],[-3,-1],[-2,2],[-1,3],[0,5],[0,1],[5,2],[2,-4],[0,-5],[-1,-3]],[[2484,5165],[-1,-2],[-6,2],[-1,3],[1,5],[1,2],[3,-2],[3,-5],[0,-3]],[[2464,5185],[2,-3],[1,-11],[6,-11],[0,-6],[0,-3],[0,-1],[3,-5],[2,-5],[-3,-10],[-7,-5],[-6,0],[-2,1],[-1,5],[-1,3],[1,4],[4,5],[5,5],[1,4],[-2,3],[-2,7],[-3,5],[-2,15],[-1,1],[-2,-2],[-1,2],[-1,1],[3,3],[0,3],[4,1],[1,-2],[1,-4]],[[2808,5256],[-2,0],[0,2],[1,3],[1,1],[0,-6]],[[2908,5178],[-1,-2],[-2,-1],[-2,0],[-3,2],[-1,0],[0,-2],[2,-3],[2,-3],[0,-4],[2,-5],[2,-5],[2,-3],[0,-2],[0,-4],[0,-3],[0,-14],[0,-1],[-1,0],[-1,0],[-1,2],[-1,1],[0,-3],[-1,-6],[-2,-14],[-1,-12],[-2,-5],[-3,-7],[-4,-9],[-6,-14],[-4,-6],[-3,-5],[-4,-6],[-5,-8],[-6,-4],[-8,-6],[-5,-4],[-4,-3],[-4,-3],[-6,-4],[-2,-4],[-4,-9],[-2,-4],[-1,-4],[0,-2],[0,-1],[1,-2],[0,-2],[-1,-1],[-1,0],[-1,1],[0,2],[-1,2],[-1,1],[-1,-1],[0,-2],[-1,-9],[0,-5],[-1,-2],[0,-4],[-1,-4],[-1,-3],[0,-3],[-1,-2],[-1,-3],[-1,-7],[-1,-5],[-1,-4],[0,-4],[1,-2],[0,-2],[-1,-3],[0,-3],[-2,-2],[-3,-4],[-1,-3],[-1,-3],[1,-3],[0,-2],[-2,-1],[-1,-2],[-1,-3],[-1,-2],[-3,2],[-2,0],[-2,2],[-2,5],[-1,4],[-2,6],[0,7],[-2,3],[-1,2],[-2,-1],[-3,0],[-1,2],[-3,3],[-3,4],[-2,1],[-2,-1],[-1,-2],[-2,-4],[-2,-2],[-1,0],[-2,2],[0,2],[1,3],[3,7],[-3,1],[-1,2],[0,3],[-1,2],[1,4],[1,2],[3,-2],[1,0],[1,3],[1,2],[1,1],[1,1],[-2,6],[0,2],[0,2],[0,3],[0,3],[0,2],[0,3],[-1,2],[0,1],[0,3],[-1,1],[-1,1]],[[2768,4989],[1,0],[4,3],[2,3],[2,3],[2,4],[1,4],[2,18],[3,11],[0,6],[-3,7],[0,11],[0,3],[0,3],[-2,-5],[1,-16],[-1,-7],[-2,-2],[-1,2],[0,11],[-1,-2],[-2,-8],[-3,-6],[-1,-2],[0,-2],[-3,2],[-2,3],[-7,13],[-4,3],[-2,4],[-1,2],[0,3],[2,2],[3,4],[0,8],[0,7],[-2,11],[1,14],[0,6],[-3,12],[2,6],[6,4],[2,3],[1,9],[2,6],[3,-2],[2,0],[-3,2],[-3,9],[0,4],[5,11],[2,3],[3,6],[2,10],[1,14],[-1,11],[-1,11],[2,3],[3,1],[3,4],[2,3],[3,0],[4,5],[7,2],[9,6],[2,5],[-1,10]],[[5949,6988],[1,-2],[1,-5]],[[5951,6981],[2,-12],[2,-10],[2,-13],[1,-5],[1,-4],[3,-14],[2,-12],[2,-10],[2,-14],[1,-5]],[[5969,6882],[-2,-3],[-3,-9],[-3,-30],[-5,-23],[0,-14],[-1,-6],[-2,-7],[-3,-7],[-5,4],[-8,12],[-4,12],[-5,8],[-5,10],[-1,8],[0,4],[-2,12],[-2,5],[-6,13],[-1,6],[-1,3],[-2,4],[-2,16],[-2,10],[-3,-3],[1,-4],[-2,-6],[-2,-7],[1,-5],[5,-9],[1,-3],[1,-8],[0,-11],[1,-4],[3,-8],[1,-5],[1,-4],[1,-4],[4,-7],[5,-13],[4,-10],[4,-4],[1,-4],[1,-12],[-1,-5],[3,-10],[1,-5],[3,-5],[2,-4],[1,-8],[2,-23],[2,-6],[8,-30],[7,-19],[3,-15],[5,-17],[9,-38],[6,-12],[2,-7],[4,-5],[4,-7],[-4,0],[-1,0],[-1,-1],[-1,-5],[0,-4],[0,-19],[1,-10],[4,-19],[3,-5],[1,-4],[2,-2],[9,-7],[5,-13],[11,-17],[2,-5],[0,-1]],[[6024,6451],[-10,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-10,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-9,0],[-5,0],[0,5],[1,3],[-1,3],[-1,1],[-2,-1],[-2,-11],[-2,0],[-3,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0],[-10,0],[-11,0],[-10,0],[-11,0],[-11,0]],[[5693,6451],[0,13],[0,13],[0,13],[0,12],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,12],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,13],[0,2],[-1,9],[-2,11],[-1,14],[-1,4],[-2,14],[0,4],[0,3],[4,12],[2,6],[1,7],[0,5],[-1,9],[-2,8],[0,8],[0,8],[2,5],[3,5],[0,3],[2,3],[1,2]],[[5698,7007],[2,-7],[4,-1],[15,6],[15,-6],[9,-3],[13,-5],[8,-9],[3,-2],[5,1],[4,-6],[16,-3],[8,-6],[4,-5],[3,-1],[2,0],[4,2],[4,3],[4,5],[10,12],[3,3],[2,-1],[3,0],[1,4],[1,2],[1,3],[2,3],[5,1],[9,5],[-1,-3],[-9,-6],[4,0],[4,2],[5,1],[0,3],[1,4],[1,1],[3,-1],[9,-7],[2,0],[7,4],[1,1],[2,-3],[5,-9],[-2,0],[-5,8],[0,-4],[-3,-7],[4,-3],[3,-1],[1,-4],[1,-3],[3,1],[2,5],[-1,3],[-1,2],[1,0],[2,-2],[6,-9],[2,-2],[2,1],[5,2],[1,0],[7,3],[0,-2],[1,-3],[6,3],[8,0],[6,3],[8,7],[0,1]],[[6114,6088],[2,-3],[1,1],[0,2],[5,-4],[0,-3],[-3,0],[-3,1],[-3,0],[-3,1],[-1,5],[2,-2],[1,0],[0,1],[-1,3],[-2,1],[0,2],[1,1],[1,1],[-2,4],[3,-1],[1,-2],[1,-2],[0,-6]],[[6113,6110],[1,-5],[-3,2],[-1,1],[2,2],[0,1],[1,-1]],[[6072,6221],[8,-33],[4,-20],[3,-21],[2,-30],[2,-16],[3,-8],[3,-15],[2,0],[1,-4],[3,-14],[2,-5],[0,4],[0,3],[0,4],[0,6],[2,3],[3,-5],[2,-3],[0,-7],[1,-3],[3,-8],[3,-3],[4,0],[3,-2],[2,-3],[5,-8],[10,-7],[9,-22],[5,-15],[16,-23],[3,-10],[1,-11],[4,0],[5,-11],[2,-9],[5,-3],[1,5],[2,-5],[1,-6]],[[6177,5902],[-3,6],[-2,5],[-2,6],[-3,3],[-2,4],[-3,8],[-2,9],[-4,8],[-8,10],[-6,14],[-5,14],[-4,8],[-1,1],[-7,5],[-5,7],[-3,5],[-3,1],[-2,1],[-4,-1],[-4,3],[-2,0],[-2,1],[-2,1],[-3,-1],[-5,-3],[-2,1],[-1,3],[-1,3],[-1,2],[-2,0],[0,-2],[-5,-6],[-9,-3],[-2,0],[-2,2],[-4,11],[-1,1],[-1,0],[-2,2],[-2,2],[-2,4],[-1,2],[-2,-8],[-3,-14],[-2,-8],[-2,-10],[-1,-1],[-1,1],[-4,13],[-3,4],[-2,0],[-1,-2],[-1,-5],[-1,-2],[-1,-1],[-2,0],[-4,2],[-4,0],[-4,-3]],[[6014,6005],[-1,17],[-1,11],[0,11],[-1,11],[3,7],[1,7],[3,21],[2,4],[2,11],[0,3],[3,14],[0,10],[-1,9],[1,6],[2,4],[0,4],[0,9],[0,2],[2,1],[3,-2],[2,1],[3,0],[2,1],[1,2],[1,11],[1,2],[1,0],[2,2],[2,3],[2,2],[0,1],[2,0],[2,1],[1,2],[2,1],[2,-1],[1,2],[1,0],[1,0],[1,2],[0,1],[1,2],[2,2],[0,2],[1,2],[0,2],[1,2],[2,7],[3,4]],[[4503,6786],[-3,-10],[-3,4],[-1,1],[-1,2],[3,0],[4,5],[1,-2]],[[4572,6805],[0,-4],[0,-5],[0,-7],[-1,-3],[-4,-4],[-2,1],[-2,1],[-3,6],[0,6],[3,4],[1,5],[6,-1],[1,1],[0,1],[1,-1]],[[4522,6798],[-1,-1],[-1,2],[-2,4],[1,4],[1,1],[1,0],[3,-2],[0,-3],[1,-2],[-3,-3]],[[4546,6818],[-3,-13],[-2,-5],[-1,-2],[-3,-1],[-4,8],[-2,8],[-1,3],[2,2],[2,0],[6,2],[1,0],[5,9],[6,1],[0,-3],[-6,-9]],[[4605,6806],[-4,-6],[-3,1],[-1,1],[4,2],[3,5],[2,11],[4,12],[1,5],[1,2],[2,0],[1,0],[0,-3],[0,-6],[-1,-10],[-1,-9],[-8,-5]],[[4504,6825],[-1,0],[0,4],[-3,11],[2,5],[3,0],[2,-3],[0,-4],[-1,-2],[1,-4],[-1,-3],[-2,-4]],[[4619,6849],[-2,-4],[-2,2],[1,8],[1,2],[3,4],[4,1],[1,4],[1,2],[1,-2],[-1,-3],[-1,-8],[-2,-3],[-4,-3]],[[5044,7411],[-1,-1],[-2,1],[-2,0],[-1,3],[1,1],[0,2],[2,-3],[3,-1],[0,-2]],[[5040,7425],[-1,-3],[-5,1],[-1,2],[1,4],[2,0],[0,3],[1,3],[6,2],[1,-2],[1,-3],[-4,-6],[-1,-1]],[[5087,7476],[3,-2],[2,1],[2,0],[1,-1],[1,-4],[-2,-4],[-1,-4],[-2,-4],[-1,-6],[-3,-3],[-2,-2],[-5,4],[-3,1],[-1,2],[0,6],[-1,1],[-2,1],[-2,-1],[-2,-3],[-1,3],[-2,0],[-1,2],[0,2],[12,14],[3,3],[7,4],[1,-1],[-1,-2],[0,-1],[1,-1],[0,-1],[-1,-2],[0,-2]],[[5119,7479],[-1,-1],[-8,7],[-3,0],[-1,1],[0,4],[1,1],[5,1],[5,-2],[2,-7],[1,-1],[-1,-3]],[[4950,7684],[0,-2],[1,-3],[1,-1],[2,-1],[2,0],[3,-1],[1,-2],[0,-2],[0,-3],[-1,-2],[-1,-2],[1,-1],[1,-1],[1,-1],[0,1],[1,1],[1,2],[0,-1],[1,-1],[3,-2],[7,-4],[2,0],[2,-1],[1,-2],[4,-6],[1,0],[2,0],[2,0],[2,2],[1,-1],[1,-1],[2,-1],[2,-2],[1,-3],[1,0],[7,1],[2,-1],[1,0],[2,0],[4,-1],[3,1],[1,6],[0,2],[1,1],[2,-1],[7,-3],[2,-2],[3,-2],[2,0],[2,-1],[2,-6]],[[5047,7632],[4,-3],[2,-2],[1,-1],[1,-2],[1,-1],[2,2],[3,2],[4,-2],[6,-2],[2,0],[0,1],[1,2],[1,0],[1,1],[2,1],[2,1],[2,1],[2,-1],[3,-1],[2,0]],[[5089,7628],[0,-4],[2,-1],[0,-3],[-2,-2],[-2,0],[0,-6],[1,-1],[1,-2],[0,-1],[1,-8],[-3,-5],[-4,-5],[-19,-18],[-5,-8],[-2,-2],[-14,-5],[-10,-6],[-5,-2],[-6,-10],[-3,-4],[3,-1],[2,-5],[-1,-2],[-3,-3],[-2,-1],[-1,1],[-1,-1],[-6,-17],[-6,-12],[-3,-5],[-4,-8],[-7,-21],[0,-6],[4,-20],[2,-6],[3,-4],[5,-4],[1,-4],[-2,-3],[-5,-7],[-9,-8],[-4,-7],[-1,-7],[-2,-3],[-1,-9],[-2,-6],[0,-2],[-2,-5],[0,-3],[2,-5],[-1,-2],[-1,-1],[-4,0],[-10,-1],[-9,-10],[-4,-9],[-4,-16],[-5,-10],[-2,-2],[-4,5],[-4,0],[-4,-1],[-2,-4],[-3,-1],[-3,1],[-7,1],[-3,0],[-5,-3],[-4,2],[-7,1],[-15,-2],[-2,-1],[-2,-4],[-4,-7],[-8,-1],[-6,-4],[-2,-3],[-3,-8],[0,-6],[-1,0],[-1,1],[-1,0],[0,-4],[-3,-2],[-2,-1],[-5,3],[-4,6],[-2,0],[-4,9],[-1,5],[-2,6],[1,2],[-1,2],[-3,2],[-1,5],[3,7],[2,3],[1,1],[-3,0],[-2,-5],[-3,7],[-11,14],[1,3],[0,2],[-2,-4],[-1,-1],[-6,1],[-6,-2]],[[4794,7325],[-2,15],[-1,5],[0,4],[2,8],[2,3],[2,7],[3,6],[3,1],[1,1],[2,5],[0,3],[0,1],[-4,-1],[-6,16],[0,2],[1,4],[0,5],[0,4],[2,3],[3,3],[2,5],[1,4],[0,4],[-1,3],[-4,2],[-3,12],[-1,7],[-1,1],[-2,3],[-2,6],[-1,1],[2,1],[10,0],[2,2],[2,5],[2,8],[0,5],[-1,2],[-3,5],[0,1],[1,3],[2,2],[2,3],[1,2],[0,2],[-1,2],[0,2],[1,3],[0,7],[0,2],[0,8],[-1,5],[-2,8],[0,2],[1,1],[3,3],[3,6],[3,5],[5,4],[3,5],[1,3],[1,1],[0,2],[-1,2],[-2,2],[-2,2],[-3,0],[-1,0],[-1,2],[1,5],[-1,5],[0,2],[-1,2],[-3,-1],[-2,2],[-1,0],[-1,-1],[-5,0],[-2,1],[-1,1],[-1,-1],[0,-1],[0,-1],[-1,-2],[-1,-2],[-4,-2],[-3,0],[-3,2],[-1,1],[-1,1],[-6,-2],[0,1],[-2,-2],[-3,-2],[-2,0],[-1,1],[0,1],[-1,3],[0,2],[3,5],[-1,1],[-1,2],[0,2],[-1,2],[-1,0],[-2,-1],[-6,-3],[-1,-1],[-3,-3],[-2,-3]],[[4756,7600],[-2,-1],[-1,1],[0,9],[3,6],[2,4],[-1,0],[-2,0],[0,3],[1,2],[1,3],[-1,1],[-1,2],[0,5],[0,2],[0,3],[-5,-3],[-1,0],[0,4],[2,6],[1,2],[-4,1],[-2,3],[-1,2],[-2,4],[0,4],[2,8],[2,2],[2,1],[4,6],[6,-1],[3,1],[4,3],[1,0],[3,3],[0,3],[-1,3],[1,2],[3,3],[4,4],[4,0],[5,4],[3,-3],[2,1],[3,-2],[4,-6],[5,-3],[5,2],[8,1],[4,-1],[7,1],[4,0],[6,3],[5,-4],[10,-2],[6,-3],[16,-5],[6,0],[8,3],[3,2],[4,-1],[4,2],[3,0],[3,-3],[10,-5],[3,4],[2,1],[7,-3],[8,-5],[3,0],[6,1],[5,4],[1,0]],[[5628,8560],[2,-1],[1,0],[2,1],[4,-1],[9,-7],[1,-2],[-5,0],[-1,-3],[-2,-1],[-1,-1],[-3,-3],[-3,-2],[-1,-2],[-7,0],[-3,-1],[-3,-3],[-1,-7],[-2,-4],[-2,-2],[-3,0],[0,1],[0,2],[5,7],[1,2],[-3,1],[-1,3],[-5,3],[0,2],[1,0],[0,1],[2,2],[0,2],[-3,6],[1,1],[3,0],[2,-2],[2,2],[1,1],[2,-1],[2,4],[4,1],[2,2],[2,-1]],[[5648,8556],[-2,0],[-6,4],[1,2],[2,2],[5,-2],[0,-4],[0,-2]],[[5636,8572],[-2,-3],[-1,1],[-1,2],[-3,-7],[-3,-1],[-2,2],[0,2],[-2,6],[-3,2],[-4,0],[-3,3],[11,2],[2,3],[2,3],[2,0],[1,-1],[0,-2],[1,-1],[5,-1],[2,-5],[1,-4],[-3,-1]],[[5778,8610],[1,-2],[2,-3],[0,-1],[0,-1],[-2,-1],[-1,-1],[0,-2],[-3,0],[-1,-1],[-1,-5],[-3,-8],[-3,-6],[-3,-3],[-2,-3],[-1,-3],[0,-3],[3,-17],[0,-4],[-1,-3],[0,-3],[0,-3],[2,-5],[2,-7],[1,-4],[1,-2],[2,-1],[0,-1],[0,-1],[-1,-1],[-6,-2],[0,-2],[-1,-2],[-2,-4],[-1,-3],[-1,-3],[0,-2]],[[5759,8497],[-4,1],[-5,2],[-2,2],[-1,0],[-3,-1],[-8,-4],[-2,1],[-4,4],[-2,3],[-6,7],[0,2],[-1,1],[-5,2],[-2,3],[-2,0],[-2,1],[-7,6],[-1,0],[-1,-1],[0,-1],[0,-1],[-1,0],[-1,2],[-2,2],[-6,-3],[-2,-1],[-1,0],[-9,-5],[-3,-2],[-1,0]],[[5675,8517],[0,2],[4,12],[1,9],[1,1],[0,1],[0,3],[-4,2],[-2,-1],[-1,-3],[-1,-2],[-4,-1],[-3,2],[-6,3],[-2,4],[0,5],[-4,4],[-2,4],[1,4],[3,2],[1,2],[-4,0],[-1,0],[0,2],[-2,6],[2,2],[1,2],[-2,2],[1,2],[1,2],[-1,5],[4,3],[4,2],[8,1],[0,5],[3,0],[6,5],[5,-1],[8,4],[16,0],[2,2],[0,3],[0,2],[3,-1],[5,1],[18,-5],[5,0],[6,-5],[4,-1],[10,0],[15,-2],[3,3],[1,1]],[[6192,5817],[-1,-2],[-1,-3],[-1,-3],[-2,-4],[-3,-9],[0,-2],[1,-2],[1,-4],[2,-7],[1,-6],[0,-4],[2,-3],[3,-7],[2,-5],[3,-3],[1,-6],[2,-10],[3,-7],[2,-6],[3,-2],[1,0],[6,-11],[4,-8],[1,-2],[8,-5],[9,-6],[7,-5],[10,-6],[9,-7],[8,-6],[12,-8],[10,-7],[8,-5],[1,-2],[9,0],[10,0],[9,0]],[[6332,5644],[-7,-13],[-7,-16],[-9,-16],[-5,-11],[-8,-16],[-7,-14],[-7,-15],[-7,-14],[-8,-19],[-5,-12],[-9,-19],[-5,-12],[-1,-1],[-8,1],[-7,1],[-10,1],[-1,0],[-2,-1],[-2,-1],[-7,-4],[-1,0],[-6,-6],[-6,-6],[-3,-4],[-2,-7],[-1,-5],[-1,-2],[-2,-2],[-12,-5],[-4,0],[-5,-4],[-3,-6],[-1,-3]],[[6163,5413],[-4,0],[-7,-1],[-3,-1],[-2,0],[-3,0],[-2,1],[-1,2],[-2,4],[-4,7],[-3,5],[-7,-6],[-6,-5],[-8,-8],[-5,-5],[-1,-6],[-4,-10],[-3,-6],[-2,-1],[-7,1],[-3,1],[-4,2],[-6,2],[-4,2],[-5,0],[-6,1],[-4,2],[-4,6],[-5,6],[-5,7],[-5,8],[-7,8],[-6,9],[-2,1],[-1,0],[-7,0],[-8,1],[-5,0],[-2,1],[-1,2],[-2,7],[-2,5],[-2,6],[0,8],[0,9],[1,3],[0,3],[0,4],[-2,4],[-7,4],[-2,0],[-1,-2],[-1,-1],[-1,1],[-1,2],[0,2],[0,2]],[[5979,5500],[0,1],[-3,4],[-2,6],[-1,5],[-2,5],[-1,11],[-1,7],[-2,8],[-2,15],[-1,5],[-2,4],[-3,3],[-2,7],[-5,6],[-3,5],[-3,8],[-1,4],[-1,4],[-1,4],[-2,4],[-6,10],[-2,1],[-3,1],[-3,1],[-5,2],[-4,3],[-2,3],[0,2],[0,3],[2,5],[3,12],[2,8],[1,3],[3,0],[4,0],[3,0],[4,-1],[5,1],[1,3],[2,3],[0,2],[1,6],[0,4],[-1,17],[0,10],[0,11],[0,3]],[[5946,5729],[0,3],[1,12],[1,7],[1,4],[3,12],[0,4],[1,3],[-1,16],[1,8],[3,7],[2,3],[2,2],[1,0],[2,-4],[2,-3],[2,1],[1,2],[2,4],[0,5],[1,12],[0,6],[1,9],[1,11],[1,7],[1,4],[4,9],[3,11],[2,8],[4,14],[2,5],[2,2],[2,1],[5,2],[3,1],[1,2],[0,2],[0,6],[1,11],[1,10],[2,8],[1,3],[1,4],[1,6],[2,12],[0,9],[2,15]],[[5600,8646],[-2,-1],[-2,2],[1,1],[2,2],[1,-1],[1,-1],[-1,-2]],[[5606,8648],[-3,-2],[-1,0],[0,4],[2,1],[3,0],[-1,-3]],[[5615,8661],[4,-1],[1,0],[2,-3],[-3,-2],[0,-2],[1,-2],[1,-2],[-3,0],[-2,2],[0,2],[-2,2],[-1,1],[1,2],[0,2],[1,1]],[[5610,8659],[-2,0],[-2,3],[-1,1],[1,0],[0,3],[0,1],[2,-2],[1,-2],[-1,-1],[2,-2],[0,-1]],[[5595,8670],[0,-2],[-2,0],[-2,-1],[-1,3],[-1,4],[0,1],[1,1],[1,-2],[4,-4]],[[5589,8826],[0,-1],[2,1],[2,2],[2,-1],[-1,-3],[-1,0],[-1,-1],[-1,-1],[-1,-1],[-3,3],[-2,4],[4,0],[0,-1],[0,-1]],[[5690,8927],[-4,-2],[-4,1],[0,4],[2,2],[4,1],[5,-2],[1,-1],[-3,-1],[-1,-2]],[[5804,9159],[-2,0],[-6,-3],[-3,-2],[-4,-1],[1,-2],[7,-1],[1,0],[1,-1],[0,-2],[-1,-2],[-7,-14],[-1,-2],[3,-8],[3,-10],[11,-4],[8,-3],[5,-8],[8,-10],[4,-3],[0,-2],[-1,-7],[-5,-7],[-5,-5],[-5,-8],[-4,-6],[-5,-7],[0,-2],[0,-2],[1,-3],[5,-9],[2,-4],[3,-5],[2,-5],[1,-5],[3,-5],[1,-2],[2,-4],[3,-4],[1,-4],[4,-14],[1,-3],[-1,-3],[-1,-1],[-5,0],[-4,-2],[3,-4],[-3,-5],[0,-8],[-3,-4],[0,-1],[0,-1],[5,-2],[1,-1],[0,-2],[0,-2],[-3,-2],[-3,-2],[0,-2],[0,-2],[1,-3],[1,-4],[3,-3],[8,-2],[1,-2],[0,-2],[0,-3],[-4,-5],[0,-2],[2,-4],[2,-5],[8,-5],[2,-2],[1,-2],[0,-4],[0,-3],[0,-4],[-3,-4],[-5,-8],[-6,-3],[0,-1],[1,-3],[10,-10],[7,-5],[9,-7],[6,-6],[1,-3],[3,-5],[3,-3],[2,-3],[0,-2],[0,-2],[-2,-6],[-2,-5],[-3,-7],[-2,-5],[-7,-9],[-11,-12],[-2,-3],[-5,-6],[-8,-12],[-2,-3],[-7,-9],[-3,-3],[-2,-3],[-7,-9],[-7,-7],[-7,-6],[-2,-4],[-3,-2],[-3,-2],[-1,-2],[-8,-8],[-9,-12]],[[5772,8671],[-1,-1],[-3,-2],[-4,0],[-2,-2],[-6,5],[-1,0],[-3,-1],[-4,-3],[-6,-1],[-3,-1],[-2,-2],[-1,4],[1,4],[1,3],[0,2],[-1,0],[-2,-5],[-1,-4],[-2,-3],[-5,-1],[-4,4],[-3,0],[2,-3],[1,-3],[0,-2],[-3,1],[-3,-2],[-2,-3],[-1,0],[-2,4],[-3,-2],[-2,-2],[-6,-1],[-3,-3],[-5,-2],[-3,0],[-7,-3],[-3,-4],[-2,-1],[-2,1],[-9,-2],[-9,-2],[-3,0],[-4,1],[-4,-4],[-4,-4],[-4,-2],[-2,1],[2,2],[3,3],[2,3],[0,3],[-2,1],[-1,0],[-3,3],[-2,7],[-1,0],[-1,-2],[-1,-4],[0,-2],[-2,-1],[-1,-1],[-1,-1],[-6,0],[0,3],[0,1],[1,3],[-1,1],[1,2],[1,0],[1,1],[1,1],[0,1],[-2,1],[0,1],[2,4],[0,2],[-1,0],[-1,-1],[-7,2],[-9,6],[-2,0],[-2,5],[-2,-1],[-3,-3],[-3,3],[-2,1],[-1,2],[0,4],[0,4],[-1,5],[0,6],[0,6],[2,4],[1,2],[1,7],[0,7],[0,3],[0,1],[1,0],[0,2],[-1,0],[0,2],[0,1],[2,0],[0,1],[1,0],[-2,5],[0,2],[-2,6],[-3,6],[-3,4],[1,7],[2,7],[-1,3],[0,4],[-5,4],[0,6],[-1,6],[0,4],[1,3],[1,2],[7,10],[1,4],[5,1],[-2,4],[-1,2],[0,3],[7,2],[3,-1],[6,2],[5,3],[0,2],[-1,2],[-1,4],[1,1],[2,-1],[-1,2],[0,2],[3,-1],[3,5],[0,4],[7,2],[7,8],[3,2],[3,2],[7,8],[3,0],[1,6],[6,7],[2,1],[3,6],[7,8],[4,9],[3,4],[1,3],[2,1],[3,2],[5,2],[6,0],[2,-2],[2,1],[0,3],[-2,2],[1,2],[3,1],[0,3],[-1,2],[-2,3],[1,6],[0,6],[2,7],[-3,4],[-12,7],[-2,0],[-2,0],[-3,5],[1,5],[1,1],[-1,0],[-2,-2],[-4,-2],[-4,1],[-3,0]],[[5670,8974],[-3,11],[-1,4],[-2,5],[-5,2],[-1,2],[0,2],[0,3],[-1,4],[0,4],[1,2],[2,1],[2,5],[1,2],[0,5],[1,4],[2,2],[-1,2],[-1,2],[-2,3],[-3,4],[-2,4],[-1,3],[0,3],[0,3],[1,2],[2,3],[1,1],[-1,5],[-2,1],[-4,1],[-2,0],[0,1],[0,3],[1,2],[1,2],[0,1],[-1,5],[0,6],[0,4],[4,4],[0,1],[-4,3],[-4,5],[-1,2],[-4,0],[-2,7],[-3,4],[-4,3],[-2,1],[-11,4],[-5,1],[-6,2],[-4,4],[-3,2],[-3,2],[-4,2],[-1,2],[-5,4],[-2,2],[-7,5],[-1,2],[0,1],[0,1],[-8,3]],[[5572,9160],[2,2],[6,0],[5,-2],[1,1],[0,2],[-2,6],[1,1],[2,2],[3,2],[6,0],[3,0],[1,0],[6,-7],[4,-7],[3,-2],[6,-8],[2,-5],[1,-3],[2,0],[9,-1],[7,-2],[2,-1],[5,0],[4,2],[7,2],[2,2],[2,3],[4,-1],[4,-2],[5,-3],[5,-1],[6,-2],[2,-3],[4,0],[4,2],[3,8],[2,3],[3,2],[3,1],[3,1],[2,1],[3,5],[0,4],[0,9],[0,3],[2,5],[4,13],[1,4],[2,2],[2,1],[4,4],[6,8],[2,0],[4,1],[6,0],[4,-2],[1,0],[2,1],[4,2],[7,5],[4,1],[4,0],[5,-5],[6,-6],[4,-3],[10,-5],[10,-3],[5,-12],[-2,-4],[-2,-2],[-4,-4],[-5,-7],[-1,-3],[2,-3],[2,-3]],[[9850,3934],[-1,0],[0,1],[0,1],[1,-1],[0,-1]],[[36,3993],[-1,0],[0,1],[0,1],[1,-1],[0,-1]],[[41,4080],[-1,-1],[0,1],[-1,1],[0,1],[0,1],[1,0],[0,-1],[0,-1],[1,-1]],[[9957,4091],[0,-3],[-4,-1],[-1,2],[-1,0],[-2,-3],[0,-2],[0,-1],[-1,-1],[-4,-1],[-2,1],[1,2],[2,2],[1,0],[2,2],[1,3],[2,1],[2,1],[2,-1],[2,-1]],[[6,4093],[0,-2],[-1,0],[0,1],[-1,0],[0,-1],[0,-1],[0,-1],[0,1],[0,1],[0,2],[1,1],[1,-1]],[[34,4134],[0,-2],[-1,2],[-1,1],[2,1],[0,-2]],[[9981,4141],[-3,4],[0,2],[1,2],[1,1],[1,-2],[0,-5],[0,-2]],[[28,4148],[-1,0],[-1,1],[0,1],[0,2],[2,-2],[0,-2]],[[49,4150],[-2,-1],[-1,3],[1,2],[1,0],[0,-3],[1,-1]],[[9966,4163],[-1,-1],[-1,3],[1,4],[2,0],[0,-4],[-1,-2]],[[9951,4183],[0,-2],[1,-1],[1,-1],[2,-4],[3,-5],[2,-3],[0,-3],[-1,-3],[1,-5],[1,-5],[1,-9],[-2,-1],[-3,0],[-1,-2],[-1,1],[-2,-1],[-3,-3],[-2,-3],[-3,0],[-3,-1],[-3,0],[-2,2],[-4,3],[-5,1],[-2,2],[-1,3],[-2,6],[0,3],[0,3],[1,1],[2,1],[0,2],[0,2],[1,0],[0,1],[0,3],[0,3],[3,6],[3,4],[5,4],[4,0],[5,3],[2,2],[1,-1],[1,-3]],[[9983,4184],[-1,-2],[0,8],[1,0],[0,-1],[1,-2],[-1,-3]],[[29,4189],[-1,-2],[0,1],[0,3],[1,1],[-2,2],[0,1],[1,1],[1,-2],[1,-1],[0,-1],[0,-2],[-1,-1]],[[9922,4196],[-1,-1],[1,5],[0,1],[1,1],[1,0],[-1,-3],[-1,-3]],[[9999,4207],[-2,-2],[-1,2],[1,5],[-9997,5],[9999,-10]],[[0,4217],[3,5],[1,1],[1,-5],[-1,-5],[-3,-4],[-1,-2],[0,10]],[[9999,4231],[0,1],[-9999,2],[2,3],[1,0],[-1,-2],[0,-2],[-2,-2],[9999,0]],[[9999,4253],[-4,-8],[-2,-4],[-1,-4],[-4,-5],[-1,-6],[0,-7],[4,7],[4,5],[1,1],[1,0],[0,-2],[-1,-1],[0,-5],[1,-5],[-3,1],[-3,-1],[-3,-2],[-4,-1],[-1,0],[-1,1],[-1,1],[-1,3],[-3,0],[-4,-6],[-2,-5],[-1,0],[-2,1],[-2,-4],[-3,-1],[-1,3],[-1,4],[-1,3],[-3,1],[1,3],[1,2],[0,2],[1,2],[1,-1],[2,-1],[1,2],[2,0],[2,5],[2,3],[4,3],[3,2],[2,0],[2,1],[3,5],[3,3],[2,1],[2,1],[2,-1],[2,1],[-9995,3],[1,2],[1,0],[-1,-1],[-1,-1],[9999,0]],[[9919,4464],[-1,-1],[-2,0],[0,1],[0,1],[2,0],[1,0],[0,-1]],[[3342,2175],[-2,-1],[0,1],[-1,2],[0,3],[0,1],[1,0],[2,-3],[0,-3]],[[3376,2188],[1,-5],[-3,2],[0,2],[1,2],[1,0],[0,-1]],[[3305,2201],[2,-1],[2,1],[-1,-6],[-1,-3],[-3,0],[-2,4],[-1,2],[3,1],[1,2]],[[3325,2220],[4,-1],[4,4],[2,1],[2,-1],[2,-2],[2,0],[6,2],[1,0],[2,3],[2,-2],[1,-2],[0,-3],[-2,-2],[-1,-3],[-1,-2],[-3,-2],[-1,-3],[-4,-7],[-6,-10],[-2,0],[-4,-1],[-1,1],[-2,-1],[-1,-5],[-2,-3],[-1,-1],[-2,-1],[-1,-2],[-5,1],[-4,2],[-4,5],[6,7],[5,-1],[4,5],[3,2],[1,2],[1,2],[0,2],[-1,1],[-1,0],[-2,-1],[-3,-1],[-2,2],[1,1],[2,0],[5,2],[1,1],[-1,4],[-4,2],[-2,3],[-1,2],[1,2],[-2,4],[2,0],[2,-3],[4,-3]],[[3330,2223],[-4,0],[-1,2],[0,5],[3,1],[3,-2],[0,-2],[-1,-4]],[[3365,2231],[4,-4],[5,2],[3,-1],[1,-3],[-1,-3],[-1,1],[-2,-1],[0,-4],[1,-1],[6,-4],[1,0],[0,2],[-1,2],[0,3],[0,2],[2,1],[6,1],[2,-1],[3,-7],[-3,0],[-1,-3],[2,-2],[2,-1],[-1,-3],[0,-2],[-5,-2],[-4,-1],[-1,-3],[-4,-2],[-9,-5],[1,-3],[0,-2],[-1,-4],[-13,5],[-2,0],[4,-9],[-3,-2],[-2,1],[-3,-1],[-1,-6],[-4,4],[-3,6],[0,3],[3,6],[-1,3],[7,8],[2,3],[2,1],[2,1],[1,1],[0,2],[-1,3],[0,6],[6,8],[-1,5],[2,0]],[[6549,3955],[-4,-2],[-2,1],[-6,4],[-1,4],[-2,9],[0,3],[2,6],[4,2],[4,-1],[2,-1],[2,-7],[2,-7],[0,-8],[-1,-3]],[[6254,4436],[-1,0],[-1,1],[-1,4],[1,4],[0,2],[-1,5],[1,3],[1,-3],[1,0],[2,-3],[-1,-4],[0,-1],[-1,-4],[0,-4]],[[3483,5318],[1,1],[1,0],[1,4],[2,3],[5,14],[1,6],[0,3],[1,7],[-1,9],[0,2],[4,10],[1,5],[0,5],[1,4],[-1,1],[0,1],[-2,4],[0,4],[-3,4],[-1,3],[-3,9],[0,5],[-1,2],[0,2],[0,2],[-1,6],[-1,5],[0,3],[1,6],[-1,6],[0,3],[-1,5],[1,5],[0,2],[0,4],[3,10],[3,5],[2,4]],[[3495,5492],[2,4],[3,15],[2,5],[2,1],[11,-13],[5,-1],[10,-7],[4,-8],[9,-15],[4,-5],[0,-3],[-1,-6],[3,5],[5,-8],[1,-5],[1,-7],[0,-5],[-1,-3],[0,-2],[1,3],[1,2],[0,5],[2,7],[1,0],[1,-4],[3,-16],[0,-4],[1,-5],[0,-2],[0,-2]],[[3310,6019],[0,-4],[-1,0],[-1,2],[-5,0],[0,3],[0,1],[2,4],[-3,1],[-1,2],[-2,9],[0,2],[1,1],[2,1],[2,-3],[3,-4],[0,-1],[0,-3],[1,-3],[1,-1],[1,-7]],[[3299,6099],[-2,0],[-1,4],[2,2],[0,1],[1,-3],[1,-2],[-1,-2]],[[3289,6106],[-2,-3],[-1,1],[-2,5],[-1,14],[1,2],[0,1],[3,-2],[2,-2],[1,-1],[-1,-3],[1,-10],[-1,-2]],[[3296,6119],[-3,-1],[-2,1],[-1,4],[1,3],[0,4],[0,3],[1,2],[2,-3],[0,-3],[1,-3],[5,-6],[-4,-1]],[[5263,7649],[-1,-8],[1,-3],[1,-1],[0,-2],[1,-23],[0,-2],[-4,-9],[0,-2],[-1,-12],[0,-3],[-1,-3],[-2,-9],[-2,-4],[-5,5],[-3,2],[-2,3],[-1,1],[1,2],[1,3],[0,2],[-3,2],[-1,1],[0,3],[1,3],[-1,4],[-2,-1],[-1,1],[0,2],[1,2],[1,2],[0,3],[-1,2],[-2,2],[-1,4],[2,2],[1,1],[-1,4],[-1,0],[-1,1],[1,1],[1,3],[3,7],[2,3],[5,2],[2,1],[1,3],[1,1],[2,0],[2,-1],[0,-1],[1,1],[1,3],[-1,3],[1,7],[1,5],[1,0],[1,-3],[0,-2],[1,-5],[0,-3]],[[4967,7828],[-1,-5],[-2,4],[-3,4],[0,4],[0,1],[3,-3],[3,-5]],[[5160,8037],[1,-2],[2,-1],[1,0],[1,-2],[1,0],[2,0],[1,2],[2,1],[2,0],[1,-1],[2,-2]],[[5195,7829],[-3,-3],[-4,-3],[0,-2],[0,-3],[1,-1],[2,-3],[2,-5],[1,-4],[3,-5],[1,-1],[0,-1],[-1,-2],[-1,-6],[-1,-1],[-2,-1],[-3,-4],[-2,0],[-3,0],[-1,-1],[0,-3],[1,-3],[1,-3],[1,-3],[1,-2],[3,-1],[1,0],[1,-1],[1,-1],[1,-7],[-1,-1],[-1,-1],[-1,-2],[-2,-4],[0,-3],[1,-3],[0,-2],[-1,-2],[1,-4],[2,-3],[5,-4],[5,-4],[1,-1],[7,3],[1,0],[0,-3],[1,-2],[-1,-3],[-2,-4],[-2,-3],[-1,-3],[1,-2],[0,-3]],[[5208,7705],[-2,-1]],[[5206,7704],[-1,1],[-1,-1],[0,-1]],[[5204,7703],[-3,-2],[-2,-3],[-9,-12],[-4,-4],[-1,-2],[-1,-4],[-2,-4],[-2,-2],[-5,-1],[-6,-4],[-2,1],[-6,0],[-4,5],[-7,3],[-3,6],[-3,1],[-2,0],[-2,1],[0,2],[0,2],[-2,-1],[-2,0],[-1,-1],[-1,-1],[-1,1],[-1,0],[1,-2],[-3,0],[-2,1],[-6,3],[-1,1],[-4,1],[-2,2],[-1,3],[-1,1],[-1,1],[-4,-2],[-1,-3],[-2,-3],[-15,-15],[-3,-7],[-3,-9],[0,-5],[1,-14],[3,-8],[1,-1]],[[4950,7684],[4,2],[4,7],[4,26],[3,31],[2,6],[3,2],[-3,4],[-1,-2],[0,-2],[-1,-1],[1,28],[2,10],[1,11],[4,-4],[4,-4],[1,-4],[2,-13],[2,-3],[2,-2],[-1,3],[-1,2],[-3,17],[-1,5],[-3,4],[-8,8],[-1,2],[0,3],[3,0],[2,-2],[0,2],[-1,2],[-1,7],[-1,16],[0,3],[0,3],[-3,1],[-2,0],[-2,1],[-11,10],[-4,10],[-4,7],[-1,3],[0,3],[2,7],[-1,4],[-2,1],[-2,2],[2,4],[1,2],[2,1],[3,-1],[3,-2],[2,-1],[-6,6],[-11,-2],[-2,1],[-2,1],[-1,4],[2,2],[1,3],[-1,2],[-2,1],[-4,0],[-2,0],[-1,1],[2,4],[-2,1],[-2,-1],[-3,0],[-3,1],[-2,4],[-2,0],[-1,-1],[-2,2],[-2,0],[-1,0],[-2,2],[-11,5],[-5,1],[-4,-2],[-2,0],[-2,3],[-1,6],[-7,4],[1,2],[3,1],[4,2],[1,2],[-3,3],[-2,1],[-1,1],[-1,2],[2,1],[1,0],[2,-1],[5,1],[-2,3],[-2,0],[-1,1],[-3,0],[-2,-1],[-4,0],[0,3],[-1,2],[1,6],[6,4],[13,5],[5,0],[4,0],[5,4],[2,2],[7,2],[6,-3],[6,-11],[3,-4],[7,7],[10,0],[2,-4],[1,3],[2,4],[1,-2],[1,-2],[11,0],[1,1],[-3,3],[-2,6],[0,23],[-3,6],[-4,10],[-1,6],[-1,2],[1,4],[4,-1],[3,0],[7,2],[3,-2],[-1,-4],[1,-6],[1,-3],[2,-4],[5,1],[5,-2],[7,0],[10,-4],[4,2],[4,4],[8,3],[1,1],[-5,0],[-4,2],[0,3],[0,3],[2,6],[12,9],[8,3],[9,5],[5,5],[3,7],[1,1],[1,1],[-1,3],[0,25],[1,5],[2,4],[3,3],[4,3],[14,4],[3,2]],[[4813,8723],[1,-2],[-1,0],[-2,2],[-3,5],[-1,4],[0,2],[1,0],[0,-2],[3,-1],[1,-1],[0,-2],[1,-2],[0,-3]],[[4816,8744],[-1,-2],[-1,0],[-2,2],[-2,2],[-1,1],[-1,2],[1,0],[2,0],[3,-2],[1,-2],[1,-1]],[[4800,8763],[2,-2],[1,-2],[-1,-1],[-2,-1],[-2,1],[-3,1],[-2,4],[3,0],[3,1],[1,-1]],[[4815,8768],[0,-8],[-1,0],[-3,2],[-1,1],[0,-1],[0,-2],[3,-6],[0,-1],[0,-1],[-3,2],[-5,6],[-5,11],[6,2],[5,-3],[4,-2]],[[4822,8770],[-2,-4],[-2,0],[0,1],[-1,1],[1,3],[-1,4],[3,-3],[2,-2]],[[9526,5491],[1,-3],[-2,1],[0,1],[1,1]],[[9397,5576],[-2,-1],[-2,1],[-1,4],[0,1],[0,3],[1,2],[3,-2],[1,-3],[0,-2],[0,-3]],[[9212,5607],[-1,-1],[-1,0],[-1,1],[1,0],[0,1],[0,1],[1,0],[1,-1],[0,-1]],[[9218,5612],[-1,0],[0,1],[1,1],[1,-1],[-1,-1]],[[8836,5731],[-2,-5],[0,2],[1,3],[1,3],[1,2],[1,0],[0,-2],[0,-3],[-2,0]],[[5309,4958],[-3,5],[-2,10],[-3,6],[-6,9],[-1,7],[-7,15],[-10,16],[-6,13],[-1,3],[1,-1],[6,-6],[1,0],[1,2],[-3,3],[-3,3],[-2,2],[-3,0],[-1,2],[-1,5],[-1,3],[-1,4],[-3,8],[-1,3],[-2,4],[1,1],[4,-4],[0,1],[0,3],[-4,3],[-2,1],[-1,2],[1,3],[-3,12],[-3,8],[-1,4],[8,-18],[1,-1],[2,1],[3,2],[-1,2],[-1,3],[-1,-1],[-2,-1],[-1,2],[-1,1],[2,9],[-1,0],[0,-2],[-1,0],[-2,-1],[-4,5],[-3,13],[-1,3],[-1,4],[-1,2],[-4,19],[2,-2],[2,-5],[3,1],[1,3],[2,0],[1,1],[1,3],[5,13],[1,16],[0,10],[-1,10],[1,4],[1,-3],[0,-3],[1,-3],[1,-2],[3,-1],[5,-3],[2,-3],[0,5],[5,4],[-1,1],[-5,-1],[-6,6],[-2,4],[-2,7],[-2,4],[0,3],[4,3],[1,0],[1,-4],[1,-1],[1,0],[0,3],[0,9],[-2,12],[1,2]],[[5266,5243],[1,1],[1,2],[1,0],[2,0],[0,-3],[1,-2],[1,0],[2,-2],[1,1],[1,1],[1,1],[4,0],[4,0],[8,0],[7,-1],[8,0],[5,0],[0,7],[0,11],[0,13],[0,12],[0,11],[0,14]],[[4970,8103],[-2,-2],[-1,-2],[-1,-1],[-1,0],[-2,0],[-6,4],[-1,0],[1,2],[4,2],[2,2],[5,-2],[2,-3]],[[4883,8255],[1,-1],[3,0],[-1,-2],[-3,-3],[-2,-3],[-3,-2],[-1,3],[-2,0],[-2,5],[0,7],[3,2],[4,0],[3,-6]],[[4827,8299],[-3,1],[-1,-1],[-1,-1],[-1,0],[-3,-1],[-3,0],[-1,2],[1,5],[-1,1],[-2,0],[-1,1],[-2,4],[0,1],[-1,2],[-1,3],[-2,2],[-1,0],[-3,-3],[-2,-4],[1,-1],[1,-2],[-1,-2],[-3,-3],[-1,-1],[-1,-1],[-1,1],[-4,0],[-2,0],[-2,3],[-5,2],[0,3],[-1,1],[-6,7],[-1,2],[1,2],[2,2],[7,3],[1,1],[0,2],[-2,1],[-2,1],[0,1],[0,1],[1,1],[2,1],[2,-1],[1,1],[2,1],[2,1],[1,4],[2,3],[0,1],[1,6],[1,1],[4,4]],[[4799,8357],[1,-2],[2,-1],[2,2],[3,6],[1,1],[2,-1],[3,1],[7,3],[2,0],[4,-2],[3,0],[3,-4],[1,-7],[3,-6],[5,-6],[0,-3],[-2,-2],[-3,-2],[0,-3],[2,1],[2,1],[4,-1],[2,-2],[1,-4],[1,-3],[-1,-3],[-1,1],[-1,3],[-1,1],[-2,1],[1,-4],[-1,-6],[1,0],[2,-1],[-1,-5],[-3,-2],[-3,0],[-1,-2],[-1,-3],[-1,-4],[-3,-2],[-2,1],[-3,1]],[[4858,8378],[-4,0],[-1,0],[-2,1],[-1,8],[0,3],[1,1],[1,2],[2,0],[1,-1],[1,-2],[2,-5],[0,-5],[0,-2]],[[4829,8405],[1,-7],[1,-5],[0,-1],[-1,-2],[-4,-3],[-2,0],[1,3],[-1,4],[1,2],[-1,1],[0,-1],[-4,-4],[-1,0],[0,1],[1,3],[0,2],[0,2],[1,1],[1,1],[1,0],[1,-1],[3,3],[2,1]],[[4834,8399],[-1,-1],[-1,0],[-1,1],[0,2],[0,2],[1,2],[3,3],[-1,1],[0,1],[1,2],[3,4],[1,0],[1,0],[-2,-6],[-4,-11]],[[4839,8429],[-11,-3],[-4,0],[0,2],[1,1],[3,1],[1,8],[-5,3],[0,1],[0,2],[1,1],[3,1],[1,1],[1,-1],[2,-2],[2,-4],[3,-1],[2,-1],[0,-9]],[[4816,8443],[-2,0],[0,1],[3,3],[2,1],[-1,-3],[-2,-2]],[[4794,8465],[-3,-1],[-1,1],[1,2],[1,1],[2,-1],[0,-1],[0,-1]],[[4825,8465],[-1,-1],[-1,0],[-1,1],[-1,3],[3,2],[1,-1],[1,-2],[0,-1],[-1,-1]],[[4798,8474],[-1,-1],[-2,1],[-1,0],[0,4],[-1,2],[1,4],[0,5],[3,0],[1,-1],[0,-14]],[[4829,8496],[0,-3],[-1,-3],[1,-3],[0,-2],[1,-1],[1,-1],[5,-1],[5,0],[1,-1],[0,-1],[-1,-2],[-2,-3],[-4,-4],[-1,-1],[-1,-1],[-1,1],[0,8],[-4,-1],[-3,1],[-1,1],[-1,2],[-2,5],[-7,2],[-2,3],[0,1],[0,1],[1,2],[2,0],[1,0],[1,1],[0,1],[-1,2],[6,3],[1,3],[1,1],[2,-2],[2,-3],[1,-5]],[[4799,8506],[4,-3],[-3,-5],[-4,0],[-5,4],[0,2],[1,0],[1,1],[1,-1],[2,1],[2,0],[1,1]],[[4827,8545],[-3,-10],[-2,0],[-1,-2],[-4,-3],[4,0],[1,-1],[0,-2],[-1,-1],[-4,-5],[-3,-2],[-3,-4],[-2,0],[-1,-4],[-2,-1],[-1,1],[-2,3],[3,3],[1,1],[2,2],[0,1],[-4,2],[-2,2],[1,1],[1,1],[0,1],[-1,1],[-1,0],[0,1],[-1,2],[1,3],[1,1],[0,1],[1,1],[1,-1],[2,-2],[2,1],[3,-1],[0,1],[-2,5],[0,1],[1,1],[6,4],[7,6],[1,0],[1,0],[0,-3],[0,-5]],[[4913,8554],[0,-5],[0,-1],[-1,-2],[-2,-3],[-5,-5],[-10,-10],[-6,-6],[-1,-2],[-1,-4],[4,-1],[1,-1],[0,-2],[-6,-6],[-1,-6],[4,0],[3,1],[7,4],[6,3],[3,0],[6,-2],[1,0],[3,1],[2,0],[17,-1],[5,1],[3,-1],[3,-4],[2,-7],[0,-1],[-1,-3],[-3,-4],[-3,-5],[0,-3],[-1,-3],[-1,-3],[-4,-14],[-5,-8],[-2,-5],[-3,-4],[-2,-3],[-3,-2],[-7,-2],[-2,-1],[-3,-3],[-2,-1],[3,0],[3,2],[5,0],[7,-4],[-1,-4],[-2,-3],[-6,-1],[-6,-6],[-2,-2],[-3,-1],[-3,0],[-6,2],[-3,2],[3,-3],[2,-2],[16,-3],[1,0],[5,4],[6,0],[13,-7],[3,-6],[6,-8],[2,-3],[3,-2],[1,-5],[2,-13],[3,-14],[4,-14],[1,-4],[2,-3],[11,-7],[3,-2],[4,-6],[4,-7],[4,-5],[4,-4],[-2,-2],[-1,-4],[1,-4],[1,-5],[4,-7],[3,-7],[-1,1],[-1,0],[-2,0],[-2,1],[-2,2],[-3,3],[-5,-1],[-3,0],[-3,0],[5,-1],[5,-1],[12,-13],[4,-7],[2,-10],[-1,-5],[-3,-3],[-2,-3],[-2,-4],[6,-6],[2,1],[1,0],[1,2],[3,5],[1,2],[4,0],[3,0],[4,-1],[3,0],[6,-2],[3,-2],[8,-8],[1,-4],[1,-6],[0,-6],[-1,-6],[-2,-5],[-1,-7],[0,-2],[-1,-2],[-4,-5],[-3,-3],[-1,1],[-1,0],[0,-1],[1,-3],[0,-3],[-2,-2],[-3,-1],[-4,1],[-6,-5],[4,-2],[1,-2],[-1,-5],[-2,-2],[-3,-1],[-3,0],[-2,-1],[-3,-2],[3,1],[2,-1],[1,-3],[2,-1],[5,-2],[4,0],[6,1],[4,0],[1,-1],[0,-3],[-1,-7],[-1,-2],[-8,-6],[-2,-4],[-1,-3],[-5,1],[-2,-3],[-5,-2],[-3,-2],[-3,-3],[-3,0],[-11,3],[-7,-1],[-9,-2],[-3,0],[-3,3],[-4,1],[-4,1],[-4,2],[2,-4],[-5,-4],[-2,-1],[-2,0],[-5,-1],[-5,1],[1,-4],[1,-2],[-1,-1],[-1,-1],[-9,2],[-1,0],[-1,-2],[-3,1],[-3,3],[-4,2],[-3,1],[-3,0],[-11,-5],[-2,-5],[-1,-7],[-2,-6],[-3,-4],[-3,-1],[-3,3],[-5,4],[-2,2],[-1,0],[-1,0],[-2,-2],[-2,0],[-4,-1],[-6,-3],[-2,-2],[-6,-5],[-1,-2],[-2,-5],[-3,-1],[-2,3],[-3,2],[-4,-1],[-2,-2],[-1,1],[0,3],[3,4],[6,3],[6,7],[2,5],[2,2],[1,2],[2,0],[0,3],[8,11],[1,3],[0,5],[1,4],[6,3],[3,9],[1,1],[9,2],[6,-1],[7,-1],[3,0],[3,0],[3,3],[4,9],[3,4],[3,3],[3,4],[4,8],[-3,-3],[-4,-4],[-2,-2],[-6,-3],[-3,-2],[-5,-6],[-1,0],[-7,1],[-6,7],[-4,3],[-1,1],[-2,-1],[-3,-1],[-3,0],[2,3],[2,2],[-5,2],[-2,1],[-1,2],[-4,0],[-2,0],[-4,-3],[-5,-4],[-6,5],[-1,2],[0,4],[-1,3],[-2,1],[3,4],[2,3],[6,2],[9,7],[5,2],[4,5],[2,3],[2,4],[1,4],[2,4],[-2,1],[-1,3],[0,3],[1,2],[0,4],[-2,3],[0,3],[1,3],[-4,-1],[-3,0],[-4,-2],[-3,-3],[-3,-1],[0,3],[2,2],[3,4],[3,3],[1,3],[1,3],[2,2],[4,4],[9,5],[1,0],[3,0],[3,0],[3,2],[3,1],[6,-5],[-1,7],[2,2],[4,-7],[2,-1],[3,1],[-1,2],[-2,0],[-1,1],[-2,2],[-3,7],[1,4],[1,5],[2,4],[-1,1],[-2,1],[0,4],[0,4],[4,3],[1,5],[0,5],[0,2],[-4,0],[-1,-1],[-2,-2],[-1,0],[-5,6],[-2,5],[-5,9],[0,6],[3,12],[6,7],[6,3],[-1,1],[-10,0],[-3,-1],[-3,-3],[-2,-1],[-2,-1],[-1,-1],[-2,-3],[-1,-1],[-4,0],[-1,0],[-1,1],[-1,2],[-2,1],[-1,-1],[-3,-3],[-3,-1],[-4,2],[-4,3],[-1,-1],[-1,-3],[-1,-5],[-3,4],[-3,6],[-1,3],[0,4],[1,1],[2,-1],[3,9],[5,12],[1,4],[2,5],[-1,3],[-1,2],[-4,6],[0,5],[0,5],[1,3],[1,1],[6,0],[-2,1],[-5,5],[0,2],[1,4],[-1,-2],[-2,-5],[-2,-1],[-3,-1],[-1,-3],[0,-1],[-2,0],[0,-2],[-1,0],[0,2],[0,4],[0,4],[2,3],[5,7],[-3,-2],[-5,-7],[-3,-4],[-1,-1],[0,-1],[0,-1],[1,-8],[0,-3],[-5,-22],[-1,-2],[-1,-1],[-3,0],[-1,2],[0,1],[1,3],[2,11],[1,3],[1,2],[3,5],[-2,-1],[-1,1],[-1,1],[1,13],[1,5],[1,7],[1,5],[2,5],[1,5],[1,2],[1,4],[2,4],[1,4],[-10,-11],[-2,-2],[-4,0],[-2,2],[-2,2],[-1,5],[-3,0],[-2,1],[0,1],[3,2],[4,1],[4,4],[-3,3],[0,1],[3,3],[4,8],[1,7],[-2,4],[-1,2],[-3,3],[-1,3],[0,2],[2,2],[2,1],[2,1],[-2,2],[-1,2],[-1,2],[0,1],[1,7],[1,2],[2,4],[7,-1],[1,2],[1,0],[3,-1],[0,1],[-6,8],[-1,2],[2,4],[0,2],[0,2],[0,1],[2,1],[6,0],[1,1],[0,2],[-2,2],[0,3],[0,2],[1,4],[0,1],[1,3],[1,1],[2,0],[3,0],[1,-2],[2,-2],[1,0],[4,3],[1,0],[1,-3],[7,3],[9,1],[6,1],[6,1],[5,2],[6,-1],[0,-1],[0,-2],[-2,-4]],[[4918,8567],[-1,1],[-2,4],[3,1],[1,-1],[0,-1],[-1,-4]],[[4912,8570],[-2,-1],[-2,1],[-2,3],[-1,2],[0,2],[1,0],[3,0],[1,-3],[0,-2],[0,-1],[2,0],[0,-1]],[[4915,8584],[-1,-2],[2,0],[3,-1],[2,0],[2,-1],[-1,-3],[-1,-1],[-1,0],[-4,3],[-4,-2],[-1,1],[-1,1],[0,1],[0,2],[-1,0],[-1,-2],[-1,0],[0,1],[-1,2],[1,3],[1,4],[1,0],[3,0],[3,-2],[1,-2],[0,-1],[-1,-1]],[[4929,8595],[-3,0],[1,4],[2,1],[4,-1],[-1,-1],[-3,-3]],[[4924,8593],[-3,-2],[-1,2],[0,3],[-3,2],[-1,1],[-1,2],[2,1],[3,-3],[1,-3],[3,-1],[0,-2]],[[4963,8671],[1,-4],[1,1],[2,-4],[1,0],[2,1],[0,-3],[-2,-10],[-1,-2],[0,-3],[0,-1],[-1,-6],[-1,-2],[-1,-5],[-1,0],[-1,2],[1,7],[1,4],[0,3],[-1,2],[-3,0],[-2,-1],[0,1],[0,1],[-1,1],[-2,0],[-1,0],[-1,2],[0,1],[3,1],[2,0],[3,2],[-2,8],[-3,0],[0,1],[0,2],[2,0],[2,4],[2,1],[1,0],[0,-4]],[[4971,8669],[-1,0],[-3,5],[2,7],[3,0],[0,-2],[0,-1],[-2,-1],[1,-3],[0,-4],[0,-1]],[[4978,8686],[-1,-5],[0,-2],[-3,0],[0,1],[-1,3],[1,3],[1,1],[0,-1],[2,2],[1,-2]],[[6206,7552],[0,1],[0,1],[-1,2],[-1,0],[-2,0],[-2,1],[-2,2],[0,2],[1,1],[-1,1],[-3,3],[-4,6],[-2,2],[-1,4],[-1,1],[-2,0],[-2,0],[-1,-1],[-2,-6],[-1,-1],[-3,0],[-2,2],[-2,0],[-4,1],[-4,0],[-3,-4],[-1,1],[-2,1],[-4,2],[-2,1]],[[6152,7575],[6,11],[1,6],[0,4],[0,5],[-2,10],[-3,15],[-2,15],[-2,4],[-8,6],[-2,6],[-6,7],[-9,4],[-2,1],[-7,10],[-6,6]],[[6110,7685],[1,3],[2,4],[2,1],[5,-1],[5,-2],[4,1],[4,-3],[4,-3],[4,-3],[7,-2],[3,-4],[3,-3],[13,-2],[1,1],[1,0],[5,2],[4,-1],[4,-4],[2,1],[3,0],[4,-2],[3,-2],[0,-3],[2,-3],[7,-5],[6,-3],[2,-3],[5,-3],[0,-1],[0,-2],[-1,-2],[-1,-3],[1,-1],[2,-1],[3,0],[2,1],[2,1],[3,3],[4,2],[5,3],[2,0],[2,-1],[1,-1],[2,-6],[2,8],[1,1],[2,-2],[3,-2],[3,-1],[1,-2],[4,-7],[6,1],[3,-1],[1,-1],[1,-2],[-2,-6],[-1,-8],[0,-1],[3,-3],[3,-3],[2,-2],[1,-2],[3,-2],[3,-1],[1,0],[2,-1],[4,-4]],[[4930,8035],[-1,-4],[-3,1],[0,1],[3,2],[1,0]],[[4998,5824],[1,-3],[1,-2],[-1,-8],[-1,-5],[-1,-5],[0,-2],[1,-3],[3,-4],[1,-2],[2,-4],[2,-4],[3,-5],[1,0],[0,-2],[0,-2],[-1,-18],[0,-4],[0,-3],[0,-6],[-1,-1],[-1,0],[0,-2],[0,-1],[2,-1],[0,-1],[-2,-1],[-1,-2],[1,-2],[-1,-2],[0,-1],[1,-1],[1,0],[2,3],[1,0],[1,0],[2,-5],[0,-2],[-1,-8],[-1,-6],[0,-8],[1,-5],[0,-2],[-1,-3],[-2,-3],[0,-2],[1,-4],[2,-4],[4,-6],[2,-7],[0,-3],[-2,-3],[-1,-2],[0,-4],[0,-24],[-3,-11],[0,-2],[1,-4],[0,-2],[2,-1],[1,-2],[0,-7],[-1,-7],[0,-4],[0,-2],[-2,-1],[0,-3],[0,-2],[0,-3],[1,-2],[1,-4],[2,-8],[1,-1],[0,-2],[0,-2],[1,-4],[2,-3],[3,-4],[2,0],[0,-3],[2,-4],[1,-2],[1,-1],[1,0],[0,-3]],[[5032,5535],[-2,-3],[-1,-3],[-1,-5],[-2,-6],[-6,-2],[-2,0],[-11,-1],[-11,-10],[-6,-4],[-4,-7],[-5,-4],[-4,-5],[-7,-3],[-12,-8],[-4,-3],[-4,-6],[-6,-7],[-3,0],[-4,7],[-4,3],[-9,5],[-7,1],[-3,3],[-1,0]],[[4914,5479],[2,0]],[[4683,5898],[-1,-1],[0,-4],[-1,-4],[-1,-3],[0,-1],[2,-4],[4,-5],[1,-1],[1,1],[2,4],[2,5],[2,2],[2,0],[1,-3],[2,-7],[2,-6],[0,-1],[1,-1],[1,0],[1,2],[1,1],[0,2],[4,9],[2,2],[1,1],[2,1],[3,-2],[4,-3],[6,-5],[2,0],[1,0],[1,6],[2,2],[3,3],[2,2],[2,0],[0,1],[0,3],[0,2],[-1,4],[0,2],[0,1],[2,0],[3,0],[2,-2],[2,-3],[2,-3],[1,-7],[1,-7],[3,-10],[0,-7],[-1,-8],[2,-1],[1,-1],[1,-1],[1,-6],[1,-2],[2,0],[2,-4],[2,-1],[0,-2],[0,-1],[-1,-2],[-1,-1],[-1,-3],[-1,-3],[-3,-9],[0,-1],[0,-1],[1,0],[2,0],[2,3],[2,-1],[2,-2],[1,-3],[0,-3],[-1,-4],[0,-4],[1,-8],[1,-7],[1,-3],[6,-7],[1,-2],[0,-3],[0,-4]],[[4764,5619],[-1,2],[-1,2],[-1,3],[-1,1],[-1,0],[-1,-2],[-1,-3],[0,-4],[0,-2],[-1,-2],[-2,-4],[0,-4],[-1,-4],[-2,0],[0,1],[-1,-1],[-2,-2],[-2,-1],[0,2],[-1,2],[-1,3],[-2,3],[-2,2],[-1,-1],[-2,0],[0,1],[0,1],[1,4],[1,4],[0,4],[0,4],[0,5],[-2,4],[0,2],[0,4],[0,3],[0,2],[-1,3],[0,3],[-1,1],[0,5],[0,5],[-1,1],[-1,2],[-1,2],[-1,2],[-1,0],[0,-1],[-1,0],[-1,4],[0,1],[-1,-2],[-7,-5],[0,2],[-1,3],[-1,1],[-3,-2],[-1,0]],[[4714,5673],[-2,0],[-1,-1],[-3,-7],[-2,-2],[-1,0],[-1,1],[-1,-1],[-1,1],[0,2],[1,2],[1,7],[4,8],[0,1],[-2,5],[-1,6],[0,6],[0,5],[-3,1],[-1,1],[0,1],[1,4],[1,4],[0,2],[0,1],[-2,4],[-3,8],[-3,8],[-2,7],[-2,4],[-2,4],[-1,4],[-2,1],[-5,0],[-7,-1],[-5,0],[-1,-4],[-6,-2],[-4,3],[-4,-2],[-2,-2],[0,-4],[-1,-5],[-1,-2],[-1,-2],[0,-2],[-1,-2],[-1,-5],[-2,-6],[-2,-4],[-3,-3],[-2,-6],[0,-3],[-2,-2],[-1,-1],[-2,1],[-1,0],[-2,-1]],[[4630,5705],[0,2],[1,5],[-1,3],[-3,5],[0,3],[-1,3],[-3,7],[-4,0],[1,6],[0,8],[-1,4],[0,5],[0,-1],[-2,-3],[-1,1],[-4,5],[-2,5],[0,3],[-1,2],[-1,-1],[-2,0],[-7,7],[-5,17],[0,4],[0,7],[0,2],[-2,-5],[-1,3],[-1,7],[-1,4],[-2,2],[-1,1],[-1,-2],[-1,-8],[-1,0],[-2,2],[1,6]],[[4582,5814],[1,3],[1,5],[5,19],[2,4],[1,2],[2,0],[4,2],[4,5],[1,1],[4,0],[5,1],[6,4],[0,5],[0,8],[0,3],[-2,2],[-2,2],[-1,3],[-1,2],[0,2],[2,2],[1,1],[2,0],[1,1],[1,2],[0,5],[1,5],[-2,6],[0,5]],[[4618,5914],[9,-1],[1,0],[4,-1],[3,0],[1,-1],[1,-1],[0,-2],[-1,-2],[1,-3],[1,-1],[1,1],[1,2],[0,1],[2,-1],[2,-4],[2,-1],[3,-2],[2,-1],[3,0],[1,-2],[3,-1],[4,3],[3,1],[4,0],[3,-1],[6,3],[3,-1],[2,-1]],[[4534,5936],[0,5],[-2,11],[2,5],[3,3],[1,-2],[0,-5],[2,-3],[4,-2],[4,2],[2,-1],[0,2],[1,4],[4,1],[6,1],[5,2],[4,0],[1,1],[-4,1],[-8,-2],[-8,-1],[-6,-6],[-2,1],[-3,6],[-1,7]],[[4539,5966],[8,1],[8,0],[9,-1],[5,0],[2,8],[4,4],[5,1],[2,0],[3,-1],[4,-7],[3,-1],[3,-2],[2,-3],[2,-3],[3,-1],[1,0],[2,1],[2,1],[4,1],[4,-4],[0,-4],[0,-4],[-5,-2],[-6,-4],[-6,2],[-6,5],[-4,3],[-1,2],[-3,2],[-2,2],[-2,2],[-1,1],[-1,-2],[-1,-2],[-1,-4],[-1,-2],[-6,-1],[-4,-1],[-3,-1],[-2,-1],[0,-9],[-6,0],[-5,0],[-6,0],[-6,-1],[-1,-2],[-2,-3]],[[4558,5822],[0,-1],[-2,0],[0,1],[0,1],[1,5],[1,-1],[0,-1],[0,-4]],[[4552,5821],[-2,-1],[-1,3],[0,1],[1,1],[1,2],[1,1],[1,1],[1,-5],[-1,-2],[-1,-1]],[[4563,5830],[0,-3],[-1,1],[-1,1],[1,4],[1,2],[1,-1],[1,0],[-1,-2],[0,-1],[-1,-1]],[[4558,5844],[-1,-2],[-2,1],[-1,2],[1,3],[1,4],[1,-1],[1,-7]],[[4568,5848],[-1,-1],[-1,1],[2,5],[1,1],[0,-4],[-1,-1],[0,-1]],[[4555,5868],[-1,-7],[-2,1],[-1,4],[0,2],[3,0],[1,0]],[[4582,5814],[-2,4],[1,8],[-1,-1],[-2,-6],[-1,0],[0,7],[-1,1],[-2,-1],[-2,4],[0,3],[0,4],[1,2],[0,1],[-1,1],[-2,-1],[0,1],[1,5],[5,4],[2,1],[3,1],[-2,3],[-3,2],[-2,-1],[-1,-3],[-2,0],[-2,6],[0,3],[1,4],[1,2],[6,0],[2,2],[1,0],[1,2],[0,1],[-1,0],[-2,-2],[-7,1],[-2,-2],[-4,-5],[-5,-4],[-3,2],[1,7],[-1,1],[-1,2],[-5,-3],[-4,4],[-1,4],[0,5],[2,4],[0,2],[-2,0],[-3,-2],[-8,8]],[[4535,5895],[2,1],[4,-1],[3,1],[2,2],[2,3],[3,0],[9,-1],[7,3],[5,6],[5,5],[7,0],[7,0],[10,0],[8,0],[9,0]],[[5266,5243],[0,2],[-2,3],[-2,0],[-2,1],[2,9],[1,8],[3,7],[1,1],[0,3],[2,10],[3,8],[-1,8],[1,14]],[[5242,5400],[1,0],[4,0],[1,-3],[0,-4],[-4,-13],[-1,-6],[-2,-5],[-1,0],[-5,3],[-1,2],[0,2],[0,5],[1,2],[2,1],[1,0],[1,6],[0,5],[1,4],[2,1]],[[5662,7231],[2,-1],[2,0],[1,1],[2,3],[2,0],[1,-3],[-2,-2],[-1,-1],[1,0],[1,-2],[2,1],[0,-3],[1,-2],[1,-1],[1,-1],[2,1],[3,1],[3,1],[2,1],[8,-1],[3,-3],[5,-1],[5,-2],[3,2],[4,1],[1,-1],[-1,-9],[1,-2],[1,-1],[1,0],[2,3],[3,2],[4,0],[4,6],[1,0],[-1,-3],[-1,-6],[0,-4],[-1,-3],[-2,-1],[-3,0],[-6,0],[-6,-1],[-11,-3],[-12,-1],[-1,1],[0,4],[0,2],[-1,2],[-4,1],[-3,3],[-13,4],[-3,1],[-5,-1],[-2,0],[-1,2],[-1,2],[0,7],[0,7],[1,1],[1,-2],[1,-1],[1,2],[0,4],[1,3],[1,-2],[0,-4],[2,-1]],[[5754,7227],[-1,-4],[-1,3],[1,3],[-2,5],[3,8],[0,3],[2,2],[-1,-6],[-1,-5],[1,-4],[1,-5],[-2,0]],[[5640,7268],[0,-2],[-3,1],[-1,3],[0,6],[0,3],[1,0],[1,-3],[3,-4],[-1,-4]],[[5773,7253],[-2,-1],[-1,0],[-1,3],[1,6],[-1,4],[0,2],[2,3],[1,3],[3,4],[7,5],[2,0],[0,-3],[-3,-10],[-2,-4],[1,-4],[-4,-1],[-3,-7]],[[5707,7280],[-1,-3],[-2,1],[1,1],[0,2],[0,2],[0,1],[0,1],[2,-3],[0,-2]],[[5734,7291],[-2,-1],[-1,-3],[-2,2],[0,3],[2,-1],[1,1],[0,2],[1,-1],[1,-2]],[[5773,7289],[0,-1],[-2,3],[0,1],[2,2],[1,-1],[0,-2],[-1,-2]],[[5681,7301],[0,-3],[0,-1],[-6,-2],[1,4],[0,1],[2,-2],[1,1],[0,1],[2,1]],[[5704,7296],[0,-1],[-2,4],[-1,2],[1,2],[3,-4],[-1,-3]],[[5748,7299],[-1,0],[1,3],[3,4],[4,3],[2,0],[2,-2],[-4,-3],[-1,-2],[-4,0],[-2,-3]],[[5718,7303],[-3,-1],[0,1],[1,1],[1,1],[1,1],[2,2],[2,3],[1,-2],[-2,-1],[-3,-5]],[[5686,7310],[-1,3],[0,2],[0,1],[1,0],[1,-4],[-1,-2]],[[5750,7313],[-3,-1],[1,4],[-2,4],[3,-2],[1,-3],[1,0],[-1,-1],[0,-1]],[[5702,7319],[-3,-5],[-1,1],[-1,2],[1,4],[2,2],[2,0],[-1,-3],[1,-1]],[[5709,7313],[-2,-2],[-2,3],[-1,5],[4,7],[2,0],[0,-2],[0,-7],[-1,-4]],[[5681,7322],[-1,-1],[-2,2],[0,3],[2,1],[1,-1],[0,-1],[0,-3]],[[5678,7335],[-1,-2],[0,4],[-1,2],[1,2],[1,1],[1,-1],[0,-3],[-1,-3]],[[5692,7343],[0,-6],[-1,0],[0,1],[0,3],[0,3],[1,-1]],[[5705,7339],[-3,0],[1,4],[1,1],[3,-2],[0,-1],[-2,-2]],[[5722,7345],[-1,0],[1,3],[2,4],[4,0],[3,2],[-1,-3],[-3,-3],[-5,-3]],[[5701,7349],[-1,-3],[-2,0],[-3,4],[-1,2],[0,2],[1,0],[1,-2],[4,-1],[1,-2]],[[5676,7348],[-2,-3],[0,5],[1,4],[2,0],[0,-2],[-1,-4]],[[5745,7362],[3,-2],[1,0],[2,-1],[0,-3],[-2,-1],[-4,-3],[-1,1],[-2,3],[-3,0],[-1,1],[1,3],[3,2],[3,0]],[[5580,7361],[3,-5],[-3,1],[-2,-4],[-3,5],[-2,4],[-1,2],[2,4],[2,-4],[2,-1],[2,-2]],[[5694,7359],[-1,-4],[-2,4],[-3,3],[-1,3],[-1,2],[0,3],[1,2],[1,0],[2,-4],[3,-1],[-1,-3],[1,-3],[1,-2]],[[5654,7368],[-1,-1],[-2,0],[-1,0],[0,2],[1,0],[0,2],[1,1],[1,0],[0,-1],[1,-3]],[[5572,7395],[0,-7],[2,-1],[3,-6],[0,-3],[-1,-1],[-4,2],[-1,-1],[-1,1],[-1,3],[0,1],[-1,2],[0,1],[-2,-3],[-1,0],[0,2],[1,7],[1,1],[1,-2],[1,1],[1,3],[0,4],[1,1],[1,-5]],[[5576,7392],[-1,-1],[-2,5],[-1,4],[1,0],[1,0],[0,-1],[0,-2],[1,-1],[1,-2],[0,-2]],[[5724,7385],[-2,-3],[-3,5],[-1,1],[2,2],[1,3],[0,4],[-3,5],[-1,4],[5,1],[3,-3],[1,0],[0,-3],[0,-1],[0,-10],[-1,-1],[0,-3],[-1,-1]],[[5574,7408],[-1,-1],[-1,0],[-1,0],[-1,-1],[1,5],[0,5],[2,4],[1,1],[1,-2],[0,-10],[-1,-1]],[[5685,7419],[-3,-1],[-1,0],[1,2],[-3,4],[0,4],[1,1],[2,-2],[0,-4],[3,-4]],[[5650,7428],[1,-6],[2,-3],[3,-2],[1,0],[6,-5],[6,-1],[1,-1],[0,-4],[2,-2],[0,-2],[-1,-3],[1,-7],[2,-7],[2,-3],[3,-1],[3,0],[0,-1],[0,-6],[-1,-3],[-1,0],[-1,0],[-1,2],[-2,1],[-1,2],[-3,3],[-1,2],[0,3],[-1,3],[-1,4],[-1,1],[-1,2],[0,1],[-4,1],[-4,0],[-3,2],[-1,6],[-1,2],[-2,2],[-1,2],[-3,5],[-3,4],[-3,2],[-3,2],[-2,-2],[-2,0],[0,2],[3,2],[4,5],[4,2],[1,0],[3,-4]],[[5660,7437],[-1,-2],[-2,1],[-2,6],[5,-5]],[[5663,7439],[-1,0],[1,4],[2,3],[-1,-4],[-1,-3]],[[5733,7449],[0,-3],[3,-6],[2,-4],[0,-3],[0,-1],[-2,2],[-1,0],[1,-2],[1,-2],[-2,-1],[-3,0],[-6,3],[-1,3],[3,5],[1,2],[-2,-1],[-3,-5],[-5,2],[-1,2],[-1,2],[2,5],[3,0],[2,1],[2,1],[0,3],[5,0],[2,-3]],[[5557,7455],[1,-3],[-4,2],[-2,3],[-2,7],[-5,8],[0,2],[2,2],[4,1],[1,-1],[1,-1],[0,-2],[-2,-3],[0,-1],[1,-3],[0,-1],[1,-6],[1,-2],[2,-1],[1,-1]],[[5706,7487],[-1,-2],[-1,-4],[0,-4],[-2,0],[-1,1],[0,1],[0,3],[-1,0],[0,-3],[-1,-1],[-2,0],[-1,1],[0,4],[-1,3],[0,2],[5,0],[2,-3],[2,2],[0,2],[2,1],[0,-3]],[[5713,7512],[-3,-1],[-4,5],[4,1],[1,-1],[1,-2],[1,-2]],[[5688,7523],[-4,-2],[-4,4],[0,2],[2,5],[1,1],[3,0],[2,-3],[0,-2],[-1,-2],[1,-3]],[[5723,7530],[-1,2],[-4,4],[-10,3],[-5,3],[-2,-1],[-4,4],[-3,-2],[-6,-6],[-3,1],[-3,4],[-3,0],[-2,-2],[-4,-7],[-5,-4],[-3,2],[-5,0],[-1,-4],[1,-3],[3,-5],[-2,-4],[1,-3],[2,-1],[3,0],[5,-4],[2,-5],[2,-6],[-3,4],[-2,4],[-3,1],[-4,3],[-3,1],[-2,-2],[-1,-3],[3,-4],[3,-3],[1,-3],[1,-5],[0,-2],[-1,-1],[-3,3],[-5,12],[-7,2],[-1,-2],[1,-7],[1,-2],[6,-7],[0,-1],[-1,-1],[-7,4],[-2,6],[0,7],[-6,5],[-6,6],[-1,5],[1,2],[1,4],[-3,-1],[-2,-2],[-3,-3],[0,-4],[0,-3],[-1,-5],[-1,-9],[1,-5],[7,-14],[2,-10],[2,-3],[3,-5],[4,-7],[1,-4],[1,-7],[-3,-4],[-1,0],[-1,2],[1,4],[0,3],[-5,4],[-2,-1],[-2,-3],[1,-5],[2,-3],[0,-5],[3,0],[-4,-5],[-3,-3],[-4,0],[-2,0],[-1,-1],[2,-1],[2,-1],[2,-2],[7,-4],[3,-4],[3,0],[4,-8],[5,-2],[3,-8],[5,-2],[3,-3],[1,-2],[1,-5],[0,-11],[1,-8],[0,-2],[0,-4],[-1,-2],[-2,0],[-2,6],[-4,6],[-5,7],[-1,1],[-1,1],[-2,-3],[-6,-2],[-3,-2],[-1,-1],[-1,-1],[2,-2],[1,-3],[0,-5],[2,-5],[2,-2],[2,0],[1,-1],[1,-2],[1,-2],[1,-2],[0,-2],[-7,-3],[-1,-2],[-1,-1],[-2,2],[0,4],[-2,3],[-2,2],[-3,1],[-2,3],[-1,-3],[1,-8],[2,-6],[4,-16],[2,-9],[0,-5],[-1,-8],[2,-5],[2,-6],[-2,0],[-1,2],[-2,3],[-4,9],[-2,6],[-2,0],[-3,-1],[-3,-12],[0,-7],[-2,2],[-1,2],[0,8],[0,3],[-4,10],[-2,1],[-1,4],[-1,4],[-2,-1],[-2,-2],[0,-5],[0,-5],[-1,-4],[-5,7],[-4,13],[0,6],[3,7],[0,4],[-3,9],[-5,6],[-2,1],[-1,7],[-3,3],[-1,1],[-1,2],[1,2],[4,6],[3,10],[1,0],[3,-2],[3,1],[3,5],[2,3],[3,0],[8,-8],[9,-4],[4,-4],[3,-4],[1,0],[2,-1],[0,3],[-1,2],[2,2],[5,0],[1,1],[0,2],[-1,3],[-1,1],[-2,0],[-1,1],[-2,-1],[-2,2],[-2,2],[-1,1],[-4,3],[-5,6],[-1,-3],[-2,-2],[-2,0],[-7,3],[-5,-2],[-2,-1],[-2,0],[-2,-1],[-3,-1],[-2,5],[-1,4],[-1,1],[0,-4],[-1,-3],[-3,-2],[-2,3],[-2,7],[-1,8],[-4,7],[-2,2],[-1,4],[1,3],[3,1],[5,-3],[1,0],[1,2],[0,3],[-1,3],[-1,0],[-1,0],[-3,0],[-4,-1],[-2,1],[-1,2],[-3,5],[-3,6],[-5,4],[-3,13],[-2,5],[-3,4]],[[5582,7537],[4,0],[1,0],[5,1],[2,2],[2,0],[3,-2],[1,1],[4,3],[5,10],[1,1],[4,0],[2,1],[1,0],[5,-2],[2,0],[3,1],[4,3],[1,7],[0,1],[2,1],[2,0]],[[5731,7587],[2,-2],[2,-1],[0,-2],[2,-2],[1,0],[1,-5],[0,-7],[-1,-2],[-1,-1],[-6,-6],[0,-5],[0,-3],[0,-2],[0,-2],[0,-2],[0,-2],[-3,-4],[-1,-4],[-2,-4],[-1,-1],[-1,0]],[[3285,5876],[-1,-1],[0,3],[0,3],[1,5],[2,3],[1,-1],[0,-10],[-3,-2]],[[3714,8685],[-3,-7],[-3,1],[-2,3],[-3,2],[-3,-1],[0,2],[11,7],[5,2],[0,-3],[-1,-3],[-1,-3]],[[3971,8958],[-4,0],[-2,5],[1,5],[5,1],[2,-3],[-1,-5],[-1,-3]],[[3583,9190],[-5,-2],[-1,0],[-1,2],[-2,7],[0,3],[0,4],[-1,3],[4,4],[3,0],[5,-1],[7,-3],[-1,-1],[-1,-2],[-5,-2],[-1,-6],[0,-2],[0,-2],[-1,-2]],[[3535,9213],[9,-5],[10,-3],[1,-2],[1,-2],[0,-1],[0,-1],[-1,-1],[1,-2],[2,-1],[0,-2],[-2,-3],[-4,-4],[-18,-7],[-7,-1],[-16,-5],[-5,0],[-1,0],[-3,2],[-4,3],[-2,1],[-1,2],[0,2],[3,0],[5,0],[6,2],[-2,1],[-1,1],[-1,2],[-3,0],[-2,1],[-4,1],[-10,0],[-7,2],[-2,1],[-1,2],[-2,3],[2,11],[2,3],[3,1],[9,-3],[1,1],[-9,4],[-4,3],[-1,2],[0,2],[0,2],[0,2],[1,1],[2,2],[9,4],[10,-1],[18,-5],[2,0],[6,-4],[10,-11]],[[3564,9265],[-3,0],[-9,1],[-1,1],[0,1],[1,3],[4,1],[5,-2],[4,-3],[1,-1],[-2,-1]],[[4293,9269],[1,-4],[0,-1],[0,-2],[-1,-1],[-1,0],[3,-3],[0,-1],[1,-1],[-2,-3],[-11,-3],[-3,-1],[-4,-4],[-5,-3],[-1,0],[-2,3],[-7,3],[-14,-2],[-17,-3],[-5,-1],[-3,1],[-1,1],[0,1],[2,5],[0,1],[4,2],[3,4],[-1,4],[1,6],[2,1],[7,-2],[4,0],[7,-1],[10,1],[8,3],[14,7],[3,0],[2,-3],[1,-1],[4,-2],[1,-1]],[[3513,9276],[-3,-1],[-7,3],[-2,1],[0,2],[0,1],[2,3],[5,5],[3,0],[2,-2],[2,-4],[0,-2],[0,-2],[0,-2],[-1,-1],[-1,-1]],[[3471,9376],[-4,-3],[-3,-3],[-7,-6],[-1,-1],[-2,1],[-1,2],[-3,0],[-1,2],[-1,1],[-2,0],[-3,0],[-3,0],[-2,3],[4,2],[2,2],[9,1],[3,-1],[2,0],[2,0],[5,2],[1,1],[5,-1],[0,-2]],[[4500,9527],[2,-6],[1,-6],[3,-3],[8,0],[2,-6],[-5,-3],[-21,1],[-9,0],[-6,4],[0,7],[1,7],[6,4],[5,-3],[6,2],[7,2]],[[4483,9564],[-3,-2],[-11,24],[0,9],[1,6],[5,1],[4,-4],[2,-13],[2,-21]],[[3009,9638],[-10,-1],[-10,2],[-3,2],[0,3],[2,1],[5,1],[4,0],[3,-1],[7,-1],[5,-2],[3,0],[0,-3],[-6,-1]],[[4501,9656],[-6,0],[-2,1],[2,3],[7,9],[3,0],[3,-1],[2,-4],[-3,-4],[-6,-4]],[[4472,9675],[-4,-2],[-2,6],[-2,8],[-1,9],[6,5],[3,1],[2,-1],[-1,-4],[0,-8],[2,-6],[-3,-8]],[[4510,9782],[-11,-7],[-18,1],[-10,3],[-3,4],[4,5],[12,4],[16,3],[14,-2],[2,-5],[-6,-6]],[[4481,9898],[-3,-2],[-7,1],[-9,5],[-7,4],[0,5],[3,3],[5,0],[7,-4],[7,-6],[4,-6]],[[3753,9912],[-5,-1],[-12,6],[-19,6],[-16,4],[-15,11],[-2,3],[3,4],[13,0],[11,2],[27,-7],[14,-5],[5,-5],[-1,-9],[-3,-9]],[[4168,9997],[26,-3],[14,-4],[3,0],[19,-2],[19,-2],[30,-5],[4,-1],[-3,-2],[-8,-1],[-38,-1],[-70,-2],[-40,-4],[-13,-1],[-1,-5],[5,-1],[9,1],[32,6],[11,1],[22,-1],[29,-2],[11,1],[21,-1],[23,2],[29,4],[7,-8],[11,-9],[8,1],[7,0],[3,-3],[3,-1],[8,1],[25,-3],[17,-4],[6,-2],[3,-3],[2,-2],[-3,-3],[-10,-4],[-14,-5],[-18,-3],[-20,-3],[-159,-7],[-5,-2],[-4,-4],[3,-6],[7,-1],[17,4],[30,3],[22,0],[53,-3],[16,-7],[8,-10],[18,2],[4,2],[3,3],[2,3],[2,4],[2,2],[2,2],[4,1],[11,1],[27,1],[7,0],[5,-5],[1,-3],[0,-4],[0,-4],[-1,-6],[-2,-5],[-8,-10],[-6,-5],[-6,-3],[-13,-9],[-4,-2],[-14,-10],[-4,-5],[0,-3],[2,-1],[4,4],[2,2],[3,2],[20,6],[4,2],[14,8],[8,2],[7,3],[4,2],[21,15],[10,4],[12,0],[2,-7],[13,-1],[6,0],[9,-2],[4,-1],[7,-1],[8,-2],[6,2],[2,1],[6,6],[8,4],[8,6],[3,2],[4,1],[4,1],[11,2],[3,0],[7,0],[27,-1],[15,-1],[21,-4],[14,-2],[7,-2],[10,-4],[7,-5],[4,-1],[0,-1],[-3,-2],[-19,-7],[-7,-4],[-18,-9],[-9,-3],[-10,-1],[-11,0],[-7,-1],[-1,-1],[5,-4],[2,-2],[0,-2],[-5,-4],[-2,0],[-20,-3],[-9,-4],[-13,0],[-9,0],[-12,-4],[5,-4],[4,-1],[14,-4],[0,-2],[-7,-3],[-8,-5],[-11,-3],[-4,0],[-5,0],[-5,0],[-10,-1],[-9,0],[-18,2],[-9,2],[-5,1],[-6,0],[-3,-1],[-9,-6],[-5,-4],[-3,-4],[-1,-4],[0,-5],[1,-3],[2,-1],[2,-1],[4,-1],[9,1],[4,-1],[1,-1],[2,-3],[0,-2],[-2,-4],[-1,-5],[-1,-5],[0,-3],[4,0],[2,0],[2,-1],[2,-2],[1,-2],[2,-3],[-1,-2],[-2,-1],[-6,-2],[-12,-3],[-2,-1],[-1,-2],[0,-3],[-2,-3],[-2,-3],[-2,-1],[-5,-1],[-5,0],[-6,-1],[-14,-9],[-1,-1],[6,-2],[-1,-3],[-6,-10],[-2,-5],[-1,-7],[-3,-5],[-3,-5],[-3,-5],[-4,-7],[1,-4],[4,-4],[6,3],[7,9],[7,3],[8,-1],[7,-1],[9,-4],[8,-2],[6,-3],[3,-2],[3,-3],[0,-2],[-5,-2],[-2,1],[-12,5],[-5,2],[-8,-2],[-7,-2],[6,-10],[7,-5],[11,-2],[6,-2],[5,-3],[3,-1],[5,0],[6,3],[9,0],[4,-1],[3,-3],[1,-4],[0,-7],[-1,-6],[-1,-3],[-4,-5],[-2,-1],[-4,0],[-3,1],[-4,2],[-5,1],[-9,2],[-10,3],[-6,1],[-12,-1],[-12,-2],[-1,-2],[-18,-9],[-4,0],[-5,3],[-7,3],[-4,0],[-6,-4],[-1,-1],[0,-2],[4,-3],[2,0],[2,-1],[8,-1],[4,-1],[3,-10],[5,-6],[3,-1],[2,-1],[6,1],[8,2],[3,-2],[6,-2],[4,0],[4,0],[5,-1],[7,-6],[-3,-7],[4,-6],[7,-6],[2,-2],[0,-4],[0,-2],[1,-3],[1,-2],[1,-4],[1,-6],[-1,-5],[-1,-4],[-3,-3],[-4,-2],[-3,1],[-3,2],[-4,3],[-5,3],[-7,1],[-12,-9],[-5,-1],[-5,-1],[-4,-4],[-7,-2],[-6,1],[-10,5],[4,-3],[5,-4],[3,-2],[3,0],[3,0],[4,2],[8,4],[3,0],[2,0],[1,-1],[2,-4],[2,-6],[0,-4],[-3,-5],[-2,-2],[-2,-1],[0,-1],[5,-1],[7,5],[2,7],[3,7],[6,3],[6,-3],[6,-7],[7,-13],[3,-1],[4,-3],[2,-4],[-1,-5],[-1,-3],[-1,-2],[-1,-2],[-3,0],[-5,-1],[-11,1],[-6,0],[1,-4],[-12,-4],[-13,-2],[-13,3],[-10,5],[3,7],[2,7],[-5,5],[-1,0],[2,-8],[-2,-2],[-5,-4],[-4,-1],[-1,-1],[2,-1],[1,-2],[1,-2],[-1,-2],[-2,-3],[-1,-2],[0,-1],[2,-2],[4,-2],[4,-2],[19,0],[8,-1],[18,-6],[1,-1],[-3,-10],[-2,-9],[-4,-2],[-19,0],[-6,-2],[-9,-4],[-9,-5],[-4,0],[-18,4],[-7,3],[-14,9],[-11,13],[-6,-6],[-3,-2],[-3,-2],[-3,0],[-3,1],[-3,2],[-6,5],[-7,4],[-4,3],[-1,-1],[3,-3],[4,-3],[11,-9],[3,-2],[0,-2],[-7,-2],[-8,-3],[-3,-2],[-6,-6],[-2,-1],[-9,-1],[-3,0],[-7,4],[-10,2],[-6,1],[-8,4],[3,-4],[16,-5],[1,-2],[-3,-3],[-2,-2],[-4,0],[-5,1],[-6,0],[-6,-1],[-2,-2],[1,-1],[1,-1],[2,-2],[2,0],[4,4],[4,0],[8,-1],[9,3],[7,2],[5,0],[17,4],[4,5],[6,2],[13,2],[12,-1],[7,-1],[5,-4],[7,-4],[6,-3],[7,-2],[4,-5],[11,-5],[7,-2],[4,-2],[1,-12],[0,-5],[-2,-13],[-5,-3],[1,-7],[-2,-6],[-5,2],[-6,4],[-14,6],[-13,3],[-5,4],[-6,3],[-8,10],[-5,14],[-3,7],[-4,0],[-6,-2],[-5,-2],[-2,-3],[-17,-4],[-6,-3],[-3,0],[-13,-5],[5,-2],[2,0],[6,1],[3,1],[11,5],[9,1],[4,1],[7,3],[4,1],[1,-1],[0,-1],[4,-17],[-2,-4],[-3,-2],[-8,-3],[-3,-1],[3,-3],[7,2],[5,3],[3,-1],[4,-4],[5,-2],[13,-7],[5,-3],[9,-3],[9,-5],[2,-2],[9,-2],[2,-1],[3,-8],[3,-1],[9,-1],[-2,-3],[-8,-7],[-4,-2],[-2,-2],[1,-2],[0,-5],[2,-7],[2,7],[1,3],[2,1],[2,0],[6,4],[5,-2],[2,-8],[1,-8],[-1,-6],[1,-11],[-1,-3],[2,-3],[1,-12],[2,-4],[-3,-3],[-9,-2],[-3,2],[-9,-1],[0,3],[-1,4],[0,2],[0,2],[-1,12],[-2,-3],[0,-2],[-1,-3],[-1,-13],[-3,-3],[-7,1],[-7,-1],[-3,1],[-13,6],[-5,5],[-5,8],[-2,8],[-1,7],[-4,6],[-5,4],[-6,4],[-7,3],[-6,3],[-5,4],[-6,4],[-6,2],[-10,1],[-13,0],[-9,3],[-2,-1],[-2,-1],[2,-4],[10,-2],[8,0],[10,0],[7,-1],[2,-2],[2,-4],[1,-6],[-2,-5],[-8,-5],[-4,-3],[-12,-5],[-4,-1],[-9,0],[-8,1],[-10,2],[-5,0],[-12,1],[-2,-1],[3,-3],[5,-1],[3,-2],[0,-3],[-1,-5],[-1,-3],[-2,-3],[-8,-4],[-3,-2],[-14,-5],[-1,-1],[3,0],[9,2],[3,0],[14,-4],[12,0],[24,4],[2,0],[1,-1],[2,-1],[1,-2],[-2,-3],[-5,-2],[-8,-2],[-4,-2],[-4,-2],[-6,-5],[-2,-6],[7,-2],[3,3],[4,6],[3,3],[7,3],[10,-2],[7,2],[15,6],[2,0],[22,-3],[20,-7],[10,-2],[14,-2],[25,1],[2,-1],[-1,-2],[-2,-2],[-4,-3],[-5,-2],[-3,0],[-2,-2],[-6,-1],[-2,-1],[2,-5],[-1,0],[-5,0],[-9,-3],[-7,0],[-1,0],[1,-2],[1,-2],[2,-3],[-1,-2],[-3,-1],[-3,-1],[-8,2],[-1,0],[1,-2],[1,-2],[0,-2],[-2,-3],[-5,-1],[-8,-6],[-3,-1],[-8,-1],[-1,-1],[3,-4],[0,-1],[-5,-5],[-8,-2],[-1,-2],[-1,-4],[0,-1],[-2,-2],[-7,-4],[-5,-3],[-3,-1],[-3,-3],[-4,-2],[-5,0],[-4,-1],[-8,-3],[-5,-1],[-16,-5],[-8,-1],[-6,-2],[-14,-5],[-6,-1],[-5,-2],[-5,-1],[-8,1],[-4,0],[-3,0],[-2,-2],[-4,-4],[-4,0],[-11,3],[0,-2],[3,-3],[0,-3],[-6,-2],[-4,-1],[-5,1],[-7,3],[-9,6],[-11,9],[-5,3],[0,-3],[1,-3],[2,-3],[1,-2],[-2,-1],[-1,-1],[-2,0],[3,-4],[2,-5],[0,-4],[-3,-4],[-3,-2],[-2,-1],[-13,-10],[-3,-1],[-2,-1],[-1,-2],[-4,-8],[-2,-3],[-3,-3],[-1,0],[0,-2],[0,-2],[-1,-3],[-2,-5],[-8,-13],[-6,-13],[-2,-4],[-2,-2],[-2,1],[-3,0],[-1,-3],[-1,-4],[-2,-3],[-1,-2],[-13,-9],[-3,-1],[-3,1],[-3,-1],[-7,5],[-1,2],[-5,4],[0,-2],[1,-1],[1,-2],[1,-2],[4,-11],[-3,-2],[-2,-2],[-7,-4],[-6,-7],[-3,-2],[0,5],[0,2],[-4,3],[0,-2],[0,-2],[-3,-8],[-1,-1],[-1,0],[-3,-1],[-3,1],[-3,3],[-1,2],[-5,-5],[-2,0],[0,-4],[-3,-3],[-3,-2],[-4,0],[-2,-2],[-6,2],[-1,5],[4,6],[2,2],[-1,3],[1,4],[8,13],[6,6],[0,1],[-8,1],[-7,2],[-6,1],[-3,0],[4,-4],[7,-4],[-3,-3],[-3,-4],[-3,-9],[-2,-4],[-7,4],[-3,2],[2,-5],[6,-5],[0,-2],[0,-5],[-12,-5],[-12,-1],[-9,-2],[-15,-1],[-6,0],[-1,-2],[15,-9],[2,-2],[-2,-3],[-3,-2],[-5,-6],[-2,-2],[-7,-3],[-11,3],[-6,-2],[-6,2],[0,-4],[2,-3],[2,-7],[3,1],[5,2],[4,-5],[2,-9],[5,-5],[2,-3],[0,-3],[-2,-3],[-6,-5],[-6,-1],[0,-4],[-2,-2],[-6,1],[-2,1],[-3,1],[-11,1],[11,-7],[4,-3],[2,2],[4,0],[5,-1],[-1,-12],[3,-10],[0,-2],[-6,-5],[0,-6],[-4,-1],[-4,0],[0,-6],[-2,-3],[0,-3],[1,-2],[-3,-3],[-2,-5],[-3,-4],[-2,0],[-5,0],[-6,1],[-5,5],[-2,1],[-2,2],[1,-4],[1,-2],[5,-3],[8,-5],[0,-3],[-2,-2],[-6,-9],[-1,0],[-3,-2],[-7,1],[-3,1],[-9,-1],[-3,1],[-2,-1],[2,-2],[5,-2],[6,-3],[9,-1],[-1,-4],[-2,-2],[1,-4],[-1,-3],[0,-3],[-2,-8],[2,-6],[3,-2],[0,-4],[1,-5],[-4,-5],[-3,0],[-5,-1],[-1,-2],[7,-2],[-1,-4],[-2,-5],[-2,-10],[-4,-17],[-2,-17],[-9,-14],[-3,-1],[-1,0],[-4,1],[-7,3],[-6,1],[-3,0],[-1,-2],[3,-2],[5,-1],[3,-2],[7,-2],[2,-3],[2,-3],[0,-2],[0,-2],[1,-12],[-3,-4],[-3,-3],[-8,0],[-1,1],[-8,4],[0,-2],[6,-5],[2,-2],[-1,-1],[-3,0],[-3,-2],[-6,1],[0,3],[2,2],[-3,0],[-3,-1],[-2,0],[-1,0],[-1,1],[-1,6],[1,2],[5,7],[2,4],[-2,1],[-3,-3],[-4,-7],[-1,-4],[-3,0],[-5,2],[-16,8],[1,6],[-1,4],[5,1],[3,2],[3,2],[4,4],[3,7],[-1,1],[-9,-9],[-5,-3],[-3,-1],[-1,2],[-5,3],[-3,1],[-6,2],[-1,1],[-2,1],[-3,9],[3,12],[3,3],[1,4],[1,5],[-1,2],[-2,-1],[0,-2],[0,-2],[-1,-2],[-8,-4],[-8,-4],[-4,-3],[-3,-3],[-1,-2],[-3,0],[-4,-1],[-3,-1],[-4,1],[-3,2],[-3,1],[-4,-2],[-2,0],[0,-1],[2,-4],[-3,-1],[-5,0],[-3,1],[-2,2],[-1,2],[1,3],[8,5],[4,3],[-3,1],[-8,-1],[-1,1],[-5,0],[0,7],[-1,2],[-1,1],[-1,2],[-2,1],[-1,1],[-9,1],[-1,5],[-1,4],[-2,5],[-4,2],[-2,2],[1,3],[1,3],[-2,1],[-1,2],[0,2],[-2,4],[0,3],[2,2],[5,4],[2,1],[0,1],[6,2],[-5,2],[-3,0],[-2,0],[-2,-3],[-2,-3],[-8,0],[-1,1],[0,4],[0,4],[3,4],[-4,3],[-3,0],[-4,3],[-3,2],[-3,3],[-3,3],[-1,0],[1,3],[1,3],[0,6],[-2,2],[3,5],[4,6],[8,8],[-9,-4],[-7,-8],[-1,-1],[-1,2],[-2,5],[-2,2],[-1,2],[-4,2],[-2,3],[-2,4],[-3,5],[-5,11],[-8,11],[-2,7],[2,9],[-2,5],[7,3],[11,3],[5,3],[4,0],[6,1],[3,2],[-4,0],[-3,0],[0,1],[1,2],[1,3],[-2,0],[-6,-5],[-10,-4],[-8,-2],[-1,0],[-3,-1],[-1,0],[-1,0],[-3,4],[-1,2],[5,6],[4,9],[5,5],[3,1],[6,0],[2,-1],[-1,4],[0,1],[5,2],[5,1],[4,-1],[2,-3],[3,-8],[5,-2],[-1,3],[-2,5],[-1,7],[-2,3],[-3,1],[-6,-1],[-3,5],[-1,2],[0,3],[-4,7],[-1,3],[-2,5],[-1,0],[1,-6],[2,-4],[3,-9],[1,-4],[-2,-3],[-3,-3],[-3,-2],[-6,-2],[1,5],[1,4],[-3,-1],[-3,-3],[-1,-5],[-2,-4],[-6,-10],[-2,-6],[-2,-3],[-3,0],[-2,2],[-2,5],[0,4],[0,10],[0,5],[-1,7],[-3,15],[-1,6],[-5,3],[-2,4],[-1,3],[1,1],[1,1],[8,4],[6,5],[7,8],[3,3],[10,2],[4,0],[0,1],[-1,1],[-7,0],[-9,-4],[-2,-1],[-4,-5],[-3,-3],[-8,-6],[-6,0],[-6,8],[-6,-2],[-5,1],[-1,1],[-1,10],[3,12],[-3,0],[-1,1],[-2,2],[-1,1],[1,2],[9,5],[14,11],[6,5],[4,1],[3,3],[3,4],[1,2],[2,2],[4,2],[5,2],[7,7],[1,2],[-2,1],[-3,-3],[-7,-5],[-5,-4],[-16,-14],[-8,-5],[-3,-4],[-3,-3],[-4,-2],[-3,-1],[-7,-1],[-4,-2],[-2,1],[-1,7],[1,4],[0,4],[2,6],[2,4],[1,2],[1,2],[5,4],[3,2],[2,4],[12,1],[4,0],[1,1],[1,1],[-1,1],[-3,1],[-10,0],[-9,0],[-4,1],[-2,0],[-3,1],[-4,2],[-5,9],[2,11],[0,5],[7,5],[4,1],[5,4],[7,5],[9,4],[4,1],[4,-1],[13,-5],[7,-1],[5,1],[8,-1],[13,-8],[3,1],[-1,2],[-15,8],[0,2],[4,1],[4,2],[-2,1],[-10,-1],[-3,-2],[-9,-1],[-5,2],[-5,1],[-6,3],[-6,-1],[-3,-1],[-7,-2],[-2,0],[-12,-11],[-5,-2],[-4,1],[3,6],[0,3],[0,3],[1,4],[7,8],[4,8],[1,5],[3,1],[4,-1],[13,-3],[11,-4],[7,-1],[5,0],[3,1],[1,2],[1,2],[0,3],[1,1],[2,1],[3,5],[1,4],[-1,2],[-2,-1],[-5,-1],[0,-1],[-5,-6],[-4,-1],[-11,-2],[-5,0],[-9,3],[-2,1],[0,1],[-11,0],[-4,-1],[-2,1],[1,3],[4,3],[4,12],[4,3],[8,2],[9,0],[14,-9],[5,-1],[4,1],[9,3],[2,1],[3,4],[5,6],[-1,2],[-6,-4],[-3,-1],[-3,0],[3,12],[1,8],[1,2],[8,0],[11,1],[2,2],[0,1],[-4,1],[-2,2],[-4,0],[-5,-2],[-6,0],[0,4],[5,8],[0,3],[2,8],[0,3],[3,4],[7,2],[3,2],[0,2],[-4,6],[1,2],[3,1],[2,2],[-1,0],[-3,1],[-5,-1],[-6,-1],[-4,2],[-4,1],[-2,0],[-7,-4],[-2,0],[-3,1],[-18,3],[-2,1],[-7,6],[-5,3],[-7,4],[-10,3],[-11,2],[-7,2],[-3,3],[-6,6],[-4,5],[-1,2],[2,3],[3,2],[5,2],[9,-1],[4,0],[5,-2],[4,0],[8,0],[8,-1],[5,-1],[6,-3],[17,-10],[7,-4],[4,0],[12,-4],[3,0],[5,2],[0,1],[-1,1],[-6,1],[-7,4],[-4,4],[0,5],[0,3],[1,2],[1,5],[-4,3],[-3,1],[-7,4],[-1,1],[4,0],[3,0],[8,-2],[3,0],[3,0],[0,1],[-4,3],[-5,4],[-12,1],[-7,-1],[-5,2],[-5,2],[-4,1],[-6,-2],[-4,0],[-3,1],[-3,7],[1,3],[2,1],[2,2],[1,3],[4,2],[22,6],[6,4],[-1,1],[-3,-1],[-5,-2],[-3,0],[-13,2],[-2,-1],[-5,-3],[-7,-4],[-3,0],[-5,3],[0,1],[-1,2],[5,3],[1,1],[4,4],[-1,2],[-5,-1],[-1,1],[1,3],[-1,4],[-1,4],[-5,6],[-1,1],[-2,2],[-3,8],[1,2],[3,1],[0,1],[-7,-1],[0,-2],[1,-2],[1,-2],[0,-4],[1,-2],[3,-4],[2,-1],[3,-4],[2,-5],[-1,-3],[-2,-2],[-4,-3],[-2,-2],[0,-3],[-3,-2],[-2,1],[-2,0],[2,-4],[1,-3],[-1,-4],[-4,-3],[-2,0],[-4,-2],[-10,-1],[-4,1],[-7,2],[-7,1],[-4,2],[-4,5],[-2,4],[0,4],[1,3],[3,2],[2,10],[4,9],[10,9],[2,4],[1,1],[0,2],[-1,1],[-12,-12],[-7,-1],[-2,3],[0,4],[2,1],[5,0],[3,2],[-4,4],[-4,1],[-1,1],[4,3],[9,0],[3,2],[3,2],[4,4],[1,3],[0,3],[0,2],[0,3],[0,2],[-1,3],[-2,3],[-6,2],[-2,-3],[-2,-1],[-2,0],[-2,1],[-3,0],[-2,2],[-3,0],[-1,1],[0,3],[0,3],[2,2],[4,1],[3,2],[2,4],[0,3],[-1,4],[-3,4],[-6,-4],[-3,0],[0,2],[-1,2],[-2,3],[-4,1],[-3,2],[0,2],[1,2],[1,2],[2,5],[2,0],[2,0],[-1,4],[-2,4],[-2,2],[0,1],[0,1],[-2,3],[-1,1],[-3,6],[-2,1],[-3,2],[-3,0],[-4,-2],[-8,-1],[-7,-1],[-1,0],[3,2],[5,2],[6,2],[2,3],[0,3],[0,3],[-2,3],[2,1],[6,2],[2,0],[3,2],[-7,5],[-8,4],[-2,1],[-2,2],[-1,3],[-3,3],[-3,4],[-5,3],[-12,5],[-5,4],[-3,5],[-2,3],[-2,2],[-9,4],[-1,2],[9,5],[1,2],[-4,6],[-4,4],[-4,2],[-6,1],[-5,2],[-6,3],[-5,2],[-7,2],[-13,6],[-19,6],[-9,3],[-5,2],[-7,0],[-13,3],[-11,1],[-7,0],[-2,0],[-5,4],[-8,2],[-5,-1],[-5,-4],[-6,-3],[-3,-1],[-5,4],[-2,2],[-3,1],[-2,-1],[-4,-3],[-4,-2],[-6,-3],[-5,-1],[-7,0],[-1,-1],[-3,0],[-3,1],[-3,1],[-3,3],[-2,1],[-2,0],[-5,-1],[-7,-4],[-3,-1],[-2,1],[-3,1],[-6,3],[-3,0],[-3,-1],[1,-3],[6,-6],[5,-4],[-5,-1],[-36,6],[-5,2],[-7,3],[-5,2],[-10,5],[-7,3],[-3,3],[0,1],[2,2],[15,8],[5,1],[12,2],[3,1],[1,1],[-3,1],[-16,0],[-13,1],[-12,3],[-2,1],[-2,1],[-2,3],[1,3],[3,3],[1,2],[1,1],[-15,-7],[-6,-3],[-5,1],[-3,1],[-2,1],[0,2],[1,1],[1,1],[-8,3],[-3,3],[-1,2],[3,3],[3,2],[2,1],[7,1],[27,2],[19,-2],[6,7],[4,2],[13,2],[20,0],[13,-1],[7,-2],[9,-3],[0,1],[-2,3],[0,3],[3,4],[2,3],[-1,2],[-4,3],[-7,4],[-4,0],[-4,0],[-5,-3],[-10,-5],[-5,-1],[-8,0],[-4,0],[-4,1],[-7,3],[-2,1],[-3,-2],[-4,-3],[-3,-2],[-3,-1],[-4,0],[-4,0],[-17,4],[-4,2],[0,4],[-6,3],[-6,0],[0,1],[7,5],[6,2],[-1,0],[-8,0],[-6,-2],[-3,0],[-7,-1],[-8,2],[-3,1],[-4,2],[-4,2],[-11,2],[-3,1],[-2,2],[-10,5],[-5,4],[-1,3],[7,5],[0,1],[-3,2],[-1,1],[1,2],[6,5],[2,2],[10,2],[10,4],[4,1],[4,0],[13,0],[4,1],[4,2],[6,2],[12,3],[27,5],[2,0],[0,1],[-2,3],[-1,1],[6,2],[12,3],[9,2],[5,0],[5,1],[6,2],[4,0],[21,1],[10,-1],[4,0],[3,1],[4,2],[8,6],[3,4],[4,5],[5,9],[3,9],[3,8],[2,5],[1,2],[4,2],[5,2],[8,1],[-1,1],[-3,1],[-3,1],[-3,0],[-6,-2],[-6,-2],[-7,1],[-5,-1],[-4,-2],[-7,-1],[-5,0],[-9,3],[-4,0],[-11,0],[-3,1],[-3,2],[-2,2],[-2,3],[0,4],[4,6],[2,1],[10,7],[7,3],[7,3],[4,1],[5,1],[4,1],[8,5],[8,4],[11,7],[5,2],[17,4],[5,0],[4,-1],[3,-2],[11,-7],[1,0],[-2,3],[-4,8],[1,4],[6,3],[2,1],[7,0],[10,-2],[7,-1],[5,-2],[7,-1],[3,0],[2,1],[3,3],[5,5],[1,7],[0,8],[-2,6],[-1,3],[1,3],[5,4],[5,3],[11,3],[9,1],[6,0],[7,-2],[10,-1],[9,-3],[15,-8],[9,-4],[8,-2],[8,-3],[12,-6],[6,-3],[4,-1],[3,0],[-1,2],[-6,4],[-8,4],[-19,7],[-11,6],[-9,6],[-7,3],[-13,4],[1,1],[15,5],[27,5],[32,3],[10,0],[19,1],[1,2],[4,1],[17,3],[5,0],[8,-1],[8,-3],[4,-2],[5,-5],[2,-6],[0,-18],[0,-4],[1,-1],[3,2],[5,4],[3,2],[3,4],[2,6],[1,4],[-4,5],[-1,7],[3,4],[7,0],[28,-14],[11,-3],[13,-7],[15,1],[13,-1],[7,0],[3,1],[-5,3],[-19,9],[-9,7],[-6,8],[-2,4],[5,1],[22,0],[32,-4],[42,-13],[21,-5],[37,-15],[11,-2],[4,-1],[4,2],[2,2],[0,3],[-2,3],[-1,4],[0,5],[2,9],[6,3],[3,3],[-3,6],[-7,4],[-27,11],[0,1],[6,1],[8,1],[67,-2],[11,-1],[5,-1],[3,-1],[2,-1],[15,1],[-1,3],[-1,2],[-78,4],[-15,2],[-7,0],[-8,-1],[-16,-1],[-7,0],[-9,6],[8,6],[7,0],[14,-3],[8,4],[13,3],[13,1],[28,6],[5,1],[6,-1],[15,-1],[5,-2],[7,-3],[4,-1],[4,0],[6,-2],[9,5],[8,5],[10,4],[13,-2],[8,-3],[8,-3],[10,-1],[18,-11],[4,0],[1,1],[2,2],[1,3],[2,4],[-2,1],[-15,4],[-3,2],[-3,3],[0,2],[3,2],[3,0],[10,0],[3,0],[3,2],[4,2],[3,1],[6,0],[10,-2],[9,0],[3,1],[1,2],[1,1],[1,0],[32,0],[8,1],[6,1],[8,0],[6,0],[8,-2],[9,0],[12,3],[11,1],[64,0],[21,-2]],[[2530,6099],[2,-1],[1,-1],[3,-3],[3,-2],[1,5],[-1,3],[0,1],[0,2],[10,-13]],[[2549,6090],[-1,-2],[-3,-5],[-5,-8],[-4,-6],[-4,-7],[-3,-5],[-1,-1],[-4,-4],[-1,-2],[-1,-8],[-1,-2],[1,-4],[1,-7],[0,-4],[-3,-4],[-2,-4],[-1,-3]],[[2517,6014],[0,1],[-1,0],[-2,-1],[-1,0],[-1,-1],[0,-3],[0,-4],[0,-2],[0,-1],[-3,-2],[-1,-3],[-1,-3],[-2,-2],[-1,0],[-1,0],[-2,-3],[-3,-5],[-1,-4],[0,-3],[0,-3]],[[2497,5975],[-11,9],[-3,2],[-15,0],[-7,4],[-7,7],[-5,6],[-11,19]],[[2438,6022],[0,1],[1,3],[1,4],[-1,4],[0,3],[1,5],[0,4],[0,2],[1,1],[1,3],[-3,9],[0,3],[0,2],[3,10],[3,12],[4,13],[3,8],[8,0],[5,0],[8,0],[7,0],[5,0],[2,1],[0,5],[0,5],[1,6],[0,2],[-1,3],[-3,1],[-2,3],[0,3],[-1,4],[-1,4],[-3,5],[-4,4],[-4,7],[-3,7],[-3,5],[-2,3],[0,1],[6,0],[5,0],[0,11],[0,10],[0,11],[10,0],[13,0],[12,0],[10,0],[6,0]],[[9020,5948],[-1,-1],[-1,2],[-1,2],[0,6],[4,6],[1,5],[1,0],[1,-1],[1,-2],[-4,-9],[-1,-8]],[[3411,5503],[-2,-3],[0,-3],[-1,-4],[-1,-2],[2,-5],[1,0],[0,-1],[1,-1],[0,-1],[-1,-1],[-1,-1],[-1,-3],[0,-3],[-1,-2],[-2,-1],[-5,0],[-2,0],[-1,-1],[-2,-2],[-1,-1],[-1,-1],[-1,-2],[-1,-4],[0,-2],[1,-3],[1,-3],[-1,-6],[-1,-4],[0,-3],[-1,-6],[-2,-6],[-1,-4],[0,-4],[1,-6],[3,-8],[1,-4],[1,-6],[3,-6],[2,-4],[0,-5],[0,-2],[2,-1],[1,-1],[2,0],[1,0],[1,1],[3,0],[0,-1],[0,-8],[1,-3],[0,-1],[1,-2],[0,-2],[0,-4],[1,-3],[0,-4],[0,-2],[1,-1],[1,-3],[0,-1],[1,-1],[1,-5],[0,-1],[1,0],[0,-2],[0,-4],[1,-1],[1,-4],[0,-3],[1,-4],[2,-3],[0,-3],[2,-6],[2,-5],[2,-1],[1,-1],[2,-1],[1,-2]],[[3312,5483],[-5,14],[-6,14],[-6,13],[-1,2],[3,6],[2,5],[2,2],[1,3],[-1,10],[0,3],[-1,4],[0,4],[0,4],[1,2],[1,1],[3,1],[2,1],[1,1],[1,2],[1,0],[3,-1],[1,2],[3,3],[5,5],[1,3],[1,5],[0,3],[-1,1],[-1,0],[-2,1],[-2,-2],[-1,1],[-2,3],[0,3],[1,3],[0,3],[-3,8],[0,2],[2,3],[1,3],[2,7],[1,3],[3,1],[1,1],[2,4],[3,4],[4,4],[1,6],[1,2],[3,3],[1,2],[0,1],[-5,14]],[[3333,5676],[1,-1],[4,-9],[2,-2],[0,2],[2,-1],[6,-6],[7,-10],[11,-20],[3,-7],[2,-4],[3,-8],[1,-4],[0,-17],[-3,-11],[0,-8],[0,-12],[-2,-6],[2,3],[1,11],[2,6],[2,6],[3,2],[4,-3],[3,0],[2,-2],[5,-11],[5,-9],[2,-7],[6,-3],[3,-5],[1,-5],[1,-12],[-1,-19],[0,-1]],[[8172,6463],[0,-1],[-2,4],[0,2],[1,0],[2,-2],[0,-2],[-1,-1]],[[8166,6463],[-4,0],[0,1],[-1,1],[2,2],[4,3],[-1,-3],[0,-4]],[[8173,6482],[1,-2],[0,-3],[1,-1],[0,-2],[-1,-2],[0,-2],[-1,-2],[-3,3],[-3,2],[-3,-1],[-1,2],[0,2],[3,3],[0,1]],[[7047,2123],[-4,-3],[-3,0],[-1,3],[-3,6],[-1,1],[-1,2],[2,1],[2,-2],[5,-1],[4,-4],[3,-1],[-1,-1],[-2,-1]],[[2690,6047],[-7,1],[-4,-2],[-1,-4],[-1,-1],[-2,0],[-2,-2],[-3,-3],[-3,-1],[-2,0],[-1,0],[0,-2],[-1,-1],[-1,0],[-1,0],[-1,1],[-1,0],[0,-3],[-1,0],[-1,1],[-2,-1],[-1,-3],[-3,0],[-3,1],[-2,3],[-2,5],[-1,1],[-4,-3],[-1,-4],[-1,-3],[1,-2],[-1,-1],[-2,-1],[-1,-3],[-1,-4],[0,-4],[1,-2],[-1,-2],[-2,-1],[-3,-4],[-3,-7],[-2,-4],[-3,-3],[-2,-3],[0,-3],[0,-1],[-1,-1],[-6,7],[-1,5],[-2,-1],[-1,-2],[-3,-6],[-2,-7],[-2,-1],[-6,1],[-4,0],[0,-1],[-1,-3],[1,-4],[1,-13],[0,-5],[0,-2],[-2,0],[-2,-1],[-2,-3],[0,-2],[0,-4],[-1,-3],[-1,-3],[-2,-1],[-7,-1]],[[2574,5931],[0,6],[-2,3],[-2,5],[-1,3],[1,2],[-1,3],[-3,2],[-3,-2],[-1,1],[-2,2]],[[2560,5956],[3,3],[0,1],[-1,2],[-1,1],[1,3],[0,4],[1,9],[0,2],[-2,3],[-3,0],[-2,-1],[-2,2],[-1,3],[-2,1],[-3,-2],[-4,-4],[-1,-1],[-1,0],[-1,3],[0,3],[0,1],[-2,1],[-2,1],[-1,1],[-1,2],[-3,3],[-1,3],[-3,5],[-1,2],[-1,2],[-2,3],[-1,-1],[-5,3],[-1,0]],[[2549,6090],[3,-2],[2,4],[1,1],[3,4],[1,1],[5,2],[2,0],[2,-4],[2,-3],[3,2],[2,1],[11,-4],[4,2],[8,0],[3,-1],[5,6],[3,1],[4,3],[-1,3],[-1,1],[6,-1],[8,-6],[9,1],[3,3],[2,1],[9,-6],[3,-5],[2,0],[1,1],[1,1],[-2,1],[-1,1],[7,-3],[14,-22],[0,-2],[-6,7],[-3,-1],[-1,-1],[0,-3],[1,-2],[1,0],[1,1],[2,-2],[2,-2],[2,-4],[1,-4],[1,0],[2,3],[2,0],[1,-3],[1,1],[-1,4],[-4,4],[1,0],[8,-7],[2,-10],[2,-2],[2,-3]],[[2599,6127],[-4,-4],[-2,0],[2,3],[4,3],[2,2],[3,-1],[-5,-3]],[[2614,6132],[-2,-3],[0,1],[1,3],[1,2],[1,0],[0,-2],[-1,-1]],[[5489,7647],[3,-4],[-11,5],[1,1],[2,0],[5,-2]],[[5462,7660],[5,-1],[4,0],[3,-1],[2,-1],[1,-1],[-3,0],[-3,0],[-3,-1],[-4,1],[-1,1],[-1,1],[0,2]],[[5512,7635],[0,-2],[1,-2],[1,-3]],[[5514,7628],[-5,5],[-5,6],[-9,10],[-7,2],[-9,8],[-6,2],[2,1],[3,0],[14,-10],[-2,3]],[[5477,7668],[-2,-1],[-12,1],[-4,1],[-4,3],[-1,1],[4,1],[4,-1],[1,-2],[10,-2],[4,-1]],[[5466,7676],[-5,0],[-3,1],[-2,2],[0,1],[0,3],[5,0],[6,-2],[2,-2],[-1,-1],[-2,-2]],[[5426,7717],[2,-5],[-1,1],[-2,3],[-1,3],[2,-2]],[[5423,7722],[0,-2],[-3,4],[-2,2],[0,1],[5,-5]],[[5421,7714],[1,-1],[0,-1],[-2,1],[-7,12],[-1,3],[3,-3],[6,-11]],[[5421,7737],[0,-1],[-2,3],[-2,2],[-1,2],[-2,3],[-1,4],[-4,6],[0,2],[2,-3],[1,-1],[1,-1],[3,-4],[3,-6],[4,-5],[-1,0],[-1,-1]],[[5411,7762],[1,-3],[-2,3],[-3,0],[0,2],[0,2],[1,1],[1,0],[1,-2],[1,-3]],[[5402,7756],[0,-2],[-2,3],[-1,5],[-2,8],[0,2],[1,3],[0,2],[-2,7],[2,1],[1,-5],[0,-2],[2,-4],[0,-6],[0,-8],[1,-2],[0,-2]],[[5411,7774],[-4,-1],[-1,2],[-1,2],[-2,1],[-2,2],[0,1],[2,3],[1,5],[2,-3],[2,-5],[1,-1],[2,-6]],[[5525,7829],[-1,-1],[0,-2],[-1,-2],[1,-4],[2,-6],[-1,-4],[1,-2],[3,-2],[0,-1],[-1,0],[-1,-2],[0,-4],[3,-4],[5,-3],[1,-1],[1,-1],[1,-1],[0,-1],[0,-1],[0,-1],[-2,-1],[-3,0],[-2,2],[0,-1],[0,-2],[-2,0],[1,-10],[0,-2],[-1,-1],[-1,0],[-1,0],[0,-1],[0,-2]],[[5488,7657],[-1,1],[-6,9],[-6,6],[-6,10],[-8,4],[-6,5],[-4,-1],[-3,-1],[-3,0],[-1,0],[-2,3],[0,2],[0,3],[-3,5],[-5,4],[-4,6],[-9,15],[-1,5],[1,1],[2,0],[1,1],[2,0],[3,-1],[-2,3],[-3,3],[-8,13],[-3,6],[0,6],[1,9],[-2,6],[-6,9],[-2,4],[-5,2],[-2,0],[-1,-3],[-1,-7],[-4,-9],[-1,-4],[-3,-6],[-1,0],[-2,0],[-3,9],[-3,7],[0,3],[-1,4],[-2,14],[2,3]],[[5377,7806],[1,-3],[7,-3],[2,2],[1,2],[0,1],[3,-2],[2,1],[3,0],[3,-1],[1,2],[2,5],[1,3],[1,1],[1,-1],[0,-2],[1,-2],[3,-4],[1,-2],[2,0],[1,1],[2,1],[4,-3],[4,-1],[3,2],[-1,2],[-1,2],[0,2],[0,2],[2,2],[0,1],[-2,3],[0,1],[5,4],[4,2],[1,1],[1,3],[0,4],[0,4],[-2,4],[0,1],[0,2],[1,2],[2,1],[2,1],[2,1],[2,1],[2,2],[2,4],[1,0],[3,0],[1,1],[-1,5],[1,2],[1,0],[1,1],[3,0],[2,-2]],[[5458,7862],[2,-1],[5,-4],[3,-4],[2,-5],[3,-4],[3,-3],[2,-3],[2,-5],[3,-2],[3,-1],[3,-2],[0,-2],[2,-3],[3,-2],[4,-1],[9,0],[1,0],[1,-1],[3,1],[2,2],[1,1],[3,5],[2,0],[3,0],[1,1],[1,0]],[[2977,6265],[0,-4],[-7,5],[-6,6],[0,4],[3,0],[3,-2],[4,-4],[3,-5]],[[3006,6223],[-2,4],[-3,4],[-1,2],[-2,1],[-12,-1],[-2,0],[-1,-2],[-1,0],[-3,-1],[-4,-1],[-8,3],[-3,2],[-3,1],[-3,0],[-4,-1],[-3,-2],[-2,-4],[0,-4],[-2,-1],[-3,6],[-2,4],[-3,3],[-6,5],[-2,2],[0,3],[2,11],[3,1],[2,1],[3,-2],[4,-2],[3,-1],[5,-1],[2,-2],[19,-4],[4,-1],[1,0],[1,2],[1,2],[2,2],[5,1],[1,1],[1,2],[0,3],[-3,4],[-5,9],[-5,10],[2,4],[-1,6],[1,6],[1,6],[-4,4],[-6,5],[-7,2],[-2,1],[-1,4],[1,5],[2,2],[3,2],[3,1],[6,2],[7,-2],[6,-5],[6,-4],[7,-1],[3,-2],[2,2]],[[2981,6338],[1,-1],[0,-2],[-3,1],[-3,2],[-1,-1],[0,1],[-2,1],[2,2],[1,0],[2,0],[3,-3]],[[5614,7972],[3,0],[1,0],[0,-3],[1,-2],[0,-2],[1,-2],[2,0],[3,-3],[2,-4],[2,-1],[1,-1],[0,1],[2,0],[0,-1],[2,-2],[0,-2],[0,-2],[0,-2],[1,-1]],[[5635,7945],[-1,-1],[-5,-7],[-2,-2],[-1,0],[-2,0],[-2,0],[-2,-2],[-1,0],[-2,-2],[-1,-4],[-2,-3],[-2,-2],[-1,-2],[-1,-6],[-1,-2],[-1,-2],[-1,-2],[-2,-9],[-2,-3],[-2,-3],[0,-2],[0,-2],[-2,-5],[-2,-5],[-1,-2],[1,-3],[-3,-3],[-1,-2],[-1,-1],[-1,-2],[-1,-5],[0,-2],[0,-2],[-2,-1],[0,-2],[-1,-3],[-1,-1],[-2,-3],[-6,1],[-2,0],[-1,-2],[0,-1],[0,-2],[-2,-1],[-1,-1],[-3,2],[-6,-2],[-1,-1]],[[5562,7840],[-1,1],[-2,1],[-6,1],[-2,-1],[-4,0],[-3,1],[-2,-1],[-2,-4],[-1,-1],[-1,-1],[-2,-1],[-1,-2],[-2,-1],[-2,1],[-1,1],[-1,0],[0,-2],[-1,-1],[-3,-2]],[[5458,7862],[0,1],[-2,5],[-2,2],[1,3],[-1,1],[-1,1],[0,3],[-1,3],[0,2],[-6,0]],[[5476,7949],[1,0],[2,0],[1,-1],[5,-6],[4,-4],[4,-3],[5,0],[5,0],[10,1],[7,0],[0,1],[1,3],[-1,2],[0,3],[1,4],[4,2],[10,2],[5,2],[1,3],[2,3],[2,0],[2,-1],[3,-3],[2,-1],[2,1],[5,4],[5,5],[4,11],[1,2],[4,1],[6,0],[3,-2],[3,0],[3,0],[5,2],[2,0],[2,-1],[1,-2],[2,-2],[0,-2],[1,-1],[1,-2],[1,-2],[1,0],[10,3],[0,1]],[[8414,4555],[-2,0],[-1,1],[0,5],[1,3],[6,4],[2,3],[3,7],[2,2],[1,1],[0,-1],[0,-5],[1,-3],[0,-2],[-3,-2],[-2,-7],[-6,-4],[-2,-2]],[[8385,4574],[-2,-1],[-3,2],[0,1],[2,3],[2,4],[3,0],[1,-1],[0,-5],[-3,-3]],[[8427,4590],[-2,-2],[0,5],[2,5],[2,2],[1,-2],[0,-1],[-3,-2],[0,-5]],[[8333,4644],[1,-3],[5,-5],[0,-2],[1,-3],[1,-3],[2,0],[2,0],[1,-1],[2,-3],[2,-5],[2,-6],[2,-3],[2,-4],[-1,-4],[-3,-6],[-2,-1],[-2,-1],[-3,-3],[-2,2],[-3,1],[-3,2],[-3,5],[-2,5],[-1,4],[-4,3],[-6,8],[-3,1],[-2,-1],[-1,0],[-8,4],[-1,2],[-1,3],[-1,2],[0,4],[1,2],[1,2],[4,3],[3,1],[4,0],[5,1],[5,-1],[1,1],[3,3],[1,-1],[1,-3]],[[8473,4636],[-2,-3],[-1,-6],[-3,-5],[-4,-9],[-3,-5],[-2,-5],[-3,-4],[-2,-1],[-5,-1],[-5,-6],[-3,-3],[-3,0],[-3,2],[-1,2],[0,3],[1,3],[1,2],[1,3],[-4,4],[0,3],[1,7],[1,8],[2,5],[4,9],[3,5],[2,2]],[[8445,4646],[0,-2],[1,-3],[1,0],[0,1],[4,-1],[1,1],[2,3],[1,2],[1,5],[0,2]],[[8456,4654],[4,2],[2,3],[1,3],[5,5],[1,2]],[[8469,4669],[0,-5],[1,-2],[1,0],[3,3],[1,0],[1,-2],[0,-5],[-2,-4],[-3,0],[-1,-1],[0,-2],[0,-3],[1,-1],[1,-4],[1,-7]],[[8211,4679],[-1,-2],[-2,3],[-1,2],[2,2],[2,-2],[0,-3]],[[8415,4692],[-1,-4],[-1,1],[0,3],[1,2],[2,3],[2,1],[2,-1],[0,-1],[-3,-1],[-2,-3]],[[8318,4680],[-1,0],[-2,1],[1,5],[-1,3],[1,3],[1,5],[0,1],[1,-1],[0,-1],[1,-1],[1,0],[0,-2],[0,-2],[0,-2],[-2,-2],[-1,-3],[1,-4]],[[8425,4703],[-1,-3],[-7,0],[0,4],[2,3],[1,1],[2,1],[3,-1],[0,-5]],[[8239,4688],[-3,-12],[1,-2],[1,-2],[-6,-2],[-3,1],[-1,-1],[-6,3],[-4,2],[-1,3],[1,2],[1,-1],[3,0],[2,1],[0,8],[-1,10],[5,8],[2,3],[3,2],[6,-4],[2,-2],[0,-1],[1,-3],[-3,-13]],[[8452,4704],[-2,-4],[-1,-6],[-1,-2],[-3,-1],[-1,6],[-2,0],[1,6],[1,2],[2,0],[0,-3],[1,0],[3,9],[1,0],[1,0],[0,-1],[0,-6]],[[8442,4707],[-4,-1],[-3,-7],[-2,0],[-1,-4],[0,-1],[0,-1],[0,-1],[-1,-2],[-2,2],[-1,-2],[-1,-1],[-2,3],[-2,0],[-1,0],[3,6],[3,5],[1,1],[-1,1],[-1,1],[0,1],[2,1],[2,0],[1,-2],[1,0],[4,6],[2,-1],[2,-2],[1,-2]],[[8857,4701],[-1,-1],[-7,2],[-1,2],[0,1],[2,3],[1,4],[3,1],[1,0],[2,-9],[0,-3]],[[8265,4702],[-1,0],[-1,1],[0,2],[0,4],[0,3],[1,2],[4,0],[0,-2],[-3,-10]],[[8307,4709],[-1,0],[-1,2],[1,3],[1,1],[1,-2],[0,-1],[0,-2],[-1,-1]],[[8460,4715],[0,-4],[2,2],[2,1],[5,-1],[4,0],[2,-2],[0,-7],[-1,-1],[-18,-6],[-2,2],[-1,2],[2,5],[0,2],[1,4],[2,3],[2,0]],[[8550,4717],[5,-2],[2,0],[1,-2],[-3,-5],[-5,4],[-1,4],[1,1]],[[8410,4688],[-4,-2],[-3,-2],[-2,-3],[-1,0],[-3,-1],[-4,1],[-2,-1],[-7,-7],[-3,0],[-3,-2],[0,3],[-1,2],[-3,0],[-2,0],[-3,-6],[-3,1],[-2,0],[-1,-1],[-2,-1],[-1,1],[-6,4],[-6,3],[-7,-1],[-5,2],[-3,-2],[-3,-2],[-1,2],[-1,3],[-1,4],[0,4],[0,3],[1,3],[1,3],[0,3],[1,-2],[1,1],[4,3],[4,5],[3,2],[2,1],[2,-1],[2,0],[1,1],[3,-4],[1,-1],[4,0],[4,-2],[3,-3],[4,-4],[3,-4],[2,-1],[1,-1],[1,1],[2,3],[2,1],[2,0],[3,1],[2,0],[1,2],[2,-1],[1,-2],[5,-7],[2,0],[3,1],[1,2],[0,3],[1,3],[1,2],[2,2],[4,3],[3,2],[2,5],[-5,2],[1,4],[2,2],[2,-1],[1,-3],[1,-10],[-1,-1],[-1,-2],[-1,-2],[-2,-4],[1,-4],[-1,-2],[-1,-1]],[[8634,4705],[-2,-2],[1,4],[6,11],[1,-2],[3,-1],[-4,-4],[-4,-2],[-1,-4]],[[8284,4705],[1,-3],[1,1],[3,3],[2,1],[1,0],[2,0],[2,-3],[0,-4],[1,-1],[1,5],[1,1],[1,1],[3,0],[1,-2],[2,-7],[0,-6],[0,-3],[2,-1],[0,-2],[0,-3],[-1,-1],[-2,-1],[-1,0],[-1,2],[-1,1],[-2,-1],[-2,-1],[0,-3],[2,-1],[0,-1],[0,-1],[-1,0],[-2,2],[-1,-1],[-6,-2],[-1,0],[-1,2],[0,6],[-1,2],[-4,-8],[-1,-1],[-1,-1],[-2,0],[-6,-5],[-2,1],[-1,0],[-7,-5],[-3,-1],[-2,-1],[-1,1],[-2,-1],[-1,-2],[-3,-1],[-3,1],[-2,2],[-3,2],[0,3],[0,4],[1,4],[-1,9],[1,4],[1,3],[1,2],[2,0],[3,3],[3,5],[1,-1],[4,-3],[2,0],[4,0],[1,-1],[1,-5],[1,-1],[1,-2],[3,-7],[2,0],[2,-1],[4,5],[3,-1],[0,4],[-1,4],[-2,3],[-1,0],[-2,0],[-1,1],[-4,6],[-2,4],[0,4],[0,3],[3,3],[2,1],[5,-2],[1,-2],[2,-6],[1,-3]],[[8206,4714],[3,-3],[4,-9],[0,-2],[-1,-3],[-3,-4],[-6,-5],[-1,-3],[-2,-6],[0,-2],[0,-1],[-1,-1],[-1,-1],[-2,1],[2,4],[0,4],[-1,4],[-2,3],[-3,4],[-3,4],[-3,2],[-3,1],[-1,2],[-2,5],[-1,3],[0,2],[0,3],[1,0],[3,0],[6,-4],[3,0],[2,1],[4,6],[1,0],[4,-3],[3,-2]],[[8606,4726],[-2,-6],[-2,1],[-3,7],[0,5],[0,1],[2,1],[4,-2],[1,-4],[0,-3]],[[8521,4742],[1,-3],[0,-1],[-4,-1],[-3,-3],[-1,-3],[-2,-5],[-4,2],[-4,0],[-2,2],[-2,0],[-2,-2],[-4,-4],[0,6],[1,4],[3,8],[4,-2],[3,0],[4,2],[3,4],[4,2],[3,-6],[2,0]],[[8539,4745],[-2,-2],[0,5],[0,3],[3,-1],[0,-3],[0,-1],[-1,-1]],[[8847,4707],[-6,-7],[-9,1],[-3,0],[-5,-2],[-1,2],[1,7],[4,19],[5,17],[2,4],[3,4],[3,3],[7,4],[6,-1],[1,-1],[2,-6],[2,-4],[1,-6],[-3,-11],[-3,-10],[-5,-8],[-2,-5]],[[8647,4723],[0,-1],[-4,1],[-2,0],[0,5],[-1,3],[2,5],[0,5],[1,1],[1,3],[1,9],[1,1],[2,1],[1,5],[1,1],[1,4],[2,2],[0,3],[1,2],[2,1],[1,-1],[1,-4],[-2,-4],[1,-10],[-2,-10],[-1,-4],[-2,-2],[-1,-3],[-2,-5],[-1,-5],[0,-2],[-1,-1]],[[8665,4769],[0,-3],[-1,2],[-1,3],[-2,0],[-1,1],[-1,2],[5,1],[1,-6]],[[8177,4773],[0,-2],[-2,0],[-1,4],[1,1],[1,0],[1,0],[0,-3]],[[8573,4770],[-1,-1],[-2,3],[-1,1],[2,3],[1,1],[1,-2],[0,-1],[0,-1],[0,-3]],[[8354,4774],[-3,-1],[-1,1],[0,6],[3,-3],[1,0],[0,-3]],[[8162,4775],[-1,-1],[-5,0],[-3,-5],[-2,-1],[-7,0],[-1,1],[-1,0],[0,-1],[-3,0],[-7,5],[-2,3],[2,5],[2,5],[6,2],[25,0],[3,-5],[0,-2],[-5,-3],[-1,-3]],[[8204,4782],[-2,-1],[-2,2],[0,3],[0,3],[3,1],[2,0],[2,-2],[1,-2],[1,-2],[-4,0],[-1,-2]],[[8740,4795],[0,-1],[-1,2],[0,1],[1,3],[1,2],[1,0],[0,-2],[-2,-5]],[[7923,4801],[-2,-1],[-1,1],[-1,2],[2,4],[1,1],[1,0],[1,-2],[-1,-5]],[[8741,4807],[-1,-1],[-1,5],[1,1],[2,-3],[-1,-2]],[[8744,4813],[-1,0],[0,3],[1,2],[1,2],[1,0],[-2,-7]],[[8736,4813],[0,-4],[-1,-5],[-2,-5],[-2,-8],[-1,-2],[-3,-3],[-3,4],[-1,4],[1,17],[2,-1],[0,1],[1,1],[-2,2],[-1,10],[1,3],[1,1],[2,-3],[2,-5],[3,-4],[3,-3]],[[7982,4838],[3,-7],[2,-3],[3,-2],[3,0],[3,-1],[3,-3],[4,-1],[2,1],[1,1],[1,0],[1,-1],[3,-6],[3,-5],[0,-3],[2,-12],[2,-3],[3,-1],[3,0],[3,-1],[8,-3],[3,1],[3,3],[2,-2],[7,-4],[3,-1],[4,1],[3,1],[2,-1],[2,-2],[1,0],[2,0],[2,3],[2,5],[1,6],[1,7],[1,3],[1,3],[2,2],[1,1],[4,-1],[1,-2],[4,-11],[1,-1],[4,-1],[1,0],[3,3],[2,0],[2,-3],[2,-3],[1,-1],[7,-2],[3,-5],[1,-1],[5,1],[3,-1],[3,-1],[2,-7],[1,-8],[0,-2],[3,-3],[1,-2],[0,-7],[0,-7],[6,-6],[7,-4],[7,0],[7,1],[3,2],[5,2],[1,0],[8,-8],[1,-1],[1,-6],[0,-6],[-1,-15],[-1,-4],[1,-4],[1,-9],[1,-3],[3,-4],[0,-3],[0,-2],[-3,1],[-3,2],[-1,4],[-1,2],[-4,-1],[-6,3],[-7,5],[-12,11],[-3,0],[-3,-1],[-4,-3],[-3,-2],[-3,-1],[-2,1],[-7,3],[-6,1],[-17,1],[-5,3],[-8,1],[-6,2],[-6,3],[-16,15],[-5,4],[-16,7],[-3,1],[-5,-1],[-4,2],[-3,0],[-5,-2],[-1,-2],[-2,-3],[-3,0],[-4,1],[-8,3],[-3,2],[-3,3],[-3,4],[-1,1],[-8,4],[-6,2],[-12,2],[-2,1],[-3,1],[-1,4],[0,4],[1,3],[1,4],[1,4],[-9,7],[-7,4],[-3,0],[-3,0],[-3,0],[-4,0],[-1,1],[-2,1],[-2,-1],[-1,0],[0,3],[0,3],[2,3],[1,1],[1,-5],[0,-1],[2,-1],[3,7],[1,3],[1,8],[1,-1],[2,1],[1,1],[2,20],[2,5],[2,5],[2,1],[2,-3],[5,-1],[3,-2],[3,0],[3,-1],[5,-3],[1,0],[2,1],[2,4],[1,6],[3,-3],[5,-2],[1,-1]],[[8445,4840],[0,-3],[-1,3],[-1,2],[0,3],[1,-1],[1,-4]],[[8347,4821],[-1,-10],[0,4],[-1,9],[0,4],[0,5],[0,12],[1,6],[1,-7],[1,-4],[-1,-19]],[[8130,4849],[0,-2],[-3,0],[0,3],[1,4],[1,0],[2,-2],[-1,-3]],[[8688,4847],[-1,-6],[-2,2],[-1,4],[1,6],[-2,8],[2,0],[1,-3],[2,-8],[0,-3]],[[8742,4855],[0,-2],[0,-4],[0,-4],[-1,-4],[1,-6],[0,-3],[0,-4],[0,-1],[-1,-6],[-1,-2],[-1,-2],[-5,2],[-3,4],[-2,4],[0,1],[-3,5],[0,2],[0,2],[2,1],[2,0],[0,2],[1,8],[-3,5],[-1,2],[1,2],[3,-2],[3,9],[1,2],[0,5],[2,0],[1,0],[1,-4],[1,-2],[-1,-3],[2,-1],[1,-6]],[[8692,4844],[-3,-5],[2,12],[1,5],[2,4],[3,18],[0,-1],[1,-1],[-1,-13],[-4,-10],[-1,-9]],[[7843,4868],[-3,0],[-4,7],[0,2],[1,2],[1,0],[5,-4],[1,-3],[-1,-4]],[[8433,4880],[0,-6],[-1,1],[-1,2],[0,2],[0,1],[0,1],[2,-1]],[[8389,4871],[-2,-2],[-3,7],[-1,5],[0,3],[1,3],[1,0],[-1,3],[2,2],[1,-1],[1,-3],[1,-1],[1,-4],[-1,-12]],[[8406,4880],[-1,-4],[-1,-3],[-2,0],[-1,1],[-2,2],[-1,-2],[-1,0],[-1,3],[1,11],[2,4],[0,4],[-2,9],[1,4],[5,4],[3,4],[2,1],[1,-3],[0,-15],[-4,-12],[1,-8]],[[8421,4922],[0,-13],[0,-3],[-1,5],[-1,1],[0,-1],[-1,-1],[-1,0],[-1,-5],[0,-4],[-1,-3],[0,-10],[0,-3],[2,1],[0,1],[3,-4],[1,-3],[0,-3],[-2,-4],[-2,-1],[-2,1],[0,-1],[-1,-1],[-1,-3],[1,-2],[-2,-7],[-1,-2],[-3,2],[-1,-2],[-1,1],[-2,6],[0,4],[2,3],[0,3],[1,3],[1,4],[1,3],[0,2],[1,7],[0,3],[1,3],[1,7],[0,12],[2,10],[3,3],[1,0],[0,-3],[3,-6]],[[8709,4939],[2,-3],[-3,3],[-5,5],[-1,3],[4,-5],[3,-3]],[[8423,4947],[-3,-7],[-2,0],[-2,5],[-1,5],[0,2],[2,3],[5,-1],[1,-3],[0,-4]],[[8570,4977],[-4,-3],[1,6],[0,1],[3,-1],[0,-3]],[[8562,4972],[0,-2],[-2,-1],[-1,0],[0,2],[0,1],[-1,-1],[-2,-1],[-2,-3],[-1,1],[0,3],[0,1],[2,4],[3,1],[4,4],[2,0],[-1,-2],[0,-2],[-1,-2],[0,-3]],[[8575,4980],[0,-3],[0,-1],[-2,1],[-1,0],[-1,5],[0,1],[2,-2],[1,0],[1,-1]],[[8233,4984],[-1,-10],[-2,6],[2,7],[1,1],[0,-4]],[[8544,4993],[0,-3],[-2,2],[-2,2],[2,2],[2,-3]],[[8230,4961],[-6,-11],[-1,3],[1,11],[-2,7],[0,5],[1,9],[2,6],[3,5],[1,1],[0,-9],[0,-3],[1,-3],[-1,-2],[1,-10],[0,-3],[-1,-3],[1,-3]],[[8523,5006],[5,-5],[1,-2],[0,-4],[1,-2],[1,-1],[2,-4],[1,-4],[-1,-9],[-2,-1],[-2,-2],[-4,-5],[-2,-1],[-2,0],[-1,-2],[-2,0],[-4,3],[-3,3],[-6,6],[-1,2],[-1,3],[-2,6],[-1,4],[0,10],[1,3],[1,1],[3,-3],[3,3],[7,2],[7,0],[1,-1]],[[8554,5015],[-1,-5],[-2,0],[-1,1],[3,3],[1,1]],[[7968,5011],[0,-1],[-2,0],[-1,2],[-1,1],[0,2],[2,2],[3,-2],[-1,-4]],[[7985,5017],[-2,-2],[0,2],[0,1],[0,2],[2,1],[0,-1],[0,-3]],[[8603,5019],[7,-7],[3,-1],[6,1],[2,0],[5,-9],[2,-5],[0,-5],[1,-5],[1,-1],[2,0],[2,-7],[0,-2],[-1,-16],[-7,6],[-6,7],[-2,3],[-7,6],[-1,2],[-1,2],[-3,4],[-6,1],[-2,0],[-1,-1],[0,-2],[0,-4],[-2,-1],[-3,2],[-4,1],[-3,3],[-3,1],[-1,1],[0,2],[0,2],[-1,1],[-1,-1],[-2,-1],[-1,-2],[-2,-6],[-2,-2],[-3,-1],[-1,1],[-2,1],[-4,10],[-1,2],[-1,2],[-2,1],[-1,-2],[-1,-3],[0,-3],[0,-3],[-2,-6],[-2,-3],[1,6],[0,3],[-1,4],[-1,3],[7,17],[2,4],[11,1],[6,-1],[3,1],[2,1],[2,-1],[1,-3],[1,-2],[1,0],[3,2],[3,4],[1,2],[2,0],[2,0],[1,-1],[4,-3]],[[7789,5000],[1,-8],[-3,6],[0,4],[-1,2],[-2,4],[-1,4],[-1,9],[1,2],[1,0],[6,-12],[0,-2],[0,-5],[-1,-1],[0,-3]],[[8005,5011],[0,-6],[-1,-2],[-2,-3],[-1,-2],[-2,0],[-1,3],[0,3],[-3,2],[0,-1],[-1,-3],[-4,-3],[-2,0],[1,5],[-1,4],[0,4],[0,2],[-1,2],[1,3],[0,4],[1,3],[1,10],[5,2],[1,-2],[5,-2],[4,-6],[2,-7],[-2,-10]],[[7783,5026],[-2,-5],[-4,0],[0,3],[0,7],[-1,2],[0,1],[1,4],[0,1],[6,-10],[0,-3]],[[8732,5061],[-1,0],[0,2],[0,3],[1,1],[1,-1],[-1,-5]],[[7773,5049],[0,-2],[-5,5],[-2,2],[-2,5],[1,3],[0,4],[0,1],[2,1],[1,-3],[2,-7],[2,-6],[1,-3]],[[8501,5043],[-1,-1],[-1,3],[-2,8],[-1,3],[-1,8],[1,3],[1,3],[1,0],[1,-2],[-1,-9],[3,-11],[0,-5]],[[8439,5071],[1,-2],[-2,0],[-1,4],[1,3],[1,-5]],[[8500,5081],[8,-2],[-1,-2],[-9,-4],[-3,1],[-10,-2],[-2,0],[0,3],[-1,3],[2,2],[2,0],[5,-1],[9,2]],[[8420,5079],[-2,-5],[0,3],[0,2],[1,2],[1,1],[0,-3]],[[8620,5086],[0,-3],[2,-3],[-1,-5],[0,-1],[0,-2],[1,-2],[-1,-1],[-1,1],[-2,-2],[-1,-2],[-3,-1],[-1,2],[-6,2],[-4,6],[0,1],[7,6],[3,2],[3,0],[3,2],[1,0]],[[8471,5086],[2,-2],[1,0],[1,2],[2,-1],[0,-4],[2,1],[1,-2],[0,-4],[-5,-1],[-3,-3],[-5,3],[-6,-5],[-3,-2],[-3,0],[-2,9],[1,10],[1,1],[2,1],[5,1],[9,-4]],[[8762,5092],[11,-3],[3,1],[7,-2],[5,-3],[9,-1],[3,-1],[2,-3],[-5,-2],[-3,-2],[-4,-1],[-4,1],[-3,-1],[-1,2],[-4,2],[-5,4],[-10,5],[-1,3],[0,1]],[[8026,5091],[-4,-3],[0,5],[2,2],[2,-1],[0,-3]],[[7945,5088],[1,-4],[1,-4],[1,-4],[1,-18],[5,-16],[12,-6],[-2,-3],[-1,-2],[0,-3],[-2,-11],[0,-2],[1,-4],[0,-4],[-1,0],[-2,1],[-2,1],[-1,2],[-1,2],[-2,1],[-2,3],[-4,2],[-3,2],[-2,5],[-1,6],[1,8],[-1,3],[-1,2],[-2,6],[0,7],[-3,3],[-2,2],[-2,1],[-6,-3],[-1,1],[-1,2],[-3,2],[0,4],[1,3],[4,4],[1,2],[1,4],[-1,3],[0,2],[1,3],[2,2],[3,3],[2,-5],[0,-4],[1,-3],[2,4],[-1,7],[3,2],[2,0],[2,-2],[1,-3],[1,-4]],[[8432,5086],[-1,-1],[-2,2],[0,8],[2,2],[0,-3],[1,-2],[1,-2],[-1,-4]],[[8559,5088],[-2,-2],[-1,-1],[-4,2],[-4,-1],[-5,-2],[-3,2],[-2,3],[0,3],[2,8],[3,6],[2,1],[3,-2],[4,-4],[4,-5],[3,-5],[0,-3]],[[8422,5116],[0,-3],[-1,-3],[1,-6],[3,8],[3,1],[1,-2],[1,-1],[1,-3],[-1,-7],[-2,-3],[-2,0],[-1,4],[-2,0],[-1,-8],[0,-1],[-1,-1],[-2,2],[0,1],[2,4],[-1,11],[-1,-2],[-4,-10],[-2,-5],[-1,3],[-1,6],[0,9],[2,6],[2,-1],[5,2],[2,-1]],[[8047,5116],[-6,-6],[-1,0],[-1,2],[0,12],[1,3],[4,0],[2,-1],[2,-2],[0,-4],[0,-2],[-1,-2]],[[8748,5120],[-1,-2],[-2,2],[-1,4],[0,3],[2,3],[1,-3],[1,-3],[1,0],[-1,-4]],[[7754,5081],[-3,0],[-5,7],[-2,3],[0,4],[-5,16],[-1,4],[2,13],[6,3],[1,-2],[1,-6],[3,-11],[1,-5],[1,-3],[0,-2],[0,-1],[2,-7],[2,-4],[0,-6],[-3,-3]],[[8638,5108],[-1,-2],[-3,2],[-2,3],[-1,5],[-1,4],[0,3],[-1,4],[0,2],[6,4],[1,-2],[3,0],[1,-3],[-1,-13],[-1,-7]],[[8635,5139],[0,-3],[-2,-2],[-12,-3],[1,2],[1,2],[1,1],[1,0],[1,0],[1,0],[1,1],[2,-1],[3,1],[0,3],[2,-1]],[[8760,5146],[6,-2],[2,0],[2,-2],[2,1],[2,-1],[5,-9],[2,-6],[4,-5],[2,-1],[-2,-5],[-4,-2],[-1,0],[-3,2],[-2,0],[-3,3],[0,6],[-2,11],[-3,-3],[-3,5],[-1,1],[0,-1],[-2,2],[-1,3],[0,3]],[[8535,5139],[0,-1],[-3,1],[-1,1],[2,8],[1,0],[1,-8],[0,-1]],[[8628,5153],[-2,0],[-3,3],[2,2],[1,0],[1,2],[2,-1],[0,-2],[-1,-4]],[[8384,5160],[1,-2],[0,-3],[-1,1],[-3,0],[-1,-1],[-1,-1],[-1,-1],[1,3],[2,4],[1,0],[2,0]],[[8915,5033],[0,-11]],[[8915,5022],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-5],[-1,-6],[-2,-9],[0,-7],[2,-6],[1,-4],[0,-10],[0,-11],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12],[0,-12],[0,-11],[0,-12],[0,-12]],[[8915,4659],[-1,2],[-4,6],[-4,7],[-2,7],[-2,6],[-11,19],[-3,6],[0,1],[0,2],[1,3],[2,9],[-2,-5],[-3,-5],[-4,0],[-4,-1],[-3,-3],[-4,-1],[-2,1],[-1,4],[-1,3],[0,4],[-1,-6],[-3,-3],[-5,-7],[-1,1],[-1,3],[0,3],[1,3],[1,3],[0,7],[2,4],[1,9],[1,3],[1,3],[-1,3],[-2,1],[-1,2],[-2,6],[-1,2],[-2,2],[-1,3],[2,2],[1,1],[2,0],[3,-1],[1,0],[3,2],[-2,-1],[-1,0],[-6,4],[-4,4],[-3,7],[0,2],[2,1],[5,2],[-1,4],[-2,3],[-1,6],[-2,4],[-3,6],[-2,6],[-2,13],[-2,10],[0,4],[2,2],[-3,1],[-2,1],[1,5],[3,3],[-3,-1],[-2,-1],[-1,0],[-1,0],[-1,2],[0,3],[1,4],[-1,5],[-2,2],[-2,3],[-1,2],[-1,0],[-1,2],[-1,3],[-13,14],[-1,4],[-1,-2],[-1,-1],[-1,3],[-2,1],[-1,0],[-2,1],[-2,1],[-1,0],[-7,4],[-6,7],[-5,3],[-3,4],[-4,3],[-7,3],[-7,2],[-3,0],[-2,-1],[-2,0],[-13,15],[-2,7],[0,4],[1,3],[5,1],[-4,1],[-1,-1],[-3,-2],[-1,0],[-3,1],[-2,3],[-3,-2],[-2,3],[-1,3],[-1,2],[-1,0],[-2,-1],[-1,0],[-2,2],[0,4],[-2,2],[-1,2],[-2,4],[-2,5],[1,10],[0,4],[2,5],[2,6],[-2,0],[-2,-2],[-1,-3],[0,-3],[0,-10],[-2,-3],[-2,0],[1,-6],[-1,-5],[-3,-7],[0,-3],[0,-4],[0,-3],[-5,-9],[-1,-1],[-3,0],[-3,-1],[-2,2],[-1,3],[-1,3],[-1,7],[-1,7],[3,9],[-1,8],[-2,7],[-6,9],[-6,9],[-2,2],[-4,1],[-2,1],[-1,3],[-1,4],[3,2],[4,4],[3,0],[7,-2],[2,-3],[2,-1],[5,8],[4,10],[2,2],[2,0],[2,-1],[4,-3],[3,-2],[2,0],[2,-3],[1,-1],[0,4],[2,6],[2,1],[1,1],[1,1],[0,5],[-3,1],[1,4],[2,2],[0,2],[0,3],[-6,-5],[-6,-2],[-4,0],[-3,0],[-7,-3],[-3,0],[-7,1],[-3,2],[-3,-1],[-3,0],[-2,3],[-3,5],[-1,4],[-2,2],[0,3],[-2,13],[0,9],[-3,0],[-3,1],[-12,9],[-1,-3],[-2,-1],[-2,0],[-1,0],[-2,2],[0,2],[1,6],[2,2],[1,2],[1,3],[2,9],[0,3],[0,3],[0,3],[1,1],[5,3],[9,4],[3,3],[2,4],[2,3],[1,3],[1,2],[8,5],[3,1],[3,-1],[7,-3],[6,-6],[5,-7],[6,-5],[7,-1],[3,1],[4,-1],[1,-2],[2,-4],[0,-3],[-1,-6],[2,-6],[2,-5],[1,-7],[1,-3],[-1,-6],[-1,-3],[-2,-6],[-1,-5],[1,-7],[0,-8],[0,-6],[1,-7],[1,-6],[4,-18],[3,-12],[1,6],[0,8],[1,3],[1,1],[2,-1],[0,-3],[0,-7],[2,-13],[2,-1],[2,2],[0,-4],[0,-7],[1,-6],[1,-2],[3,-5],[2,-1],[4,-1],[3,-1],[4,2],[2,5],[2,4],[6,11],[2,6],[2,8],[0,1],[7,9],[0,3],[1,6],[2,6],[1,3],[6,3],[6,1],[7,6],[2,4],[1,3],[-2,5],[0,3],[2,2],[5,7],[7,7],[5,4],[3,0],[3,-4],[3,-3],[15,-10],[2,-3],[2,-5],[3,-3],[3,-1],[3,-3],[3,-3],[7,-7],[8,-7],[2,-1],[8,0],[2,-1],[1,-2],[1,-1],[9,-1],[2,-2],[1,-2],[1,-5],[6,-1]],[[7901,5165],[3,-6],[0,-2],[-1,-3],[-1,-5],[0,-1],[-2,2],[-2,-4],[-1,7],[-2,4],[2,5],[1,0],[0,-1],[3,4]],[[8543,5165],[3,-8],[-2,-8],[1,-5],[4,0],[1,-2],[1,-2],[0,-3],[-1,-2],[-2,-2],[-3,3],[0,3],[-1,1],[-3,-2],[-1,-1],[-1,4],[1,6],[-2,2],[-3,6],[0,2],[1,4],[0,3],[1,1],[3,-5],[1,4],[1,2],[1,-1]],[[8534,5155],[-2,-1],[-2,0],[0,6],[0,8],[2,1],[3,-2],[-1,-2],[1,-4],[-1,-6]],[[7881,5164],[-4,-2],[-4,1],[1,4],[2,4],[1,0],[3,-3],[2,-3],[-1,-1]],[[8633,5184],[5,-3],[1,0],[7,-6],[1,-3],[-1,-2],[1,-3],[-2,-4],[-1,-1],[-1,2],[-2,1],[-3,-2],[-1,1],[-2,4],[-2,3],[-4,8],[-1,0],[0,-3],[1,-3],[2,-6],[2,-1],[1,1],[1,-3],[0,-4],[-4,-2],[-1,3],[-1,6],[-2,-2],[-1,-2],[-2,5],[-4,1],[-3,3],[1,3],[0,3],[2,2],[2,-2],[2,2],[1,0],[1,1],[4,1],[3,2]],[[7734,5153],[-1,-2],[-3,2],[1,4],[0,5],[2,4],[0,5],[-3,13],[2,0],[1,-1],[2,-9],[2,-5],[-1,-7],[-2,-9]],[[7910,5174],[1,-1],[1,3],[1,-4],[1,-2],[2,-2],[-1,-1],[-1,-1],[-1,-1],[-5,7],[-4,-2],[-3,2],[0,1],[1,4],[1,8],[3,-2],[0,-3],[0,-1],[2,-1],[2,-4]],[[8598,5173],[-1,0],[-1,3],[-3,4],[-2,6],[7,-10],[0,-3]],[[8540,5183],[-1,-1],[0,2],[-1,1],[1,6],[0,1],[0,-4],[1,-5]],[[7907,5187],[0,-1],[-1,1],[-1,1],[0,1],[-3,8],[1,0],[3,-7],[1,-3]],[[7868,5215],[-3,0],[-1,0],[1,6],[1,3],[1,0],[2,-5],[-1,-4]],[[8539,5221],[-1,-1],[-1,0],[0,3],[1,4],[1,0],[0,-1],[0,-3],[0,-2]],[[8537,5229],[-1,-2],[-1,1],[0,3],[0,1],[1,1],[1,0],[0,-4]],[[7873,5222],[-1,-1],[-2,8],[0,4],[1,1],[1,-3],[1,-2],[1,-4],[-1,-3]],[[7883,5230],[0,-2],[-2,4],[0,2],[0,1],[2,-2],[0,-3]],[[7895,5232],[-2,-2],[-2,5],[0,2],[0,1],[1,0],[1,-3],[1,-1],[1,-2]],[[7861,5227],[0,-2],[-1,1],[-6,3],[-2,0],[-4,3],[-2,1],[-1,2],[1,4],[0,2],[1,6],[1,2],[2,-4],[3,-4],[1,-2],[5,-4],[1,-2],[1,-6]],[[7872,5244],[0,-3],[-2,1],[-1,4],[1,2],[1,1],[1,-3],[0,-2]],[[7865,5234],[-1,-2],[-1,1],[-2,2],[-2,3],[-2,3],[-3,2],[-1,1],[-1,0],[1,7],[2,0],[5,-6],[2,-3],[3,-8]],[[7889,5252],[2,-3],[1,2],[0,-2],[0,-2],[-2,-6],[-3,1],[-1,2],[0,2],[1,0],[0,3],[1,0],[1,3]],[[7904,5254],[1,-4],[1,-3],[1,-3],[-1,-5],[-1,-6],[-1,-1],[-2,1],[-1,2],[0,1],[0,2],[-1,1],[1,2],[-1,3],[-4,-2],[-1,0],[0,4],[0,1],[3,5],[2,1],[2,-1],[2,2]],[[7844,5241],[-1,-2],[-1,3],[-2,4],[0,4],[-1,7],[0,4],[1,3],[3,-3],[1,-5],[1,-1],[0,-5],[-1,-5],[0,-4]],[[7707,5268],[6,-16],[3,-2],[3,-8],[1,-2],[-1,-5],[-1,-15],[-2,-4],[-3,2],[0,3],[-3,11],[-4,6],[-1,0],[-1,7],[-2,7],[-6,14],[4,0],[3,3],[0,3],[1,0],[3,-4]],[[7846,5268],[0,-8],[-2,2],[-1,3],[-3,2],[-3,1],[-2,2],[-2,4],[0,1],[0,1],[1,1],[12,-6],[0,-3]],[[8468,5241],[-5,-10],[-2,-4],[-1,-5],[-2,-6],[-3,-5],[-1,-2],[-3,-2],[-1,-1],[-4,-1],[-9,-4],[-3,0],[-4,0],[-6,1],[-1,1],[-2,5],[-3,4],[-2,0],[-3,0],[-17,0],[-6,-1],[-6,-2],[-4,1],[-3,2],[-2,1],[-3,-1],[-11,-3],[-3,1],[-6,3],[-3,1],[-4,-1],[-3,-3],[-1,-3],[-3,-8],[-2,-6],[-1,-7],[-1,-7],[-1,-7],[0,-6],[0,-7],[1,-7],[1,-6],[4,-12],[1,-2],[4,-4],[3,-4],[2,-13],[2,-6],[2,0],[2,0],[3,-1],[3,-1],[3,4],[2,7],[2,5],[4,11],[3,5],[1,1],[2,-1],[1,-2],[2,-3],[3,-1],[3,1],[4,3],[1,2],[1,3],[3,2],[7,0],[3,-1],[7,1],[0,2],[-2,2],[0,2],[1,1],[4,2],[5,2],[3,-1],[2,-4],[1,-3],[1,-4],[-1,-11],[-1,-2],[-2,-1],[-2,1],[-2,6],[-3,2],[-4,-2],[-1,-2],[-2,-2],[-2,-5],[-2,-7],[-4,-10],[-5,-8],[-2,-4],[-3,-2],[-8,-6],[-2,-4],[-2,-5],[-2,-2],[-2,-1],[-1,1],[-4,3],[-1,-2],[0,-4],[2,-2],[2,-4],[2,-6],[2,-1],[2,-2],[2,-2],[2,-5],[3,-13],[1,-6],[2,-6],[6,-9],[0,-2],[0,-3],[1,-3],[2,-5],[0,-4],[-2,-4],[0,-6],[-2,-8],[0,-3],[0,-3],[1,-2],[1,-2],[2,-1],[1,-2],[3,-6],[1,-2],[1,-2],[0,-4],[1,-2],[1,-3],[2,-1],[1,1],[0,1],[2,0],[0,-3],[1,-3],[0,-4],[0,-7],[-1,-2],[-1,0],[-3,3],[0,-2],[0,-2],[-1,-1],[-2,0],[-4,0],[-7,-4],[-3,-3],[-1,-4],[-1,-3],[1,-7],[-1,-3],[-3,0],[-5,1],[-3,2],[-1,2],[-2,4],[-1,6],[1,17],[1,2],[0,2],[1,3],[0,4],[-2,5],[-3,1],[-3,4],[-11,21],[-1,2],[0,3],[1,4],[3,11],[1,2],[0,9],[0,8],[0,7],[-2,5],[-3,1],[-3,1],[-3,-2],[-3,-4],[-6,-7],[-2,-5],[0,-6],[1,-6],[2,-5],[0,-6],[2,-21],[0,-2],[-2,-6],[0,-14],[0,-19],[1,-11],[0,-6],[-3,-14],[-1,-8],[0,-3],[3,-14],[1,-5],[0,-6],[-3,3],[-1,-1],[-2,0],[-3,-1],[-4,0],[-1,-2],[-3,-3],[-1,-2],[-1,0],[-5,5],[-2,5],[-3,5],[0,7],[1,6],[1,7],[2,12],[0,8],[1,6],[1,6],[1,6],[0,22],[0,2],[-4,14],[0,2],[0,4],[0,3],[0,3],[0,2],[-2,3],[-1,1],[-4,-1],[-6,-4],[-2,3],[-2,5],[-1,7],[0,7],[0,7],[1,6],[-1,5],[-1,5],[0,2],[0,2],[2,2],[1,1],[2,2],[3,7],[1,6],[1,7],[1,7],[1,6],[3,6],[0,6],[-1,9],[1,5],[-1,5],[0,5],[2,9],[4,20],[4,10],[1,3],[3,-5],[1,-6],[0,5],[0,5],[-2,12],[-1,23],[0,2],[2,0],[1,2],[1,3],[-2,9],[0,3],[3,11],[2,5],[1,2],[1,8],[1,2],[2,2],[2,5],[1,7],[1,0],[2,-5],[1,-2],[3,-2],[2,2],[1,3],[1,2],[1,3],[1,2],[2,7],[2,6],[1,2],[1,1],[2,1],[2,0],[3,-3],[2,-1],[2,0],[2,-1],[1,-1],[0,-4],[2,-3],[1,-1],[1,-1],[7,1],[7,-3],[9,-1],[3,-1],[3,-3],[4,-4],[1,-1],[2,0],[2,4],[1,1],[2,0],[6,-1],[15,-5],[3,1],[9,10],[4,9],[3,3],[2,4],[0,5],[1,1],[3,2],[1,1],[3,7],[2,5],[1,2],[3,-1],[2,-3],[2,-8],[0,-1],[-3,-4],[0,-2],[-3,-11],[-2,-6],[-2,-5]],[[7824,5304],[2,-5],[0,-3],[-1,-4],[0,-5],[-3,-4],[-3,1],[-1,1],[-2,8],[0,7],[1,3],[3,-1],[3,4],[1,-2]],[[8547,5233],[2,-2],[2,1],[1,2],[1,4],[1,6],[2,4],[2,1],[1,1],[0,5],[0,5],[2,4],[5,7],[4,3],[4,0],[0,-2],[0,-4],[1,-5],[-1,-15],[-1,-3],[-4,-5],[-5,-4],[-1,-2],[-1,-4],[0,-4],[4,-5],[6,-6],[1,-2],[1,-4],[0,-4],[1,-3],[2,-1],[2,-2],[1,-3],[-10,7],[-3,3],[-3,1],[-3,1],[-3,2],[-4,1],[-1,-2],[-1,-4],[0,-4],[0,-5],[0,-4],[0,-5],[2,-18],[3,-13],[5,-14],[2,-5],[3,-5],[-5,2],[-1,4],[-5,5],[-1,3],[-3,13],[-1,3],[-3,4],[-2,4],[0,4],[0,5],[0,7],[0,6],[1,8],[-1,3],[-2,3],[-2,6],[0,7],[0,4],[1,4],[1,3],[0,3],[-3,4],[-2,12],[0,7],[3,12],[0,6],[0,4],[1,4],[1,8],[3,7],[5,10],[2,2],[2,1],[0,-2],[0,-2],[-4,-10],[0,-2],[0,-5],[1,-2],[2,-5],[0,-7],[0,-7],[0,-7],[-1,-3],[-2,-7],[-7,-9],[0,-2],[0,-2],[1,-3],[1,-2]],[[7703,5303],[0,-1],[-3,6],[-3,3],[1,1],[3,-1],[1,0],[1,-3],[0,-5]],[[8567,5302],[-4,-1],[-1,3],[-1,12],[3,10],[4,6],[2,1],[1,0],[3,-7],[-2,-14],[-2,-7],[-3,-3]],[[8483,5337],[-1,-2],[-1,7],[1,3],[1,-1],[1,-1],[-1,-3],[0,-3]],[[7679,5320],[-2,-1],[-2,1],[-1,4],[-7,9],[-3,0],[-1,3],[-2,1],[-3,6],[0,4],[2,1],[1,4],[2,-2],[3,-6],[3,-2],[1,-1],[1,-4],[6,-8],[1,-3],[1,-3],[0,-3]],[[8024,5351],[-1,-3],[-2,2],[2,6],[1,1],[0,-6]],[[7937,5349],[-1,-1],[-1,2],[1,3],[-1,2],[0,2],[0,3],[1,-1],[1,-2],[1,-1],[1,0],[0,-1],[-1,-4],[-1,-2]],[[7952,5366],[0,-4],[-2,2],[-1,4],[1,2],[1,-1],[1,-3]],[[8267,5373],[0,-2],[-2,5],[-1,3],[0,2],[3,1],[1,-2],[-1,-7]],[[8490,5382],[-1,-2],[-3,3],[0,5],[-1,3],[-1,2],[0,3],[0,3],[2,-4],[2,-6],[1,-5],[1,-2]],[[8523,5401],[-1,-1],[-1,2],[0,1],[0,2],[0,1],[2,-3],[0,-1],[0,-1]],[[8519,5407],[0,-2],[-1,5],[-1,7],[1,-3],[2,-5],[-1,-2]],[[8274,5425],[1,-6],[0,-2],[-5,-3],[-3,7],[0,3]],[[8267,5424],[3,0],[4,1]],[[8008,5396],[-4,-2],[-2,3],[2,4],[1,0],[1,1],[0,1],[-4,3],[-2,2],[-1,5],[0,4],[6,9],[1,1],[0,-4],[4,-10],[0,-6],[0,-2],[-2,-9]],[[8265,5424],[-2,-2],[-1,-3],[3,-5],[0,-4],[2,-3],[2,-5],[1,-1],[0,-2],[1,-3],[-2,-2],[-2,-1],[-2,3],[-2,3],[0,-4],[-1,-2],[-5,0],[-3,0],[-3,-1],[1,0],[2,-1],[5,-10],[1,-3],[-2,-7],[1,-3],[2,-2],[2,-3],[2,-1],[1,-2],[0,-3],[1,-3],[-2,-1],[2,-1],[2,-2],[-1,-2],[-1,-1],[1,-2],[2,-1],[1,-2],[1,-4],[2,-8],[4,-9],[1,-4],[0,-3],[-1,-3],[-2,-3],[-2,-4],[0,-2],[-3,-1],[1,-2],[1,-2],[2,-6],[4,-9],[2,-4],[9,-13],[5,-5],[6,-13],[3,-3],[0,-4],[-2,-5],[-4,-3],[-6,-1],[-6,2],[-4,1],[-2,3],[-3,7],[-2,3],[1,-4],[0,-4],[0,-4],[-1,-3],[-2,-3],[-2,-2],[-1,-1],[-5,-23],[-1,-6],[-2,-25],[0,-7],[2,-13],[1,-7],[0,-3],[0,-3],[-1,-1],[-5,-4],[-3,-4],[-3,-4],[-2,-6],[-2,-5],[-2,-2],[-2,1],[-1,2],[-1,3],[-1,5],[0,-3],[0,-3],[0,-4],[1,-3],[-1,-4],[-1,-2],[-3,-3],[-1,-3],[0,-5],[-1,-2],[-1,-2],[-4,-5],[-1,-2],[-1,-2],[2,0],[2,0],[0,-5],[1,-3],[-1,-7],[-3,-5],[2,-2],[1,-1],[3,-1],[1,-6],[0,-6],[-1,-6],[-2,-1],[-1,1],[-2,0],[-1,-2],[0,-3],[2,1],[0,-7],[-1,-7],[0,-4],[-2,-4],[-1,-1],[-2,3],[0,-3],[0,-2],[3,-6],[-2,-2],[-1,-2],[0,-2],[-3,-7],[-1,-5],[-1,-5],[-1,-4],[-19,-18],[-16,-15],[-1,1],[-1,2],[0,23],[-2,13],[-1,6],[-2,-6],[-1,1],[-2,1],[-1,2],[0,3],[1,7],[-1,-4],[-2,-3],[-1,1],[-2,1],[0,3],[-1,0],[-3,-7],[-5,-3],[-2,0],[-2,2],[0,5],[0,5],[-1,3],[-1,1],[-1,-1],[-4,-2],[-1,0],[0,-1],[-9,18],[-2,-15],[-6,-8],[-4,-4],[-4,2],[-5,3],[-4,-4],[-5,-9],[-1,-1],[-2,0],[-1,1],[1,7],[0,6],[-1,15],[0,3],[-1,4],[-2,2],[-1,-2],[-1,-3],[-4,1],[-3,2],[-3,-1],[-6,-6],[-3,-1],[-2,1],[-1,3],[0,3],[2,2],[-3,-1],[-2,-3],[-1,-2],[-1,1],[-2,6],[-6,-2],[0,-1],[-2,-2],[-1,1],[-1,2],[0,14],[-3,26],[-1,14],[0,3],[-3,5],[0,6],[1,6],[1,7],[-1,7],[-1,7],[-1,6],[-2,4],[-2,6],[-3,3],[-6,5],[-4,-1],[-1,2],[-1,2],[1,5],[1,3],[1,0],[0,2],[-3,4],[-3,4],[0,3],[-1,3],[0,8],[1,4],[1,3],[0,7],[2,3],[0,1],[-1,1],[-1,3],[-1,2],[-2,5],[-4,6],[0,10],[-1,16],[1,6],[1,13],[2,4],[1,1],[2,2],[-1,0],[-1,0],[-2,-1],[2,12],[0,3],[3,6],[3,6],[1,7],[1,6],[7,6]],[[8044,5301],[-2,-8],[0,-3],[1,-2],[2,-2],[0,-9],[2,-5],[3,-5],[1,-3],[2,-3],[2,-3],[1,-3],[2,-3],[6,-11],[2,-3],[2,-3],[1,-2],[3,1],[9,8],[1,1],[3,1],[5,0],[6,-3],[2,0],[1,2],[3,-1],[2,-1],[1,1],[3,6],[4,2],[2,5],[1,6],[0,6],[2,2],[3,2],[4,3],[12,0],[2,-1],[0,-3],[0,-2],[0,-2],[2,0],[2,-1],[6,-5],[3,-1],[1,0],[3,-4],[2,1],[2,3],[2,4],[2,3],[3,2],[3,-1],[4,2],[4,1],[3,-3],[1,1],[1,3],[1,6],[1,4],[1,8],[0,1],[2,1],[1,2],[0,2],[1,3],[0,2],[-1,2],[-1,6],[0,3],[1,2],[1,2],[4,4],[3,6],[2,2],[1,2],[0,3],[-2,2],[-1,2],[0,3],[0,2],[0,2],[0,2],[0,2],[1,4],[2,4],[1,3],[2,-2],[2,1],[2,2],[1,5],[0,3],[0,2],[1,7],[0,1],[1,5],[0,4],[0,7],[0,6],[0,12],[1,2],[1,6],[1,6],[3,4],[2,4],[1,1],[1,0],[3,-3],[3,4],[3,0],[2,0],[2,-2],[1,-1],[3,4],[1,-1],[1,-1],[1,0],[2,1],[4,-1],[7,0],[5,-3],[5,-6],[2,-1],[1,0]],[[8522,5416],[-1,-1],[-2,0],[0,3],[2,6],[1,5],[-2,1],[-1,4],[0,4],[1,8],[2,-1],[1,-3],[1,-6],[1,-5],[-2,-6],[-1,-9]],[[7680,5485],[3,-1],[6,4],[4,-1],[3,-2],[3,-1],[7,1],[2,0],[1,-1],[1,-2],[3,-8],[6,-9],[2,-6],[0,-7],[1,-1],[6,-13],[1,-5],[-1,-8],[2,-5],[6,-6],[4,-4],[1,-2],[0,-3],[2,-5],[3,-2],[7,-8],[11,-15],[6,-8],[4,-11],[2,-5],[2,-6],[3,-9],[5,-10],[1,-3],[1,-5],[2,-4],[2,-4],[2,-3],[2,-1],[4,-8],[2,-2],[-1,6],[-1,5],[0,3],[0,3],[1,2],[2,1],[3,-2],[5,-9],[2,-5],[2,-8],[1,-7],[2,-4],[3,-1],[3,-1],[3,-2],[6,-10],[2,-5],[2,-6],[1,-6],[1,-8],[0,-1],[4,-9],[3,-3],[2,-2],[8,-2],[3,-3],[2,-5],[1,-5],[-1,-4],[-7,-7],[-6,-5],[6,2],[3,2],[3,3],[3,4],[5,5],[2,1],[2,0],[2,-2],[2,-5],[3,-6],[2,-6],[1,-7],[-2,-4],[-3,-3],[-5,-7],[0,-3],[1,-2],[-1,-5],[2,-3],[0,-3],[-2,-4],[1,-2],[2,-11],[1,-2],[4,-5],[6,-6],[4,-2],[4,-2],[1,0],[3,1],[1,-2],[1,-10],[1,-7],[0,-13],[2,-6],[-1,-7],[2,-6],[3,-4],[3,-3],[2,-3],[0,-4],[-1,-4],[-1,-3],[-3,-6],[-1,-2],[0,-7],[0,-3],[2,0],[1,2],[4,8],[1,2],[1,1],[2,1],[7,0],[3,-1],[3,-3],[2,-4],[9,-23],[4,-12],[0,-3],[0,-4],[0,-2],[-4,-9],[-1,-2],[-1,-9],[1,-7],[1,-3],[1,-3],[0,-3],[-3,-14],[0,-2],[2,-22],[0,-7],[-1,-7],[1,-13],[-2,-38],[-1,-2],[-1,-6],[-2,0],[-2,1],[-1,2],[-1,3],[-1,2],[-4,7],[-2,-1],[-5,-9],[-1,-1],[-1,1],[-3,3],[-8,9],[-1,-3],[0,-4],[2,-10],[0,-5],[-1,0],[-1,0],[-4,6],[-3,6],[-3,9],[-3,4],[-2,5],[-7,17],[-1,3],[-10,12],[-2,3],[-3,5],[-3,5],[-6,7],[-11,19],[-4,10],[-5,17],[-2,4],[-9,13],[-4,8],[-2,4],[-5,16],[-1,5],[-2,5],[-2,3],[-3,5],[-5,14],[-1,5],[-1,6],[0,12],[-10,37],[-3,11],[-2,16],[-1,2],[-6,14],[-2,4],[-2,5],[-2,5],[-4,16],[-1,4],[-2,4],[-7,6],[-3,3],[-2,5],[-2,6],[-1,13],[-4,20],[-3,27],[-3,12],[-3,9],[-1,2],[-13,17],[-2,3],[-3,1],[-3,1],[-3,5],[-1,7],[-1,11],[0,6],[-1,4],[-5,7],[-3,6],[-1,6],[-2,5],[-6,18],[-2,4],[-3,3],[-8,4],[-2,3],[-3,9],[-3,5],[-6,11],[-12,23],[-2,6],[-2,6],[-1,6],[-5,18],[0,4],[1,3],[0,4],[-1,3],[0,2],[2,2],[3,2],[3,0],[4,-1],[3,-2],[2,-4],[6,-9],[3,-3],[3,-2],[7,-2]],[[7648,5519],[0,-2],[-2,1],[-2,5],[1,1],[1,0],[2,-2],[0,-2],[0,-1]],[[4877,8305],[-6,-8],[-2,2],[-2,-1],[1,3],[1,6],[2,2],[3,7],[3,2],[0,-1],[1,0],[1,-7],[-1,-3],[-1,-2]],[[7607,5577],[-1,-4],[-4,14],[-1,1],[0,7],[1,3],[3,3],[1,-2],[2,-14],[-1,-8]],[[7603,5608],[-3,-6],[-1,3],[1,3],[1,1],[1,2],[1,-3]],[[7595,5638],[-2,-1],[-1,3],[-1,3],[1,2],[1,1],[2,-4],[0,-3],[0,-1]],[[7597,5648],[-1,-2],[0,2],[0,1],[-1,2],[0,3],[1,4],[1,-1],[0,-3],[0,-6]],[[7029,5660],[0,-1],[-1,0],[0,1],[1,0],[0,2],[0,1],[0,-2],[0,-1]],[[7586,5659],[1,-2],[-1,0],[-2,3],[1,3],[0,2],[1,-6]],[[7577,5710],[-2,0],[0,2],[0,2],[0,1],[1,1],[1,0],[0,-4],[0,-2]],[[7569,5792],[-1,-2],[-3,1],[0,6],[0,6],[0,2],[2,5],[2,1],[1,-5],[1,-6],[-2,-8]],[[7574,5839],[-1,-1],[-2,2],[1,2],[1,5],[1,-3],[0,-3],[0,-2]],[[7583,5877],[1,-8],[-2,4],[-1,2],[1,2],[1,0]],[[7575,5925],[-1,-4],[0,8],[0,1],[1,0],[0,-5]],[[7575,5848],[-1,-1],[-1,1],[-2,11],[-1,6],[0,3],[1,3],[1,1],[0,4],[1,5],[1,5],[0,1],[2,0],[1,1],[-1,4],[-1,2],[0,2],[0,10],[0,4],[1,4],[-1,6],[1,2],[1,4],[1,7],[-1,2],[2,11],[0,7],[1,8],[3,3],[1,0],[0,-6],[1,-2],[-2,-4],[2,-5],[-1,-2],[0,-3],[-1,-4],[-2,-2],[-1,-5],[-1,-2],[3,-5],[0,-18],[-1,-5],[-2,-1],[0,-12],[0,-3],[-2,-5],[0,-3],[-1,-2],[0,-3],[1,-2],[0,-2],[-1,-7],[0,-7],[-1,-6]],[[7186,7020],[0,1],[-2,4],[2,-5]],[[7203,6975],[1,-1]],[[7219,6963],[0,0]],[[7219,6963],[5,-6]],[[7250,6921],[-2,1],[-1,0],[-2,-2],[-1,-1],[-3,-8],[-2,-2],[-2,-3],[-4,-10],[-3,-9],[-1,-8],[0,-7],[-1,-7],[-2,-4],[-1,-1],[-1,-6],[-1,-7],[0,-3],[3,-3],[2,-3],[3,-3],[2,-3],[2,-1],[0,2],[1,2],[2,-1],[2,-3],[2,-3],[4,-4],[4,-4],[4,-4],[1,-3],[1,-3],[2,-3],[5,-7],[4,-5],[3,-3],[3,-3],[1,0],[2,2],[1,1],[1,-1],[2,-2],[5,-6],[5,-5],[5,1],[1,-1],[1,-5],[0,-4],[6,-3],[4,-1],[4,-3],[2,-2],[2,3],[0,2],[2,1],[3,-1],[6,-3],[2,-1],[2,3],[3,2],[2,1],[4,-3],[7,-5],[4,-3],[0,-3],[1,-2],[0,-7],[1,-3],[7,-6],[2,-3],[2,-1],[1,0],[1,-1],[0,-4],[1,0],[1,-1],[2,-1],[4,3],[3,3],[2,-1],[2,-3],[0,-4],[1,-4],[1,-2],[2,0],[4,3],[4,-2],[3,-1],[3,-2],[2,-1],[3,-3],[5,-4],[1,1],[7,6],[1,0],[1,-7],[3,-2],[3,-2],[3,4],[3,-1],[4,-1],[3,2],[3,1],[4,-4],[0,1],[1,2],[2,9],[1,8],[0,5],[-1,7],[-3,9],[-1,3],[1,16],[2,9],[1,4],[1,6],[0,3],[0,3],[-1,1]],[[7703,6809],[-1,-4],[0,-3],[1,-4],[0,-2],[0,-3],[-1,-2],[-2,-1],[-2,-3],[-3,-4],[-2,-4],[-2,-3],[-1,-3],[0,-4],[1,-5],[6,-16],[0,-2],[-2,-1],[-3,2],[-2,2],[-2,7],[-2,2],[-2,0],[-10,-3],[-3,-1],[-3,-3],[-3,-5],[-2,-4],[-2,-2],[-2,-4],[-8,-11],[-4,-5],[-3,-2],[-2,-2],[-1,-4],[-1,-3],[0,-8],[0,-9],[1,-5],[1,-2],[0,-1],[-1,-3],[-2,-3],[0,-2],[-1,-8],[-1,-4],[-3,-6],[-2,-4],[-3,-4],[-1,-3],[-2,-5],[0,-4],[0,-2],[0,-1],[1,-2],[2,-1],[1,-3],[0,-2],[-1,-7],[-2,-10],[-3,-7],[-3,-7],[0,-3],[-3,-8],[-2,-12],[-1,-8],[-1,-6],[-2,0],[-1,2],[-5,2],[-2,2],[-2,2],[-2,-1],[-2,-1],[-2,0],[-1,0],[-3,5],[-1,-3],[2,-14],[1,-5],[0,-9],[-1,-11],[0,-12],[-1,-3],[-1,-3],[-1,-1],[-2,2],[-1,-1],[0,-2],[0,-5],[-1,-6],[-1,-5],[0,-5],[0,-5],[2,-10],[0,-4],[0,-4],[-1,-1],[-1,0],[-1,-1],[-1,-3],[-1,-8],[-2,-1],[-1,2],[-3,5],[-1,2],[-1,0],[0,-2],[-1,-3],[-1,-2],[-1,-2]],[[7473,6456],[-1,-9],[-2,0],[2,-6],[1,-4],[0,-6],[-2,-1],[-2,1],[-1,5],[-1,-5],[-3,-4],[0,2],[-1,3],[0,4],[1,15],[0,2],[-1,1],[-1,1],[0,3],[-3,-17],[1,-7],[0,-3],[-4,-2],[-4,6],[0,2],[-1,-3],[0,-5],[-4,1],[-2,3],[1,6],[3,14],[0,6],[-3,5],[-2,2],[-2,7],[1,-7],[1,-3],[2,-2],[2,-3],[-1,-4],[-2,-3],[-3,-10],[-3,-6],[-4,-4],[-13,-6],[-3,-3],[-4,-8],[-3,-7],[0,-8],[1,-8],[1,-12],[1,-3],[-1,-5],[-3,-4],[-2,-7],[1,-4],[-1,-2],[-7,-8],[-1,-5],[-2,-5],[-3,3],[-1,0],[2,-4],[0,-2],[-1,-2],[-2,-1],[-10,-6],[-8,-6],[-2,0],[1,2],[1,2],[0,6],[-2,1],[-1,1],[-6,-8],[-2,-8],[0,-2],[2,1],[4,4],[2,-1],[0,-2],[-6,-7],[-13,-22],[-1,-4],[-1,-5],[-2,-4],[-5,-12],[-7,-16],[-3,-7],[-12,-12],[-2,-4],[-5,-13],[-6,-10],[-6,-8],[-10,-11],[-7,-10],[-2,-7],[0,-3],[1,-3],[1,-3],[0,-3],[-1,-4],[0,-2],[-2,-6],[-3,-5],[-11,-9],[-1,1],[-9,1],[-3,-1],[-1,-4],[-3,-18],[-3,-4],[-1,-5],[0,-3],[-2,1],[-1,1],[-2,-1],[-1,6],[-2,1],[-2,0],[-7,-6],[-2,-4],[-6,-23],[-1,-14],[1,-16],[2,-13],[0,-5],[0,-8],[-1,-3],[0,-5],[0,-8],[3,-12],[0,-5],[0,-5],[2,-11],[-1,2],[-1,4],[-2,7],[-3,-7],[2,-4],[5,-5],[1,-5],[-3,-38],[-3,-14],[-2,-9],[-2,-3],[-3,-15],[-3,-17],[0,-6],[1,-8],[-1,-4],[-2,-4],[3,2],[1,-4],[0,-4],[0,-25],[0,-26],[-2,-1],[-3,0],[-2,1],[-2,1],[-3,-2],[-3,-2],[-1,-5],[0,-8],[-7,-20],[-2,-7],[-1,-7],[1,-3],[2,-4],[3,-1],[4,-1],[3,-2],[1,-4],[-5,4],[-7,1],[-15,-10],[-4,-6],[-3,-6],[-1,-13],[-1,-9],[-1,-7],[-8,-11],[-6,-4],[-1,-3],[-6,4],[-7,10],[-3,5],[-9,25],[-2,4],[-2,10],[0,4],[-1,2],[-1,1],[0,2],[-3,12],[0,13],[-2,15],[1,-1],[2,-5],[1,-7],[0,-10],[1,-1],[1,1],[-3,22],[-3,6],[-1,4],[0,4],[0,2],[-2,8],[-1,4],[-5,22],[-2,16],[-3,17],[-2,6],[-4,14],[-3,6],[-3,9],[-2,3],[-1,2],[-7,29],[-2,17],[-2,7],[-1,6],[-2,25],[0,4],[-1,5],[-1,11],[-3,11],[-1,7],[0,3],[-2,11],[-1,5],[-1,4],[-1,5],[-2,3],[-4,11],[-1,3],[-3,7],[-1,13],[-3,6],[4,0],[-2,5],[-1,3],[-1,2],[1,5],[-3,0],[-1,3],[-2,9],[-4,10],[0,6],[-4,18],[-2,42],[-3,19],[0,6],[-3,16],[-1,11],[-1,10],[0,6],[-1,12],[-1,4],[-1,2],[1,5],[2,9],[1,5],[-1,8],[-2,-8],[-2,-2],[0,6],[0,8],[-1,2],[1,2],[5,-1],[-6,5],[0,3],[-1,2],[2,4],[-3,3],[0,11],[-1,2],[0,2],[1,14],[5,28],[0,7],[0,8],[-1,8],[-1,7],[0,2],[-2,1],[-1,3],[-2,11],[1,3],[2,2],[-2,0],[-2,0],[3,5],[3,4],[6,5],[2,3],[-4,-3],[-3,-1],[-9,0],[2,11],[1,3],[2,2],[-3,0],[-2,1],[1,10],[2,2],[2,1],[3,1],[-3,2],[-3,1],[-4,-2],[-3,2],[-5,0],[2,-2],[2,-3],[-1,-6],[-1,-3],[-2,-3],[-2,-4],[-1,-3],[-1,-2],[2,-2],[2,-1],[1,-3],[1,-4],[0,-7],[-5,-18],[-1,-4],[-13,-10],[-4,-6],[-11,-8],[-4,-1],[-4,1],[-7,6],[-10,15],[-2,5],[-8,18],[-6,10],[-4,10],[-6,8],[-5,12],[-1,6],[1,5],[1,3],[3,-1],[1,-5],[2,-2],[1,-1],[7,7],[3,0],[2,4],[3,-1],[5,6],[2,0],[3,1],[4,14],[3,9],[2,2],[0,2],[-1,3],[-1,-1],[-1,-3],[-1,-3],[-1,-2],[-2,2],[-2,0],[-2,-1],[-7,-6],[-3,-4],[-3,-1],[-11,5],[-12,12],[-5,8],[-3,10],[-3,11],[1,4],[5,7],[4,6],[-4,-3],[-4,-3],[-2,-3],[-2,-5],[-3,-1],[-1,8],[-1,7]],[[6893,6558],[2,2],[1,2],[3,1],[3,1],[2,0],[4,0],[0,17],[1,2],[0,1],[1,0],[1,-3],[1,1],[1,1],[3,-1],[1,1],[2,-1],[4,0],[5,0],[4,0],[2,-3],[2,-3],[2,0],[4,0],[2,1],[2,3],[0,3],[6,4],[5,3],[2,0],[0,-2],[0,-3],[1,-3],[2,-2],[2,0],[1,0],[1,1],[2,5],[2,1],[1,0],[2,2],[0,2],[-1,1],[-1,2],[0,2],[0,3],[0,3],[1,2],[1,2],[-1,4],[-2,8],[-2,9],[-2,9],[-3,7],[-1,5],[0,12],[0,2],[-1,2],[-1,0],[-2,-1],[-2,0],[-3,0],[-2,1],[-4,12],[-1,5],[0,5],[1,8],[1,7],[0,8],[0,2],[-1,2],[-2,2],[-4,0],[-5,2],[-3,5],[-3,2],[-1,2],[0,2],[1,8],[1,10],[1,3],[1,3],[1,2],[2,3],[5,9],[4,13],[3,9],[1,3],[2,2],[2,2],[2,3],[2,0],[3,-2],[1,-3],[1,-6],[1,-4],[1,-2],[2,-1],[2,0],[9,7],[3,1],[7,1],[4,3],[5,2],[0,5],[2,8],[5,10],[1,4],[2,8],[1,8],[2,3],[8,8],[7,8],[2,3],[5,16],[3,11],[0,3],[2,10],[2,9],[2,2],[5,4],[5,3],[2,4],[1,4],[0,3],[-1,4],[0,2],[0,3],[3,5],[6,14],[3,7],[1,0],[4,4],[3,4],[0,2],[0,3],[-2,1],[-1,3],[1,4],[1,12],[0,4],[-2,10],[0,3],[1,3],[3,5],[2,3],[10,8],[1,1],[4,2],[2,4],[0,4],[-1,2],[-2,3],[-3,3],[-4,3],[-5,-1],[-3,2],[-1,2],[0,5],[0,9],[-1,0],[-1,-1],[-3,1],[-3,0],[-2,3],[1,3],[0,3],[-1,4],[0,1],[-2,1],[-3,3],[-2,4],[-1,2],[0,2],[0,1],[1,4],[2,5],[1,4],[0,3],[0,2],[-2,3],[-2,2],[-1,2],[0,3],[1,4],[2,3],[4,3],[1,3],[0,3],[-1,0],[-3,0],[-5,1],[0,2],[-1,2],[0,1],[1,2],[1,3],[0,3],[-1,3],[-3,2],[-1,3],[1,2],[1,4],[1,3],[2,7],[2,1],[4,3],[3,2],[6,-2],[2,-1],[6,-2],[4,-2],[5,0],[2,0],[2,-2],[5,-4],[4,-2],[3,0],[5,3],[2,3],[3,4],[3,0],[8,5],[2,-1],[2,0],[3,2],[1,4],[0,2],[1,1],[3,2],[3,3],[1,4],[1,3]],[[7140,7206],[3,4],[3,3],[4,4],[4,5],[4,3],[2,3]],[[7160,7228],[1,0]],[[7197,7098],[0,-4]],[[7200,7059],[0,-3]],[[7691,4481],[0,1],[0,1],[1,0],[0,-1],[-1,-1]],[[7689,4482],[1,0],[0,-1],[-1,1],[0,2],[0,1],[0,-1],[0,-1],[0,-1]],[[7936,4579],[-1,-4],[-1,3],[-2,0],[0,3],[2,1],[1,1],[1,-4]],[[7013,4759],[-1,-2],[-1,-1],[0,5],[-2,4],[1,0],[1,-2],[1,-5],[0,1],[0,2],[0,2],[0,2],[-1,2],[1,1],[1,-2],[0,-2],[0,-5]],[[4723,8289],[0,-2],[-2,3],[-1,2],[-6,1],[3,2],[1,-1],[4,0],[1,-1],[0,-4]],[[4827,8299],[1,-2],[0,-2],[-2,-1],[-2,1],[-1,-2],[0,-2],[1,-4],[1,-2],[1,-6],[1,-6],[2,-3],[0,-5],[0,-2],[0,-4],[0,-1],[0,-4],[2,-8],[1,-4],[0,-10],[-1,-3],[-2,-4],[-1,-4],[-1,-4],[0,-7],[-4,-8],[-1,-2],[-2,-1],[4,-6],[-3,-2],[-4,-1],[-4,1],[-2,0],[-2,-2],[-1,-1],[-1,1],[-1,4],[-1,-5],[-2,-1],[-4,0],[-6,-1],[-3,-1],[-1,-3],[0,-2],[-1,-1],[-1,-1],[-5,-2],[-1,-1],[-2,-4],[-3,-2],[-3,-1],[-2,3],[-1,1],[-1,1],[-3,0],[1,-1],[1,-2],[0,-3],[0,-3],[-2,-2],[-2,0],[-3,-3],[-4,-1],[-2,-3],[-14,-5],[-2,1],[-2,1],[-2,-1],[-6,-2],[-3,0],[4,7],[4,4],[1,1],[-2,0],[-8,-2],[-4,-2],[-3,-1],[2,3],[4,4],[2,2],[1,1],[2,3],[4,3],[-14,-6],[-3,0],[-1,2],[-3,-1],[-1,4],[4,6],[3,3],[3,1],[2,3],[1,2],[-1,1],[-8,-1],[-4,1],[0,2],[1,2],[4,4],[2,0],[2,0],[2,-1],[1,-1],[5,0],[-2,3],[0,5],[-2,1],[2,2],[2,2],[4,4],[1,1],[7,1],[8,3],[8,3],[-4,2],[-2,2],[-3,-5],[-2,-2],[-6,-1],[-2,1],[-3,2],[-1,-1],[-1,-1],[-4,-3],[-4,0],[5,4],[6,8],[2,2],[2,5],[-1,1],[-1,1],[4,9],[2,2],[3,0],[2,1],[1,0],[1,1],[1,2],[-2,2],[-3,1],[-10,-1],[-1,0],[-1,1],[-1,1],[0,3],[-1,1],[-2,0],[-2,-1],[-1,0],[-2,1],[2,3],[-2,1],[-3,-1],[-3,1],[0,2],[1,2],[-1,2],[0,2],[1,1],[2,0],[3,2],[5,0],[-4,2],[-2,1],[0,3],[0,1],[5,4],[4,1],[0,2],[0,2],[-4,1],[-5,-2],[1,5],[1,3],[0,3],[0,3],[-2,-2],[-1,4],[-1,3],[-3,-2],[0,4],[1,2],[2,1],[2,0],[3,0],[3,1],[4,1],[7,-1],[4,-5],[2,1],[2,3],[0,1],[8,-2],[4,-2],[1,1],[0,4],[-2,2],[2,3],[2,3],[2,1],[3,1],[2,1],[1,5],[2,3],[-9,-2],[-9,4],[1,3],[2,2],[3,1],[1,2],[1,1],[3,3],[-1,5],[0,3],[2,2],[1,3],[1,2],[3,1],[4,2],[1,0],[5,0],[1,-1],[0,4],[3,0],[1,0],[0,-3],[1,-1],[1,-3],[-1,-2],[-2,-2],[2,-2],[-2,-3],[2,1],[3,3],[0,3],[-1,3],[-1,3],[1,3],[1,2],[5,1],[-2,3],[2,1],[1,-1],[3,-3],[2,-2],[3,-2],[-2,-3],[-4,-2],[-1,-3]],[[6560,6734],[-2,-6],[-4,-6],[-2,2],[-1,-1],[-3,-2],[-2,0],[-4,-4],[-3,-2],[-2,0],[-1,0],[-1,3],[0,1],[2,0],[5,3],[6,6],[1,3],[-1,4],[0,1],[4,-2],[5,4],[4,1],[2,-3],[-3,-2]],[[6357,7398],[0,-3],[1,-14],[0,-8],[1,-7],[2,-6],[2,-7],[2,-3],[6,-5],[3,-1],[7,-1],[7,-2],[4,-3],[1,-1],[1,-2],[4,-11],[5,-8],[11,-12],[5,-4],[18,-7],[12,0],[33,14],[11,4],[4,0],[-2,-3],[-5,-2],[3,-2],[4,0],[2,0],[1,2],[0,3],[0,3],[-2,13],[-1,10]],[[6497,7335],[8,-1],[3,1],[4,3],[3,2],[2,1],[2,1],[1,2],[3,13],[1,3],[5,7],[4,4],[5,4],[5,3],[7,0],[6,-1],[4,0],[1,0],[1,0],[1,1],[1,6],[1,1],[2,2],[3,0],[4,0],[2,0],[4,-2],[5,0],[3,0],[2,-2],[1,-3],[1,-2],[0,-4],[0,-2],[1,-1],[1,-1],[3,-2],[5,-1],[5,-2],[3,-2],[3,-3],[5,-7],[1,-1],[2,0],[2,0],[3,3],[3,-3],[1,1],[3,1],[3,-2],[9,-7],[1,0],[1,-1],[0,-1],[1,-2],[0,-7],[3,-4],[3,-5],[3,-2],[8,-6],[3,-4],[3,-8],[4,-10],[0,-1],[11,0],[11,0],[1,-4],[0,-8],[1,-8],[1,-6],[0,-5],[-1,-3],[-1,-3],[0,-1],[1,-2],[2,-4],[0,-6],[-1,-4],[0,-2],[1,-3]],[[6697,6919],[-7,-14],[-1,-1]],[[6689,6904],[6,-12],[3,-7],[5,-9],[0,-3],[0,-4],[5,-14],[2,-8],[1,-5],[4,-7],[3,-7],[4,-3],[3,-1],[6,-4],[3,-2],[3,-8],[4,1],[1,0],[1,0],[0,-3],[-1,-11],[1,-12],[1,-17],[0,-3],[-1,-5],[0,-4],[-1,-2],[1,-1],[1,-1],[3,0],[7,2],[1,-1],[1,-2],[2,-3],[0,-2],[-2,-3],[0,-4],[0,-7],[0,-1],[-2,-1],[0,-10],[0,-1],[-2,-1],[-9,0],[-1,0],[-3,-2],[-5,-2],[-2,-1],[-2,-3],[-1,-4],[-1,-3],[0,-1],[-3,1],[-1,-3],[-6,-5],[-1,-1],[-1,-3],[-1,-10],[0,-9],[-1,-1],[-2,-3],[0,-1],[0,-3],[0,-7],[-1,-17],[-1,-5]],[[6710,6635],[-1,0],[-2,-2],[-2,-3],[-4,2],[-4,2],[-13,6],[-1,3],[-1,5],[-2,1],[-3,-7],[-10,4],[-4,-1],[-2,2],[-6,0],[-4,4],[-6,-3],[-5,0],[-7,8],[-8,2],[-6,-1],[-3,1],[-5,3],[-2,3],[-4,-3],[-2,5],[-11,3],[-2,8],[-2,7],[0,7],[-2,12],[-1,18],[-1,6],[-2,7],[-2,5],[-3,5],[-2,2],[-10,4],[-2,0],[-5,-3],[-5,-6],[-8,-3],[-1,-3],[-2,-6],[-3,-3],[-4,1],[-4,-4],[-7,-10],[-4,-3],[-3,1],[-3,4],[-8,6],[-5,3],[-7,-2],[-3,1],[-5,7],[-2,6],[-3,3],[-10,8],[-8,11],[-1,4],[-1,5],[-4,7],[-8,6],[-4,6],[-6,2],[-4,0],[-3,1],[-2,2],[-6,13],[0,5],[-4,13],[-1,4],[-1,12],[-1,4],[-5,5],[0,3],[1,4],[0,4],[-3,3],[-3,2],[-1,3],[1,8],[-1,4],[-3,8],[-4,7],[-4,11],[-2,3],[-1,8],[-2,8],[-2,1],[-12,-11],[-4,6],[-10,10],[-1,2],[0,2],[1,2],[1,0],[3,-2],[1,3],[0,3],[-3,2],[-3,0],[1,-3],[-4,-3],[-1,-4],[1,-5],[0,-7],[-1,-4],[-1,-1],[-5,-1],[-2,-3],[-1,0]],[[6348,6910],[-2,2],[-1,2],[-1,4],[-1,3],[1,2],[-1,2],[-1,3],[-2,2],[-1,0],[-1,2],[-1,4],[-2,2],[-2,1],[0,11],[0,9],[0,10],[-5,0],[-4,0],[0,9],[0,14],[2,12],[2,11],[-3,8],[-4,9],[-2,4],[-2,11],[-2,4],[-1,2],[-1,1],[-5,0],[-4,6],[-5,7],[-6,8],[-5,5],[-3,2],[-5,0],[0,1],[-1,3],[0,4],[2,5],[0,3],[-3,10],[-1,4],[-3,1],[0,3],[0,2],[0,2],[-1,0],[-1,1],[-2,-2],[-2,5],[-5,14],[-2,2],[-1,0],[2,5],[2,6],[0,4],[0,4],[-2,7],[0,3],[1,4],[0,3],[2,-1],[2,0],[1,2],[0,8],[0,3],[7,13],[3,3],[3,3],[0,4],[0,2],[-1,3],[0,2],[-3,6],[-1,3],[0,3],[1,5],[1,4],[4,2],[2,2],[1,1],[-3,3],[-6,1],[-5,-1],[-2,1],[-2,5],[-2,3],[-2,2],[-2,0],[-2,0],[0,2],[-3,18],[-1,2],[-1,1],[-1,0],[-1,1],[-1,3],[-1,3],[0,4],[0,3],[0,3],[-1,2],[-2,1],[-1,2],[-2,16],[-1,4]],[[6243,7323],[0,1],[0,3],[1,3],[0,2],[-3,4],[-3,3],[0,1],[0,4],[0,3],[-1,3],[0,2],[0,1],[1,3],[-1,2],[-4,5],[-2,2],[-3,1],[-1,1],[1,4],[1,4],[2,4],[0,2],[1,4],[0,2],[2,4],[0,1],[0,1],[-2,1],[-2,0],[0,1],[0,2],[0,8],[-1,4],[0,4],[0,8],[-1,1],[-2,4],[0,4],[0,1],[0,2],[1,3],[0,2],[-2,3],[-1,2],[0,2],[-1,3],[0,2],[-1,2],[1,1],[2,0],[3,0],[3,0],[1,1],[2,15],[2,3],[2,2],[4,-5],[1,-1],[1,0]],[[6348,6910],[-3,-2],[-2,1],[-6,5],[-2,0],[-3,-2],[0,-1]],[[6332,6911],[-6,5],[-2,1],[-1,0],[-4,0],[-5,-1],[-3,-2],[-2,-2],[-1,-2],[0,-2],[-2,-6],[-2,-9],[-2,-8],[-3,-11],[-3,-5],[-4,-9]],[[6292,6860],[-5,-2],[-11,2],[-13,2],[-12,2],[-9,1],[-1,1],[-9,13],[-8,11],[-9,13],[-9,14],[-9,13],[-7,10],[-8,13],[-8,12],[-6,9],[-8,8],[-5,6],[-9,10],[-7,7],[-6,6],[-9,10],[-3,2],[-10,4],[-9,2],[-9,3],[-6,2]],[[6087,7034],[4,7],[-1,6],[-3,-1],[-3,-1],[-2,9],[2,1],[-2,13],[-2,13],[-2,12],[-2,13]],[[6076,7106],[8,8],[6,6],[8,9],[8,8],[8,8],[8,9],[8,7],[6,3],[2,3],[3,10],[3,9],[0,3],[0,12],[0,15],[1,8],[2,7],[1,6],[0,4],[0,5],[-1,8],[-2,8],[0,7],[1,4],[1,6],[1,5],[2,3],[6,3],[4,2],[5,8],[3,5],[5,8],[3,5],[0,2],[0,1]],[[6176,7321],[3,1],[5,7],[3,7],[1,0],[2,-2],[2,0],[4,2],[3,-1],[2,-2],[1,0],[6,-4],[2,0],[3,-1],[4,0],[3,2],[2,3],[1,0],[2,-1],[1,-1],[1,-2],[0,-2],[0,-9],[1,-2],[0,-2],[1,0],[2,2],[2,2],[2,3],[2,3],[1,1],[2,0],[2,-1],[1,-1]],[[4568,8998],[3,0],[5,2],[2,2],[6,4],[3,1],[5,0],[2,0],[-3,-2],[-2,-1],[-4,-2],[-3,-6],[-2,-3],[0,-2],[3,-2],[3,-2],[3,2],[1,-1],[1,-2],[1,-1],[0,-2],[0,-4],[-2,-3],[-3,-3],[1,-1],[2,-1],[9,2],[1,0],[0,-1],[0,-2],[1,-1],[1,-2],[0,-1],[-4,-5],[4,3],[4,1],[6,-2],[3,-2],[2,-3],[2,1],[1,0],[1,-1],[0,-2],[-1,-3],[0,-2],[-1,-1],[-2,-1],[-1,-1],[1,-2],[1,-2],[2,0],[1,0],[0,-1],[-1,-2],[-1,-1],[-2,-1],[5,-3],[1,-1],[0,-2],[0,-1],[-1,-2],[-2,-1],[-3,-1],[-2,-1],[0,-2],[0,-2],[0,-3],[-3,-5],[-3,-2],[-2,-2],[-5,1],[-2,1],[0,-4],[-2,-2],[0,-2],[1,-1],[0,-3],[-2,-2],[-2,-3],[-2,-2],[-4,-2],[-4,-3],[-3,-2],[-6,0],[-7,-2],[-9,-5],[-7,-3],[-4,-5],[-7,-7],[-5,-3],[-2,0],[-6,-1],[-4,-2],[-15,-3],[-5,-2],[-1,-2],[-2,-3],[0,-1],[1,-1],[0,-1],[-2,-3],[-4,-2],[-1,0],[-3,2],[-1,0],[0,-1],[1,-2],[-2,-1],[-10,-3],[-16,2],[-7,2],[-8,3],[-5,1],[-6,1],[-6,4],[-3,3],[0,1],[0,2],[1,1],[1,0],[2,0],[0,1],[-1,2],[-2,-1],[-3,-3],[-2,0],[-2,2],[0,1],[-4,1],[-4,2],[-4,3],[0,1],[2,1],[-1,1],[-1,0],[-3,-1],[-4,-3],[-1,-1],[-26,-1],[-6,0],[-2,-1],[-1,3],[-1,5],[0,3],[0,2],[1,2],[1,0],[2,-2],[1,-2],[1,-1],[9,2],[4,2],[1,2],[2,3],[2,1],[1,2],[2,5],[1,2],[2,1],[1,1],[4,1],[-2,1],[-3,0],[-8,-5],[-3,0],[0,1],[1,1],[3,3],[-2,0],[-1,1],[0,2],[2,4],[7,5],[2,0],[1,1],[-1,1],[-2,0],[-6,-4],[-5,-2],[-2,0],[-3,2],[0,1],[-2,2],[1,1],[2,4],[0,1],[-2,0],[-5,4],[-7,0],[-17,2],[-4,-1],[-5,-3],[-4,-1],[-2,0],[-1,2],[-2,2],[-1,3],[1,2],[2,1],[2,0],[4,0],[6,2],[4,0],[1,0],[2,2],[1,1],[2,-1],[1,-1],[5,2],[2,1],[1,1],[1,0],[2,-1],[3,0],[3,1],[5,0],[11,1],[2,1],[1,2],[1,4],[0,1],[-8,-4],[-1,0],[-9,2],[-3,2],[1,2],[5,3],[4,3],[7,4],[2,1],[0,1],[-5,3],[-8,-1],[-2,4],[-7,1],[-5,-1],[-3,2],[-6,-3],[-13,-3],[-5,-3],[-3,-1],[-4,2],[-5,3],[-7,1],[0,1],[3,4],[3,1],[3,0],[4,-3],[4,-1],[-4,4],[0,2],[-1,2],[-1,2],[-1,2],[0,1],[2,1],[3,-1],[9,-5],[4,1],[2,2],[3,1],[-1,1],[-7,0],[-4,1],[-2,1],[-1,3],[0,1],[2,1],[6,-1],[-4,5],[-3,2],[0,1],[0,2],[1,1],[7,-2],[2,0],[-2,1],[-3,3],[0,1],[1,0],[1,2],[0,1],[2,1],[2,0],[2,-1],[7,-5],[1,-1],[0,-2],[0,-2],[0,-1],[3,1],[2,-1],[1,0],[2,4],[2,-1],[1,-2],[1,-1],[0,-2],[-1,-4],[2,2],[3,0],[1,1],[0,4],[-1,4],[-10,5],[-2,1],[-2,3],[1,1],[2,1],[2,0],[7,0],[1,1],[-1,1],[-3,1],[-1,0],[-1,2],[-3,-1],[-5,0],[-4,1],[0,1],[2,1],[3,3],[2,1],[4,-1],[5,1],[4,-1],[3,-3],[4,-4],[5,-3],[1,-1],[3,-2],[6,-7],[6,-3],[0,-1],[-1,-1],[-2,-2],[3,-1],[3,-3],[0,-1],[-2,-8],[-1,-1],[-1,-1],[-6,1],[1,-2],[4,-3],[1,-1],[0,-2],[1,1],[1,-1],[0,-2],[-1,-2],[-1,-2],[1,-1],[1,1],[2,-1],[2,-2],[2,-7],[1,-2],[0,2],[1,5],[1,2],[1,0],[0,1],[1,2],[1,5],[4,4],[1,2],[2,0],[1,-1],[3,-4],[1,-1],[1,1],[2,3],[1,5],[0,6],[0,7],[0,5],[2,3],[2,1],[3,-1],[2,-2],[4,-7],[4,-3],[3,-4],[1,-1],[3,-1],[1,0],[0,1],[1,2],[-1,9],[1,3],[1,3],[5,1],[3,1],[3,3],[2,1],[2,0],[2,-1],[2,-2],[3,-4],[4,-6],[5,-4],[2,-8],[1,-1],[1,0],[0,1],[1,1],[0,4],[-2,4],[-4,11],[0,2],[0,1],[4,1],[7,-1],[3,-2],[5,-7],[1,-1],[1,-1],[0,1],[2,1],[2,2],[2,3],[5,7],[1,0],[2,0],[2,-2],[1,-1],[3,-1],[2,0],[4,2],[4,2],[1,3],[0,1],[-3,10],[1,2],[7,2],[6,1],[2,-1],[3,-5],[3,-2],[1,-2],[0,-4],[2,-2],[3,-2]],[[5993,7069],[-1,0],[-3,-3],[-1,-1],[0,-1],[-1,-1],[0,-13]],[[5987,7050],[-2,0],[-2,3],[-1,2],[0,1],[-2,0],[-3,2],[-4,-5],[-1,-7],[0,-3],[-2,-7],[1,-4],[0,-6],[0,-4],[0,-3],[-1,-1],[1,-1],[0,-1],[2,2],[2,-2],[2,-2],[0,-1],[-1,-1],[-3,-4],[-3,-4],[0,-4],[-2,-8],[0,-1],[1,-1],[5,0],[5,4],[4,3],[1,0]],[[5984,6997],[-1,-9],[0,-5],[0,-1],[1,-5],[-2,-9],[-1,-7],[-1,-3],[-2,-7],[-2,-9],[0,-6],[0,-2],[-1,-11],[1,-3],[-2,-10],[-1,-4],[-1,-7],[-1,-13]],[[5971,6886],[-2,-4]],[[5951,6981],[3,5],[0,4],[4,10],[0,1],[-1,2]],[[5957,7003],[6,18],[3,17],[3,24],[3,13],[2,8],[1,6]],[[5975,7089],[3,1],[2,-1],[3,0],[2,2],[1,8],[2,1],[0,-2],[1,2],[3,4],[2,2],[1,2],[1,1]],[[5996,7109],[-1,-3],[0,-2],[0,-3],[0,-2],[1,-3],[1,-4],[-1,-2],[0,-3],[0,-3],[1,-2],[-2,-5],[-1,-5],[-1,-3]],[[5334,7301],[-1,-1],[-2,2],[0,3],[0,1],[2,-1],[1,-3],[0,-1]],[[5432,7385],[-2,-6],[-1,-3],[-6,-16],[-1,-4],[-1,-4],[0,-3],[-1,-3],[-1,-5],[0,-4],[0,-3],[1,-1],[2,-2],[1,-2],[-2,-2],[2,-4],[1,-2],[0,-3],[0,-2],[-3,-5],[-1,-2],[-1,-3],[0,-3],[0,-3],[0,-3],[-3,0],[-3,2],[-3,-1],[-5,3],[-1,1],[-2,1],[-3,10],[-3,5],[-4,3],[-3,0],[-3,0],[-3,2],[-6,7],[-6,5],[-3,4],[-1,2],[-2,2],[-3,1],[-4,4],[-1,0],[-3,0],[-2,0],[-1,1],[-4,5],[-2,6],[0,2],[1,7],[2,7],[2,1],[1,2],[1,2],[1,2],[3,-7],[2,-1],[1,0],[3,2],[0,3],[3,4],[4,0],[1,-1],[1,-3],[2,-1],[1,-1],[6,-5],[1,-1],[1,-1],[5,3],[3,1],[6,-1],[4,1],[2,0],[4,2],[3,4],[1,1],[2,0],[4,0],[3,-1],[2,1],[1,3],[2,1],[2,-1],[4,4],[2,1],[2,-2],[-2,-3]],[[5235,7434],[-2,-6],[-1,4],[0,4],[0,1],[2,-2],[1,-1]],[[5387,7528],[-2,0],[0,1],[-1,0],[1,3],[2,-2],[0,-1],[0,-1]],[[5230,7548],[-1,-3],[-2,0],[1,2],[1,4],[2,1],[0,-1],[0,-2],[-1,-1]],[[5267,7539],[1,-4],[4,-15],[0,-3],[-1,-4],[-1,-2],[-3,-8],[1,-6],[1,-4],[0,-4],[0,-6],[-2,-32],[-1,-6],[-1,-5],[-2,-2],[-3,2],[-3,3],[-2,-1],[-1,-1],[-2,1],[-1,2],[-1,-11],[-1,-5],[-3,-3],[-2,0],[-2,1],[-2,0],[-2,2],[-1,4],[-2,5],[-2,5],[0,5],[0,11],[0,2],[1,3],[1,4],[-1,5],[1,1],[1,-1],[1,0],[0,2],[0,4],[-2,4],[-2,1],[0,3],[0,4],[1,2],[1,3],[0,10],[-2,3],[-1,5],[0,4],[-2,3],[-2,3],[-1,2],[0,7],[0,6],[1,2],[1,0],[1,-3],[2,-1],[3,0],[3,1],[3,2],[4,3],[4,10],[3,2],[2,2],[1,3],[1,1],[1,-3],[2,0],[3,-3],[1,-3],[1,-3],[1,-1],[2,-1],[-1,-1],[-1,-4],[0,-1],[2,-1]],[[5288,7652],[1,-2],[0,-1],[0,-2],[0,-3],[-2,3],[-4,-2],[-2,1],[-1,2],[1,2],[3,0],[1,1],[2,-1],[1,2]],[[5380,7863],[-1,-3],[-1,-1],[-2,-2],[-2,-2],[-2,-3],[-1,-4],[1,-2],[1,0],[1,0],[2,-1],[2,-1],[0,-2],[0,-1],[-2,-3],[-2,-2],[0,-2],[0,-1],[1,-1],[2,0],[1,-1],[-2,-7],[1,-1],[2,-2],[2,-1],[3,-5],[1,-4],[-1,-1],[-2,-1],[-1,1]],[[5381,7810],[1,2],[-4,8],[-2,0],[-3,-3],[-7,3],[-1,-1],[-1,-3],[-3,-4],[-3,-1],[-4,-4],[-4,-3],[-3,-2],[-2,1],[3,4],[-2,0],[-3,-3],[-3,-3],[0,-4],[-1,-7],[2,-2],[3,-10],[3,-4],[0,-4],[-1,-3],[-3,-3],[-1,2],[-1,0],[-1,-6],[1,-17],[3,-12],[2,-5],[6,-8],[6,-4],[11,-14],[6,-4],[1,-3],[4,-10],[3,-12],[3,-19],[3,-9],[4,-11],[10,-15],[9,-11],[9,-7],[6,-1],[16,1],[3,0],[2,-2],[1,-5],[-1,-3],[-3,-3],[-3,-5],[-1,-6],[3,-5],[15,-11],[16,-10],[4,-5],[6,-8],[13,-11],[2,-5],[9,-11],[3,-9],[1,-6],[-2,-7],[-1,-5],[-1,-5],[-3,2],[-4,5],[-6,20],[-11,2],[-2,1],[-4,4],[0,2],[-1,3],[-1,1],[-4,0],[-3,-3],[-4,-7],[-3,-11],[-4,-16],[-1,-7],[3,-6],[6,-4],[5,-5],[3,-6],[0,-14],[2,-8],[-3,-5],[-4,2],[-5,-3],[-4,-5],[-2,-5],[1,-13],[-1,-5],[-7,-9],[-4,-9],[-1,-4],[-2,-5],[-9,0],[-2,6],[0,8],[2,5],[3,2],[2,10],[0,8],[1,3],[1,3],[3,1],[3,1],[1,11],[-3,5],[-1,6],[-1,13],[-5,15],[-3,14],[-2,7],[-3,4],[-5,0],[-3,1],[-9,10],[-1,1],[0,3],[2,3],[-1,6],[-1,5],[-2,4],[-2,2],[-5,-1],[-1,-1],[-3,0],[-2,-2],[-1,0],[3,8],[-1,1],[-3,4],[-5,0],[-1,0],[-1,-2],[0,2],[0,3],[-6,15],[-3,6],[-2,1],[-3,-1],[-5,2],[-4,1],[-1,-1],[-3,-2],[-1,2],[-1,2],[-5,6],[-6,3],[-11,20],[-4,8],[-8,8],[-4,11],[-4,5],[-6,3],[-1,0],[-2,-1],[-1,-1],[-1,2],[1,2],[1,0],[0,5],[-7,11],[-3,4],[-1,3],[-1,3],[-1,2],[-2,1],[-1,0],[-2,1],[0,5],[0,5],[0,3],[-2,10],[-4,8],[-2,20],[-2,5],[-3,4],[-9,5],[-12,13],[-3,0],[-7,5],[-5,0],[-6,-4],[-7,-12],[-6,-13],[-2,-2],[-8,-4],[-6,-2]],[[5344,7714],[1,-2],[1,0],[1,3],[0,3],[-2,-1],[-1,-3]],[[2854,6247],[3,-2],[3,-1],[2,0],[1,-1],[4,-5],[2,-3],[10,-6],[3,-10],[1,-3],[-3,-2],[-3,-1],[-3,0],[-3,2],[-1,1],[-3,1],[1,2],[-1,0],[-2,0],[-1,-4],[-2,-3],[-2,0],[-1,3],[-1,-1],[-2,-2],[-1,-8],[-2,4],[-2,3],[-3,1],[-6,0],[-3,2],[-2,6],[-1,2],[-2,1],[-2,8],[-1,1],[-6,1],[-1,4],[0,4],[2,4],[1,1],[3,0],[4,2],[1,1],[2,2],[11,-4],[3,0],[3,0]],[[4943,8019],[1,-2],[-2,-1],[-1,1],[-2,0],[-2,-1],[1,5],[4,0],[1,-2]],[[6087,7034],[-4,-7],[-1,0],[-6,-3],[-11,-6],[-7,-4],[-9,-5],[-8,-4],[-8,-4],[-7,-3],[4,-8],[6,-12],[4,-8],[5,-11],[5,-9],[4,-9],[-3,-4],[-5,-5],[-1,-1],[0,-1],[-2,-10],[-2,-8],[-1,-1],[-7,-2],[-8,-3],[-5,-2],[-1,-2],[-3,-9],[-3,-10],[-6,-8],[-6,-9],[-1,-1],[-4,1],[-8,3],[-7,2],[-5,2],[-6,2]],[[5970,6875],[1,7],[0,4]],[[5984,6997],[1,5],[1,6],[1,5],[-1,13],[0,7],[2,8],[-1,9]],[[5993,7069],[3,-1],[2,-3],[3,-7],[5,-3],[1,-2],[3,-4],[3,-1],[9,-3],[8,9],[6,7],[7,8],[5,6],[9,9],[5,6],[7,8],[7,8]],[[8441,6582],[-2,-1],[-2,1],[-2,1],[0,1],[2,2],[0,3],[0,1],[5,-3],[0,-2],[-1,-3]],[[8452,6596],[-2,-9],[-1,-2],[-2,1],[-1,5],[1,2],[1,-1],[1,1],[3,7],[1,-1],[-1,-3]],[[8484,6609],[-3,-2],[-2,1],[0,8],[1,-1],[1,-2],[2,-2],[1,-2]],[[8949,6717],[-1,0],[-1,6],[1,-1],[1,-3],[0,-2]],[[8562,6719],[-3,-3],[-1,-3],[-2,-1],[-3,-4],[-2,-1],[0,-4],[1,-3],[-1,0],[-2,-4],[0,-3],[0,-2],[0,-1],[-2,-3],[-2,0],[0,3],[0,3],[2,6],[0,7],[2,1],[1,1],[3,5],[0,3],[-1,2],[0,2],[0,1],[3,-1],[1,-1],[0,-1],[1,2],[1,2],[3,5],[1,5],[2,-4],[-1,-5],[-1,-4]],[[8582,6780],[-1,-1],[-1,2],[-1,6],[1,4],[1,0],[1,-5],[1,-3],[-1,-3]],[[8591,6803],[1,-2],[-3,1],[-1,6],[2,-1],[0,-2],[1,-2]],[[8595,6809],[-2,-5],[-3,4],[-3,3],[2,1],[0,1],[0,2],[2,2],[4,2],[2,0],[1,2],[1,2],[0,1],[3,2],[0,-2],[0,-3],[-2,-1],[-2,-3],[-1,-3],[-2,-2],[0,-1],[0,-2]],[[8628,6927],[-4,-1],[-1,1],[-2,7],[3,5],[4,-5],[1,-1],[-1,-6]],[[8637,6935],[-3,-1],[0,3],[2,8],[1,5],[1,7],[1,2],[1,0],[0,-2],[0,-8],[-2,-7],[-1,-7]],[[8602,7007],[0,-1],[0,5],[2,4],[1,-3],[-3,-5]],[[8621,7051],[-3,0],[-1,1],[0,2],[3,3],[3,0],[-1,-4],[-1,-2]],[[8613,7040],[-3,-2],[0,2],[-1,1],[2,3],[0,1],[-1,2],[1,7],[0,3],[4,1],[1,-3],[0,-8],[-3,-7]],[[8573,7072],[1,-1],[2,0],[1,1],[1,-1],[1,-4],[1,-2],[-2,-1],[-1,0],[-1,-3],[-2,1],[-1,1],[0,2],[0,7]],[[8884,7088],[-1,-1],[-1,2],[0,2],[0,1],[1,0],[1,-2],[0,-2]],[[8585,7075],[-1,0],[-1,5],[-1,2],[1,1],[3,9],[0,-4],[1,-3],[1,-1],[-1,-3],[-1,-1],[-1,-5]],[[8596,7097],[-2,-2],[-1,0],[1,3],[0,1],[1,5],[2,1],[1,0],[-1,-4],[-1,-4]],[[8605,7128],[-2,-3],[-2,2],[1,5],[0,2],[2,-2],[1,-4]],[[8643,7119],[4,-1],[1,-1],[2,1],[2,2],[2,2],[2,-1],[1,-2],[1,-3],[0,-3],[-3,-6],[-2,-7],[5,-1],[5,0],[-1,-4],[0,-4],[1,-1],[1,-3],[0,-2],[-1,-2],[3,-3],[0,-2],[-1,-2],[-7,-15],[-2,-7],[-1,-8],[-1,-6],[-1,-6],[-1,-7],[-1,-7],[0,-6],[0,-6],[-4,-15],[-2,0],[-3,2],[-2,0],[-1,-4],[2,-7],[-6,-8],[-6,-6],[0,3],[1,2],[1,1],[0,2],[1,7],[0,6],[-2,9],[0,3],[1,1],[1,0],[0,1],[0,3],[0,2],[-2,1],[-2,0],[-1,-3],[-1,-6],[-1,-6],[0,-3],[1,-3],[2,-5],[0,-3],[-1,-2],[-8,5],[-2,0],[-1,1],[-2,7],[3,1],[1,1],[1,2],[0,7],[-1,5],[-2,2],[-1,3],[1,4],[0,6],[0,8],[0,2],[3,1],[2,5],[2,5],[3,8],[2,10],[-2,0],[-2,2],[2,4],[-1,6],[-3,7],[-1,8],[-3,3],[-1,2],[-2,-2],[-1,-2],[1,-6],[0,-4],[0,-5],[1,0],[2,1],[1,-1],[1,-2],[0,-4],[0,-3],[-1,-1],[-2,0],[-1,2],[-2,2],[-2,1],[-3,-2],[-3,-6],[-2,-3],[1,4],[0,5],[-1,3],[-2,5],[-1,3],[0,4],[0,4],[3,-4],[1,-6],[2,-2],[3,0],[-2,8],[-1,2],[-2,3],[-4,6],[-2,3],[0,6],[2,2],[1,-1],[4,-2],[0,3],[0,2],[-1,2],[3,2],[4,3],[1,1],[1,2],[1,1],[3,0],[2,2],[2,6],[1,3],[1,3],[5,4],[1,1],[4,-1],[3,-2],[1,-6],[2,-6],[3,-4]],[[8673,7139],[2,-2],[3,1],[0,-1],[-1,-2],[-1,-2],[-3,2],[-1,0],[-1,3],[1,1],[1,0]],[[8682,7149],[-1,-3],[-2,1],[1,2],[0,3],[1,0],[0,-3],[1,0]],[[8590,7149],[-2,-2],[0,3],[0,11],[4,-2],[0,-4],[-2,-6]],[[8731,7157],[4,-2],[4,0],[0,-10],[1,-4],[1,-3],[-1,-5],[2,-1],[-5,-5],[-5,-7],[-2,-5],[-2,-5],[-1,-5],[-1,-6],[-1,2],[-5,9],[-3,3],[-4,1],[-2,0],[-9,-9],[-2,-6],[-2,-10],[-2,-3],[-1,-1],[-1,-1],[-1,-9],[-3,-5],[-2,0],[-3,2],[-1,-1],[1,8],[-2,1],[-3,0],[-1,5],[-1,3],[1,4],[0,3],[1,2],[0,2],[0,2],[-2,1],[-1,2],[0,5],[-1,1],[-2,-1],[-6,-5],[-1,0],[2,3],[5,5],[2,2],[5,7],[3,3],[1,6],[1,4],[1,3],[1,5],[1,1],[3,5],[1,-1],[2,-5],[2,-4],[2,0],[3,2],[1,1],[4,0],[3,2],[1,3],[0,4],[-1,6],[2,0],[1,0],[4,4],[3,2],[3,1],[4,-2],[4,-4]],[[8731,7170],[0,-1],[-1,0],[-2,-2],[0,2],[-1,2],[-1,1],[4,1],[2,-1],[-1,-2]],[[8747,7159],[-3,-5],[-2,0],[-2,2],[0,3],[2,4],[3,6],[1,3],[2,2],[1,-1],[-2,-8],[0,-6]],[[8593,7163],[0,-3],[-2,2],[-1,1],[2,9],[-1,4],[1,1],[3,5],[1,-1],[0,-1],[0,-2],[0,-5],[-3,-7],[0,-3]],[[8873,7184],[0,-3],[-2,1],[-1,2],[1,3],[1,0],[1,-3]],[[8704,7269],[-1,-2],[-3,1],[-1,3],[0,3],[3,3],[2,-5],[0,-3]],[[8842,7362],[-3,0],[0,1],[1,1],[0,3],[1,4],[0,1],[-2,0],[0,5],[2,5],[4,7],[1,2],[1,-4],[-2,-7],[0,-3],[3,-1],[-2,-9],[-4,-5]],[[8922,7567],[1,-1],[5,3],[-1,-9],[0,-9],[0,-15],[1,-7],[1,-6],[2,-5],[3,-3],[4,-10],[2,-13],[2,-7],[1,-6],[0,-3],[0,-3],[0,-4],[0,-4],[0,-10],[-2,-12],[0,-6],[-2,-2],[-1,-3],[-1,-1],[-1,-1],[-1,0],[-1,-1],[0,-4],[-1,-3],[-1,-2],[-1,-4],[-1,-7],[0,-8],[-1,-5],[-3,-2],[-3,1],[-4,-3],[-1,-1],[-3,-10],[-1,-5],[0,-6],[1,-8],[1,-7],[1,-13],[-1,-20],[-1,-7],[-2,-4],[-2,-2],[-1,-3],[-2,-7],[-3,-13],[0,-3],[0,-3],[-1,-5],[0,-4],[0,-5],[1,-5],[4,-13],[2,-3],[1,-3],[-6,-4],[-1,-2],[-4,-7],[-2,-7],[1,-7],[-1,-3],[-1,-2],[-1,-1],[-5,-4],[-2,-3],[-3,-5],[-1,-3],[-2,1],[-2,2],[2,3],[-1,4],[1,9],[-1,4],[2,3],[1,4],[3,4],[1,3],[1,2],[-2,3],[-1,2],[-3,0],[-2,0],[-1,-3],[0,-4],[0,-1],[0,-2],[-4,-5],[1,-5],[1,-2],[1,-2],[0,-1],[-2,-5],[-1,0],[-2,6],[-3,3],[-3,0],[-3,-1],[-2,-4],[-1,-3],[-1,-4],[1,-8],[-1,-7],[-2,-5],[-1,-3],[-3,-4],[-1,0],[-1,2],[-1,2],[1,11],[0,5],[3,3],[-3,4],[-3,2],[-4,-2],[-1,-3],[0,-3],[-3,-4],[-2,-4],[-3,-7],[-1,-8],[-6,3],[-3,1],[-4,-1],[-5,1],[-6,-1],[-8,-3],[1,2],[6,5],[0,1],[-1,3],[-1,0],[-4,-1],[-1,0],[-1,3],[-1,1],[-1,-1],[0,-5],[-1,-1],[-1,1],[0,5],[0,6],[0,4],[1,3],[-1,1],[-2,0],[-1,-2],[-2,-2],[-3,-11],[-1,-7],[2,-5],[6,-7],[1,-2],[0,-3],[0,-3],[-2,-2],[-7,-2],[-6,-5],[-2,-4],[-5,-19],[-4,-12],[-7,-4],[-6,3],[-2,5],[-1,5],[-3,5],[-2,5],[-1,7],[0,10],[-1,6],[1,1],[4,4],[1,2],[2,5],[1,3],[0,4],[-2,2],[-4,0],[-5,-2],[-3,2],[-4,5],[-1,1],[-4,1],[-4,-1],[-3,-2],[-3,-1],[-1,-1],[-4,-6],[-3,-3],[-2,-2],[-6,-1],[-2,-1],[-3,-2],[-1,0],[-3,-3],[-4,-2],[-1,-2],[-4,1],[-7,-4],[-3,-1],[-3,3],[-3,3],[-4,-1],[-2,-6],[-1,-11],[-1,-5],[0,-6],[-2,1],[-9,11],[-8,-2],[-2,-1],[-2,-2],[-3,-1],[-2,2],[-2,2],[-2,0],[-2,-2],[-1,16],[0,2],[2,3],[1,3],[4,1],[3,-1],[3,1],[2,3],[2,5],[3,4],[3,3],[4,3],[3,5],[3,5],[2,4],[3,3],[4,8],[6,8],[2,7],[2,2],[4,3],[7,3],[3,0],[3,-6],[2,1],[1,1],[4,1],[3,-1],[3,0],[4,1],[6,2],[4,2],[3,3],[12,2],[8,5],[1,-1],[2,-1],[0,-3],[-1,-4],[1,-3],[1,-1],[8,0],[2,-1],[3,2],[3,4],[3,4],[3,5],[-2,6],[-1,7],[2,7],[2,6],[3,4],[3,4],[5,12],[4,10],[2,12],[-1,14],[3,11],[4,2],[6,5],[4,1],[0,-2],[0,-3],[-5,-9],[-3,-3],[-2,-2],[-1,-1],[-1,-3],[3,-6],[0,-3],[0,-4],[0,-3],[3,-4],[4,-1],[1,0],[1,1],[4,9],[1,1],[11,7],[5,5],[4,1],[2,3],[7,10],[2,4],[2,5],[2,6],[1,7],[2,4],[10,9],[3,5],[1,3],[2,7],[0,8],[2,5],[1,6],[3,6],[2,5],[2,5],[2,13],[1,7],[0,3],[1,2],[1,3],[1,3],[0,3],[1,9],[0,7],[-2,6],[-2,2],[-1,0],[-2,0],[-2,2],[0,2],[2,1],[1,1],[1,2],[2,7],[1,7],[0,3],[-1,6],[-1,6],[0,4],[1,4],[2,4],[1,1],[2,0],[2,1],[1,2],[1,2],[1,6],[1,4],[-1,9],[1,2],[1,2],[1,-2],[2,0],[2,1],[1,-1],[1,-3],[1,-15],[1,-2],[1,-1],[1,0],[1,2],[1,3],[2,1],[5,-3],[2,2],[1,4],[1,6],[0,6],[-2,2],[-1,0],[-1,-2],[-1,-1],[-8,-3],[0,7],[2,10],[1,3],[1,1],[3,-1],[2,-1],[3,-5]],[[8874,7608],[-1,-1],[-1,1],[0,4],[0,2],[2,2],[2,0],[-2,-8]],[[8924,7783],[-2,-1],[-2,3],[0,3],[1,2],[2,-1],[1,-3],[1,-2],[-1,-1]],[[8918,7795],[-1,-4],[-2,6],[0,6],[1,0],[1,-1],[1,-3],[0,-4]],[[8994,7725],[4,0],[1,0],[3,-1],[10,-9],[4,-1],[3,0],[2,1],[2,2],[7,11],[6,9],[1,0],[0,-3],[0,-3],[-3,-8],[-4,-12],[0,-6],[1,-6],[2,-5],[1,-7],[2,-9],[3,-1],[1,0],[3,2],[3,4],[2,0],[2,0],[-3,-3],[-3,-3],[-2,-5],[-1,-1],[-3,0],[-1,0],[-4,-3],[-3,-2],[-2,-4],[-3,-1],[-3,-1],[-5,-3],[-4,0],[-6,3],[-2,-1],[-7,-5],[-6,-8],[-5,-9],[-4,-10],[-1,-5],[-1,-6],[-1,-4],[0,-4],[-1,-3],[-1,-2],[-4,1],[-5,6],[-11,8],[-12,12],[-7,6],[-12,-2],[-12,-11],[-1,1],[-4,8],[-2,3],[-3,1],[-2,0],[-2,-1],[-2,-4],[-1,-3],[-1,-3],[0,-3],[0,-2],[3,-6],[3,-3],[1,-1],[3,0],[1,0],[5,-8],[6,-8],[1,-2],[-2,-3],[-2,-1],[-3,0],[-2,1],[-5,3],[-2,-2],[-2,-6],[-2,-6],[-1,-3],[-3,-3],[-4,-2],[-2,0],[-1,3],[-1,2],[0,4],[1,6],[1,7],[1,6],[-1,9],[-1,2],[-4,5],[-2,5],[0,6],[0,4],[1,7],[1,4],[2,2],[1,0],[3,3],[3,4],[3,4],[3,5],[2,5],[-3,7],[0,4],[0,4],[3,2],[2,-2],[6,-5],[1,-1],[3,0],[6,-1],[3,0],[1,1],[2,5],[1,6],[0,7],[0,8],[1,6],[4,9],[2,6],[0,14],[2,7],[1,6],[1,13],[-2,13],[-2,7],[-2,6],[0,5],[2,6],[0,1],[0,2],[3,1],[2,1],[1,3],[2,1],[1,-1],[1,-3],[4,-7],[7,-11],[8,-18],[5,-8],[5,-8],[6,-8],[7,-7],[4,-3],[2,-5],[2,-1]],[[7140,7206],[-2,5],[0,3],[-2,6],[-1,5],[-2,8],[-1,5]],[[6393,7767],[-1,-1],[-1,0],[-3,6],[1,6],[1,2],[1,0],[0,-1],[-1,-3],[-1,-3],[2,-4],[2,-2]],[[6397,7774],[-1,-1],[-1,4],[1,3],[2,1],[-1,-5],[0,-2]],[[6463,7799],[-1,0],[-2,1],[-1,3],[2,3],[1,0],[1,-4],[0,-3]],[[7227,7614],[-4,6],[-4,7],[-3,1],[-6,1],[-3,0],[-1,2],[-2,3],[-2,4],[-3,3],[-1,6],[-1,1],[-2,-1],[-3,0],[-1,1],[-3,0],[-4,3],[-3,2],[-5,0],[-2,0],[-7,-1],[-7,2],[-5,1],[-3,0],[-1,0],[-3,0],[-3,1],[-5,3],[-2,0],[-1,0],[-9,-3],[-3,0],[-9,0],[-7,0],[-3,1],[-1,0],[-3,-6],[-2,-1],[-7,1],[-9,4],[-6,4],[-6,5],[-7,7],[-4,3],[-1,-2],[-1,0],[-2,-1],[-4,1],[-1,-4],[-5,-2],[-3,-3],[-1,-2],[-3,-18],[-1,-6],[2,-11],[-2,1],[-3,3],[-1,2],[-3,1],[-9,2],[-2,3],[-1,2],[-2,1],[-4,1],[-7,5],[-3,0],[-10,3],[-1,0],[-1,0],[-4,-2],[-2,-1],[-3,1],[-4,-3],[-3,-4],[-2,-4],[-2,-3],[0,-5],[-2,-2],[-1,-4],[0,-3],[1,-3]],[[6970,7617],[-2,-2],[-3,-1],[-1,-1],[-2,-4],[-1,-3],[-1,-1],[-1,0],[-2,3],[-2,-1],[-2,-2],[-3,-5],[-4,-7],[-3,-4],[-5,-4],[-4,-1],[-2,-2],[-5,-5],[-1,-3],[-3,-2],[-3,-2],[-2,-4],[-1,-5],[-1,-4],[-4,-5],[-3,-4],[-2,-5],[-3,-5],[0,-2],[0,-4],[1,-3],[0,-3],[-1,-2],[-2,-1],[-2,0],[-4,3],[-3,3],[-2,2],[-1,3],[0,3],[1,6],[0,4],[-1,2],[-1,2],[-1,2],[-2,4],[-2,-1],[-1,-1],[-2,1],[-6,0],[-4,-1],[-4,0],[-5,-1],[-7,0],[-2,0],[-1,2],[-1,5],[0,4],[-2,9],[0,6],[-1,8],[-1,9],[0,6],[-5,0],[-4,0],[-5,0],[0,5],[0,6],[0,7],[1,9],[0,8],[1,9],[0,6],[0,7],[-2,-2],[-3,-2],[-3,-3],[-2,6],[-2,5],[-2,8],[-2,6],[-4,4],[-3,3],[-2,4],[-3,5],[-2,4],[-3,4],[-2,-1],[-3,-3],[-3,-2],[-3,-3],[-2,-1],[-3,1],[-3,0],[-6,1],[-4,0],[-5,1],[-6,1],[-7,1],[-4,-1],[-6,-2],[-6,-1],[-5,-2],[-6,-1],[-4,-1],[-3,0],[-3,5],[-4,8],[-3,4],[-3,5],[-4,7],[-3,5],[-3,5],[-2,4],[0,6],[-2,3],[-4,3],[-3,4],[-4,4],[-4,4],[-4,3],[-4,4],[-4,4],[-3,4],[-4,4],[-4,3],[-4,4],[-4,4],[-4,4],[-3,4],[-4,3],[-4,4],[-4,4],[-3,3],[-3,-1],[-4,-2],[-5,-2],[-5,-2],[-8,-4],[-5,-2],[-4,-2],[-5,-2],[-5,-3],[-5,-2],[-6,-3],[-5,-2],[-4,-2],[-4,-2],[-4,-2],[0,-13],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13],[0,-13],[0,-13],[0,-14],[0,-13],[0,-13]],[[6554,7564],[-1,0],[-3,-1],[-4,-2],[-4,-1],[-1,1],[-2,1],[-1,3],[-2,4],[-2,3],[-2,6],[-2,4],[-4,10],[-1,3],[-1,3],[-1,3],[-5,6],[-6,6],[-5,6],[-2,1],[-2,2],[-4,0],[-2,0],[-6,-2],[-6,-2],[-6,-3],[-6,-4],[-1,-1],[-4,-4],[-5,-6],[-5,-10]],[[6458,7590],[-1,6],[0,10],[0,3],[1,8],[2,5],[1,6],[1,7],[-2,12],[-1,2],[-1,1],[-2,0],[-3,0],[-2,-1],[-2,4],[-3,1],[-2,-2],[-1,0],[-2,1],[-2,2],[0,3],[-1,3],[-3,6],[-2,3],[-3,0],[-4,0],[-2,1],[0,3],[1,7],[0,4],[-1,3],[0,3],[-1,3],[-3,4],[-2,6],[-4,12],[-3,13],[-1,2],[-3,2],[-6,2],[-4,2],[-1,2],[-1,3],[0,3],[1,3],[1,4],[3,2],[6,1],[6,-1],[5,-5],[2,-2],[2,0],[4,2],[1,0],[5,0],[-1,2],[-2,2],[-2,0],[-1,1],[-3,5],[-4,6],[-1,2],[-1,4],[1,4],[3,3],[3,5],[1,6],[1,3],[3,4],[3,-1],[5,4],[9,-1],[11,1],[3,0],[6,-3],[4,-2],[5,-1],[3,2],[-3,4],[-7,5],[-2,5],[3,12],[5,10],[2,13],[0,13],[-2,4],[1,4],[1,3],[1,4],[-1,4],[-1,7],[-1,2],[-4,3],[-6,0],[-6,2],[-2,-1],[-1,-3],[-1,-1],[-4,-3],[-1,-1],[-2,1],[-2,3],[-2,0],[-5,2],[-3,5],[-1,1],[-9,4],[-3,0],[-7,-4],[-5,-5],[-2,-1],[-3,-3],[-1,0],[-2,0],[-1,0],[-3,-5],[-6,-6],[-3,-3],[-3,-2],[-3,-2],[-4,0],[-1,-1],[-4,-1],[-3,-1],[0,-2],[1,-4],[-3,1],[-2,-2],[1,-3]],[[6367,7853],[-1,0],[-7,6],[-5,4],[-4,3],[-1,1],[-1,1],[-1,3],[0,3],[0,2],[1,1],[2,0],[1,0],[1,-1],[2,-2],[3,0],[2,1],[0,3],[-3,10],[-3,9],[-4,9],[-1,3],[-4,8],[-4,8],[-3,7],[-1,2],[-5,1],[-9,1],[-4,1],[-2,-2],[-3,-1],[-2,3],[-2,4],[-1,5],[0,4],[0,6],[-1,6],[-2,3],[-4,2],[-5,5],[-2,10],[3,13],[4,9],[3,4],[1,4],[1,3],[-1,3],[-1,3],[-3,3],[-2,3],[1,8],[2,11],[3,9],[4,5],[3,4],[1,3],[0,5],[0,4],[1,3],[1,3],[2,2],[2,3],[3,1],[3,-3],[4,-5],[5,-11],[4,-7],[1,-2],[3,-4],[3,-2],[4,3],[5,3],[1,2],[1,2],[-1,5],[0,4],[-1,4],[-2,7],[-1,11],[-1,4],[1,0],[2,0],[2,-1],[3,3],[4,5],[7,7],[2,5],[1,5],[2,3],[5,1],[4,2],[3,4],[5,3],[4,2],[2,2],[1,3],[5,7],[3,5],[3,5],[1,3],[3,0],[4,-2],[4,-2],[3,-3],[0,-4],[0,-2],[2,-1],[1,-1],[2,1],[4,0],[5,4],[6,7],[6,2],[3,-1],[3,-5],[2,-5],[2,-2],[1,0],[3,1],[3,0],[2,-2],[4,0],[5,1],[0,1],[3,-1],[3,-2],[2,-3],[5,-8],[2,-2],[5,-3],[3,-3],[2,-4],[2,-3],[3,-5],[3,-7],[1,-6],[0,-6],[2,-2],[1,0],[1,0],[1,3],[0,4],[0,7],[-1,5],[-1,2],[0,2],[0,3],[2,1],[3,-1],[3,-3],[5,-4],[5,-7],[4,-5],[5,-4],[4,-1],[3,1],[4,3],[3,4],[2,3],[1,4],[5,6],[5,4],[2,0],[1,-2],[5,3],[2,1],[4,1],[5,-2],[3,-5],[4,-3],[3,0],[3,2],[2,3],[1,4],[2,2],[0,1],[6,-2],[3,0],[1,1],[4,-1],[6,-5],[3,-6],[4,-8],[2,-2],[3,-1],[2,-1],[3,-1],[8,-2],[1,0],[1,-2],[-1,-4],[1,-1],[6,3],[2,2],[2,6],[2,7],[1,2],[2,1],[1,-1],[2,-4],[3,-4],[4,-1],[2,-1],[4,0],[8,2],[8,4],[5,5],[2,8],[1,8],[2,6],[-1,5],[-4,5],[-1,2],[-10,3],[0,2],[-1,0],[-9,5],[-5,2],[-1,3],[-1,4],[-3,3],[-6,4],[-1,2],[1,3],[4,2],[6,6],[2,1],[5,1],[4,4],[3,3],[2,3],[-1,4],[-4,10],[-1,6],[0,4],[3,4],[1,2],[2,5],[1,2],[5,1],[5,0],[4,-1],[5,0],[4,-1],[3,-1],[2,2],[1,2],[0,3],[-2,3],[-7,4],[-3,3],[-2,-1],[-4,1],[-4,2],[-3,1],[-1,3],[1,4],[1,2],[2,1],[3,0],[3,1],[0,1],[1,2],[-1,1],[-1,2],[-2,0],[-2,-1],[-2,-1],[-4,2],[-4,2],[0,2],[3,3],[1,3],[0,3],[0,4],[1,5],[2,3],[3,2],[7,-3],[10,-3],[1,0],[1,2],[1,1],[12,1],[3,2],[1,1],[12,2],[2,2],[2,2],[2,0],[4,1],[4,2],[4,1],[4,0],[4,1],[1,1],[1,2],[4,2],[7,2],[2,-1],[3,-1],[5,1],[3,2],[2,-2],[2,-1],[2,1],[1,5],[1,4],[3,2],[1,1],[2,1],[1,2],[7,0],[5,4],[1,-2],[8,1],[9,2],[6,2],[9,3],[5,2],[6,1],[6,1],[3,4],[4,1],[3,0],[3,1],[1,2],[1,3],[-1,3],[0,3],[3,1],[3,1],[3,1],[5,5],[4,3],[3,2],[8,-1],[7,-1],[7,-3],[3,-3],[3,-3],[3,-1],[3,-1],[3,1],[2,2],[1,2],[2,2],[7,1],[2,-2],[3,-8],[2,-10],[4,-14],[2,-6],[-1,-4],[0,-5],[0,-5],[-3,-6],[1,-3],[7,-3],[9,1],[6,3],[3,-1],[2,1],[1,5],[2,1],[3,-3],[1,-5],[2,-4],[0,-4],[1,-5],[1,-1],[2,2],[2,1],[0,1],[-1,2],[0,2],[0,2],[2,1],[3,-1],[5,-1],[5,-7],[3,-1],[2,0],[3,0],[3,2],[2,3],[1,1],[2,0],[1,-1],[0,-3],[-1,-4],[-4,-3],[-4,-4],[-2,-6],[-1,-6],[1,-3],[1,-2],[0,-3],[1,-1],[2,2],[5,6],[2,1],[4,1],[6,0],[4,-2],[2,-3],[2,-2],[1,1],[1,2],[0,3],[0,3],[7,6],[4,4],[1,1],[3,-1],[2,0],[5,4],[4,4],[1,3],[0,3],[1,1],[6,1],[1,1],[5,3],[7,5],[4,3],[6,1],[1,1],[3,2],[3,3],[3,1],[-2,-7],[-2,-8],[-1,-3],[-7,1],[0,-2],[1,-4],[1,-2],[1,-1],[1,-3],[7,-7],[9,-9],[9,-10],[7,-7],[2,-3],[2,-3],[5,-10],[4,-10],[8,-16],[7,-17],[8,-17],[4,-11],[9,-21],[2,-7],[5,-12],[4,-12],[3,-11],[2,-1],[1,3],[0,2],[1,1],[3,3],[1,1],[2,0],[2,1],[1,3],[0,6],[-1,2],[1,3],[1,1],[2,1],[1,0],[2,3],[2,1],[2,0],[2,0],[1,-3],[1,-3],[2,0],[3,0],[0,-2],[-1,-5],[-1,-3],[0,-2],[2,-2],[5,1],[2,0],[1,-3],[0,-2],[1,-3],[-1,-3],[1,-2],[5,0],[3,2],[5,0],[5,-3],[3,0],[3,1],[5,0],[3,2],[2,3],[1,3],[1,1],[5,0],[2,0],[2,4],[2,2],[3,0],[3,0],[6,-3],[4,-3],[4,-4],[2,-3],[2,-5],[2,-4],[2,-5],[1,-5],[2,-9],[2,-3],[2,0],[2,-1],[3,-1],[7,-6],[2,0],[2,-2],[0,-3],[0,-3],[0,-3],[3,-5],[1,-4],[2,-5],[1,-2],[1,-1],[3,1],[3,-1],[11,-3],[1,0],[1,-3],[2,0],[2,0],[2,0],[2,3],[1,2],[4,3],[3,4],[2,3],[2,1],[1,-2],[0,-3],[-1,-2],[-2,-3],[1,-2],[2,-1],[3,-4],[4,-9],[1,-2],[2,-2],[2,-1],[2,-1],[2,-4],[1,-4]],[[6138,5059],[-1,0],[1,3],[3,4],[1,0],[0,-1],[0,-1],[0,-1],[-4,-4]],[[6163,5413],[-4,-10],[-4,-12],[-7,-23],[-6,-12],[-4,-8],[-1,-2],[0,-10],[0,-24],[0,-49],[1,-48],[0,-49],[0,-24],[0,-8],[3,-11],[4,-9],[5,-14],[3,-7],[0,-2],[0,-5]],[[6153,5086],[-4,-10],[-3,-4],[-5,-2],[-1,0],[-2,1],[-1,-2],[0,-4],[-1,1],[-1,1],[1,-6],[0,-4],[-1,-4],[-2,-4],[0,-3],[-5,-8],[-6,-1],[-4,-5],[-1,-3],[-2,-8],[1,-11],[-2,-9],[0,-4],[-4,-6],[-1,-5],[-1,-6],[-1,-2],[-2,-12],[-1,-8],[-1,-2],[0,-2],[-1,-5],[-1,-2],[-1,-2],[-4,-19],[-3,-9],[-2,1],[-2,-3],[0,-1]],[[6089,4914],[-1,0],[-2,3],[-4,7],[-5,6],[-4,7],[-4,6],[-4,6],[-5,7],[-4,6],[-4,6],[-3,4],[-1,2],[-1,5],[0,1],[-1,1],[-2,1],[0,2],[1,4],[1,5],[0,4],[0,4],[-1,6],[0,1],[-3,4],[-6,7],[-6,6],[-6,7],[-5,7],[-6,7],[-6,7],[-6,7],[-6,6],[-6,7],[-6,7],[-6,7],[-6,7],[-6,7],[-6,7],[-6,6],[-5,7],[-3,3],[-2,2],[-2,0]],[[5941,5126],[0,10],[1,25],[0,22],[0,11],[3,7],[1,5],[1,7],[1,6],[3,4],[1,3],[3,8],[2,10],[2,3],[2,3],[1,2],[2,2],[2,1],[0,2],[0,6],[0,2],[1,5],[2,3],[1,3],[1,2],[0,5],[0,3],[0,5],[0,12],[-2,9],[-1,11],[1,4],[-1,6],[-1,0],[-1,2],[-1,6],[-1,5],[0,1],[-4,5],[-2,12],[-2,2],[-1,11],[0,3],[1,12],[0,2],[-1,2],[-4,3],[-3,4],[1,2],[0,2],[-1,1],[-5,19]],[[5943,5427],[6,11],[5,12],[8,15],[6,13],[6,12],[5,10]],[[7045,7456],[-2,0],[-3,1],[-2,-1],[-2,-2],[-2,-2],[-4,-1],[-4,0],[-2,0],[-7,1],[-2,0],[-2,-1],[-4,-1],[-2,-4],[-1,-3],[0,-1],[-3,3],[-1,3],[-2,2],[-1,0],[-5,-4],[-1,0],[-1,2],[0,4],[0,3],[-2,1],[-3,0],[-1,2],[0,2],[0,2],[0,2],[-1,1],[-2,0],[-2,-2],[-2,-2],[-2,-1],[-2,0],[-2,-1],[-1,-5],[-6,-1],[-2,1],[-1,3],[-2,6],[-1,0],[-2,1],[-3,0],[-4,-3],[-1,2],[-1,1],[-1,-2],[-1,0],[-4,0],[-6,0],[-2,1],[-2,0],[-4,-2],[-2,0],[-3,-1],[0,8],[-2,6],[1,4],[1,5],[1,3],[1,-1],[2,-2],[1,0],[1,2],[-1,2],[0,2],[1,2],[1,2],[6,4],[6,2],[3,-1],[5,-4],[3,-2],[2,-1],[2,-6],[1,0],[1,1],[1,2],[1,5],[2,2],[6,4],[0,1],[0,1]],[[6970,7501],[1,1],[3,1],[6,1],[2,0],[2,-2],[2,-2],[2,0],[1,0],[1,0],[0,-2],[1,-1],[2,2],[2,2],[2,1],[1,1],[1,1],[1,3],[3,6],[2,1],[1,0],[0,-1],[0,-1],[3,-1],[1,1],[1,2],[-1,4],[0,1],[0,1],[0,1],[5,-3],[1,0],[2,2],[2,3],[1,2],[9,8],[1,1],[0,1],[-4,2],[-2,-1],[-2,0],[-1,1],[-4,1],[-1,1],[-4,5],[-2,2],[-2,2],[-2,0],[-2,-2],[0,1],[-1,2],[0,3],[0,3],[-1,1],[-2,-1],[-3,1],[-2,1],[-1,6],[-1,3],[0,3],[-1,1],[-2,1],[0,4],[0,1],[-1,1],[-1,-1],[-1,-2],[1,-4],[-1,-4],[0,-1],[-1,-2],[-2,0],[-2,2],[0,-12],[-1,-1],[-2,2],[-2,-1],[-3,1],[-3,2],[-2,1],[-2,1],[-3,2],[-1,8],[-1,3],[-1,1],[-5,-3],[-2,2],[-3,3],[-3,1],[0,1],[0,2],[7,9],[3,6],[2,3],[3,1],[2,1],[1,6],[1,1],[1,0],[3,2],[6,5],[0,2],[-1,1],[-2,2],[-2,2],[-2,-1],[-1,-1]],[[6963,7478],[0,1],[-1,0],[-2,1],[-2,1],[-1,0],[0,-1],[1,-2],[1,-2],[2,-1],[2,3]],[[6993,7485],[0,2],[-1,0],[-2,-1],[0,-1],[1,-2],[1,-1],[1,3]],[[6977,7482],[1,0],[-1,5],[1,4],[-3,0],[-1,1],[-2,4],[0,1],[-1,-2],[-1,-2],[1,-3],[1,-2],[1,-1],[0,-1],[-1,-4],[1,-1],[3,0],[1,1]],[[7869,5801],[-1,-2],[-1,5],[0,1],[2,-4]],[[7862,5834],[-1,-1],[-1,1],[0,3],[1,2],[0,1],[1,-6]],[[7900,5783],[-5,8],[-9,3],[-1,3],[0,1],[-1,-5],[-5,-4],[-2,3],[-2,3],[0,3],[2,3],[2,2],[1,8],[-1,10],[-2,3],[-2,2],[-2,-4],[-1,-6],[-2,-3],[-2,-1],[-3,0],[-2,10],[0,8],[0,9],[1,5],[-3,7],[-1,7],[-1,4],[-1,-2],[0,-2]],[[7858,5858],[0,2],[-5,20],[-1,10],[1,7],[1,3],[-2,3],[-2,5],[-4,6],[0,9],[-1,10],[-1,4],[-1,7],[-1,5],[-1,15],[1,1],[2,0],[4,1],[0,3],[0,2],[2,3],[3,7],[2,8],[2,4],[1,5],[3,7],[5,4],[3,1],[3,2],[4,2],[1,0],[4,-2],[2,-1],[2,0],[3,0],[2,0],[4,2],[6,-2],[4,2],[6,2],[3,-2],[2,-2],[0,-4],[1,-2],[1,-2],[1,0],[1,3],[2,4]],[[7921,6010],[0,-1],[1,-4],[1,-3],[1,-3],[2,-3],[1,0],[4,3],[5,-4],[1,-2],[2,-4],[2,-3],[5,0],[1,7],[-1,4],[-2,8],[-1,5],[1,1],[4,1],[1,1],[1,5],[1,-1],[3,-1],[2,4],[2,3],[0,-1],[1,-3],[1,-1],[2,-2],[2,-3],[1,-4],[1,-1],[3,1],[1,0],[1,4],[1,2],[1,-1],[1,0],[3,5],[2,4],[1,1],[2,-2],[1,1],[1,5],[2,3]],[[7986,6031],[0,-3],[-1,-6],[-1,-6],[-2,-5],[-1,-3],[0,-11],[0,-3],[0,-3],[1,-1],[2,-10],[2,-10],[2,-7],[0,-5],[-1,-12],[-2,-12],[0,-5],[1,-6],[1,-7],[0,-10],[-1,-6],[-1,-4],[-1,-4],[-2,-2],[-1,3],[-2,1],[-2,-2],[-1,-1],[-3,-6],[-3,-6],[-5,-1],[-2,-4],[-2,-1],[-3,0],[-3,-1],[0,-2],[0,-10],[0,-2],[0,-1],[-2,0],[-3,1],[-3,3],[-3,0],[-2,-4],[0,-2],[-1,0],[-1,-1],[-1,-2],[0,-2],[1,-5],[0,-6],[0,-5],[1,-3],[5,-9],[2,-2],[0,-2],[-1,-5],[1,-7],[-2,0],[-3,3],[-1,2],[-2,-2],[0,1],[-2,3],[-1,4],[-2,0],[-3,-1],[-4,-1],[-1,0],[0,-1],[-2,-6],[-1,1],[-4,2],[-3,1],[-1,-1],[1,-5],[1,-4],[-1,-2],[-2,-2],[-2,-4],[-1,-3],[-1,-1],[-4,0],[-3,0],[-2,-4],[-1,-2],[-1,-1]],[[784,4525],[0,-1],[-1,0],[0,1],[0,2],[0,1],[1,-2],[0,-1]],[[670,4860],[0,-1],[-1,0],[0,1],[0,1],[1,0],[0,-1]],[[152,4915],[1,-1],[0,-1],[-1,1],[0,1],[0,1],[0,-1]],[[216,4924],[1,0],[0,-1],[-1,0],[0,1],[0,1],[1,0],[-1,-1]],[[244,4927],[-1,-1],[0,1],[0,1],[1,-1]],[[696,4948],[-1,0],[0,1],[-1,1],[0,1],[1,0],[1,1],[0,-1],[0,-1],[0,-2]],[[248,5003],[-1,0],[0,1],[1,0],[0,-1]],[[231,5024],[1,-1],[0,-1],[1,-2],[0,-1],[-1,0],[-1,1],[0,1],[1,-1],[0,1],[0,2],[-1,0],[0,1],[-1,0],[0,1],[1,-1]],[[9854,5114],[0,-3],[-1,0],[0,2],[0,3],[-1,3],[1,-1],[1,-3],[0,-1]],[[9709,5133],[-1,1],[0,1],[1,-1],[0,-1]],[[9846,5138],[0,-2],[-1,1],[1,2],[-1,8],[-1,1],[-1,2],[2,-2],[1,-1],[0,-5],[0,-4]],[[9805,5242],[2,-2],[0,-2],[-1,-1],[-2,-5],[2,4],[0,3],[-1,2],[-1,2],[1,0],[0,-1]],[[9806,5261],[-1,0],[0,1],[4,1],[0,1],[0,-1],[0,-1],[-1,0],[-2,-1]],[[9805,5283],[-1,-1],[1,1],[0,1],[0,4],[1,0],[0,-2],[0,-2],[-1,-1]],[[9805,5290],[0,-1],[-1,3],[-1,3],[0,1],[0,-1],[1,-1],[0,-1],[1,-3]],[[629,5291],[5,-7],[-2,0],[-5,3],[-4,6],[1,2],[1,-3],[2,-2],[1,5],[1,1],[-4,5],[2,-1],[3,-3],[-1,-6]],[[9800,5360],[-2,-3],[0,1],[0,1],[2,2],[1,0],[0,-1],[-1,0]],[[9804,5364],[-2,-2],[-1,0],[3,3],[0,-1]],[[574,5410],[2,-5],[0,-3],[-2,1],[-1,1],[2,0],[0,1],[-1,1],[-1,1],[0,-2],[-1,2],[0,1],[1,1],[1,1]],[[3263,6170],[-2,-1],[-1,1],[0,4],[1,1],[2,-2],[0,-3]],[[3260,6177],[-1,-1],[-1,3],[-2,1],[-2,3],[0,1],[0,1],[1,1],[3,-3],[1,-3],[1,-2],[0,-1]],[[8508,7097],[-1,-1],[-1,1],[0,1],[-2,3],[0,2],[1,3],[4,5],[9,5],[2,0],[4,-2],[1,-4],[-1,-3],[-1,-3],[-4,-4],[-4,-2],[-7,-1]],[[8520,7162],[1,-3],[-3,1],[-1,2],[0,3],[2,0],[1,-3]],[[8506,7163],[-2,0],[-1,2],[-1,0],[1,3],[2,5],[1,2],[3,-1],[1,-3],[-2,-4],[-2,-4]],[[8549,7178],[0,-2],[-2,2],[2,3],[0,-3]],[[8504,7184],[0,-1],[-2,0],[-1,4],[0,3],[-2,2],[2,3],[3,-5],[0,-6]],[[8557,7189],[-1,-6],[-2,0],[-1,3],[-1,-1],[-1,-1],[-1,5],[0,4],[2,2],[2,-1],[2,-1],[1,-4]],[[8575,7188],[-2,-3],[-4,4],[-1,3],[3,4],[2,4],[2,1],[0,-13]],[[8511,7286],[-1,-4],[-1,2],[-1,9],[2,-3],[1,-4]],[[8636,7343],[-2,-2],[-1,2],[0,1],[1,2],[1,1],[1,-2],[0,-2]],[[8514,7357],[-1,-7],[-1,0],[-1,1],[-1,1],[-1,7],[2,3],[2,-2],[1,-3]],[[8565,7408],[7,-25],[6,-17],[6,-12],[8,-23],[2,-13],[0,-7],[2,-11],[-1,-6],[0,-10],[-1,-4],[-1,-4],[0,-7],[1,-4],[0,-5],[0,-2],[1,0],[2,2],[1,0],[0,-6],[-2,-15],[-2,-11],[-2,-9],[-4,-9],[-3,-3],[-3,-1],[-5,-1],[-4,2],[-4,-1],[-2,-2],[-1,-3],[1,-5],[0,-4],[-2,1],[-3,2],[-3,0],[-2,1],[-1,5],[-2,0],[-3,-3],[-4,-1],[-2,-1],[0,-3],[0,-2],[3,-4],[-1,-3],[-3,-2],[-1,4],[-2,5],[-1,0],[-2,-1],[0,-5],[1,-3],[1,-4],[-2,-4],[0,-3],[-2,-2],[-4,5],[0,3],[2,3],[0,4],[0,2],[-6,-9],[-4,-10],[-2,1],[-1,3],[-1,1],[-4,-7],[-1,-5],[-1,0],[-1,2],[0,5],[0,4],[-5,5],[-1,5],[1,3],[3,-2],[3,0],[-1,3],[-1,1],[2,1],[2,3],[-2,0],[-2,-1],[-1,1],[-1,6],[-2,6],[-1,7],[2,3],[1,6],[2,8],[1,3],[2,2],[1,2],[-1,1],[-2,1],[0,2],[1,1],[2,3],[3,3],[1,6],[-1,1],[-2,2],[1,3],[0,2],[0,2],[-2,3],[-2,4],[1,4],[-1,6],[0,5],[0,3],[-1,6],[0,6],[-2,-1],[-1,-1],[-4,2],[-2,0],[0,5],[1,6],[4,5],[2,0],[2,2],[2,1],[3,-3],[3,-1],[1,-6],[1,-1],[1,2],[2,3],[0,1],[0,2],[-3,1],[-2,7],[0,3],[-1,2],[1,6],[-3,7],[-1,2],[0,6],[-1,4],[-1,2],[0,3],[0,2],[1,0],[1,2]],[[8517,7360],[1,1],[0,2],[0,5],[2,3],[4,8],[1,4],[2,3],[2,3],[3,1],[3,1],[7,-1],[1,1],[5,0],[1,-1],[3,0],[4,0],[2,1],[1,2],[2,4],[1,6],[2,5],[1,0]],[[5598,7617],[-4,-1],[-2,-2],[-1,-4],[0,-1],[-1,0],[-1,1],[-2,3],[-3,0],[-7,-6],[-1,-3],[0,-7],[-1,-1],[-1,-1],[-3,0],[0,1]],[[5557,7634],[0,1],[0,4],[0,3],[-1,3],[1,2],[2,0],[1,-1],[1,3],[4,2]],[[5565,7651],[3,1],[1,2],[-1,2],[0,2],[4,5],[1,2],[0,1],[0,2],[-1,3],[0,1],[2,2],[2,1],[1,1],[1,-2],[0,-1],[0,-2],[2,-2],[2,-2],[2,-1],[2,-3],[3,-5],[0,-2],[3,-3],[2,-2],[0,-5],[7,-4],[2,0],[1,0],[0,-2],[-1,-3],[-3,-10],[0,-2],[-2,-2],[-1,-1],[1,-3],[0,-2]],[[6340,6890],[-1,-1],[-1,0],[-1,3],[-2,8],[1,3],[0,1],[0,1],[1,1],[0,3],[1,2],[1,-3],[3,-9],[0,-3],[0,-2],[-2,-4]],[[6345,6828],[-5,0],[-6,0],[-5,-1],[-5,0],[-3,6],[-1,6],[-1,6],[-2,9],[-8,2],[-5,1],[-7,1],[-5,2]],[[6332,6911],[0,-2],[1,-7],[2,-7],[1,-5],[1,-3],[-2,1],[-1,1],[-2,1],[-4,-8],[-3,-4],[0,-1],[3,-2],[3,0],[2,1],[1,-1],[1,-5],[0,-4],[3,-13],[2,-5],[2,-7],[1,-5],[1,-3],[1,-5]],[[7836,6473],[2,-6],[3,-6],[4,-8],[1,-4],[3,-4],[0,-3],[1,-4],[0,-4],[1,-2],[1,0],[1,0],[1,2],[1,5],[0,1],[1,-4],[1,-1],[1,-1],[1,-1],[0,-4],[0,-3],[-1,-3],[-1,-4],[0,-6],[-1,-4],[1,-4],[6,-18],[3,-3],[7,-3],[3,-3],[2,-2],[2,1],[2,5],[3,3],[5,5],[1,0],[3,-2],[4,-5],[3,-5],[2,-3],[1,-2],[0,-3],[-1,-2],[-2,-2],[-2,-2],[-1,-3],[1,-1],[3,0],[3,-3],[1,-2],[0,-3],[1,-3],[1,-1],[3,0],[1,-1],[1,-1],[1,-5],[0,-4],[-2,-4],[-1,-3],[-1,-4],[-1,-4],[-5,-8],[-1,-1],[-8,5],[-3,-1],[-2,0],[-1,0],[-1,-2],[2,-4],[0,-5],[-1,-4],[-3,-3],[-1,-1],[0,-2],[1,-2],[2,-3],[3,-2],[9,-12],[2,-3],[3,-4],[3,-3],[8,-4],[3,-3],[1,-2],[0,-2],[-1,-2],[-1,-5],[0,-3],[1,-2],[1,-4],[3,-6],[2,-3]],[[7925,6231],[2,0],[2,-2]],[[7929,6229],[1,-4],[2,-5],[0,-4],[1,-5],[2,-6],[3,-5],[3,-7],[2,-4],[1,-2],[7,-12],[2,-4],[2,-8],[2,-1],[1,-2],[0,-4],[0,-3],[1,-10],[1,-3],[1,-4],[1,-2],[1,-2],[1,-1],[2,3],[1,2],[0,-1],[1,-7],[2,-2],[1,-3],[2,-2],[4,-8],[3,-3],[1,-1],[1,-1],[1,-3],[-1,-2],[-1,-2],[-4,-5],[-1,-2],[1,-3],[1,-4],[1,-4],[2,-3],[3,-5],[3,-5],[2,-4],[1,-4],[-1,-3],[-1,-4],[-1,-4],[-2,-2],[0,-2],[0,-4],[1,-3],[0,-3],[0,-6]],[[7921,6010],[2,1],[2,3],[3,3],[1,4],[1,3],[0,4],[0,11],[1,5],[0,6],[-1,5],[0,8],[0,3],[0,3],[2,3],[1,4],[1,6],[0,4],[-1,2],[-1,2],[-3,3],[-2,3],[-1,3],[0,3],[1,3],[-2,3],[-5,3],[-3,4],[0,4],[-3,6],[-3,7],[-2,11],[0,13],[0,11],[2,13],[-2,10],[-3,4],[-3,4],[-3,5],[-3,7],[-3,10],[-5,13],[-2,6],[-2,-1],[-3,1],[-4,4],[-4,2],[-3,0],[-3,-1],[-1,-2],[0,-2],[1,-2],[0,-1],[-2,-1],[-2,-3],[-1,-4],[-1,-7],[-2,-2],[-2,-1],[-3,-2],[-3,-3],[-1,-2],[0,-2],[-1,1],[-1,2],[0,3],[-1,3],[-3,1],[-3,3],[-3,6],[-2,3],[-2,1],[-1,-3],[-3,-5],[-2,-2],[-1,1],[-2,-2],[-1,-4],[-1,-4],[-4,-4],[-4,-6],[-3,-5],[-4,-7],[-1,-1],[-2,1],[-2,2],[-2,3],[3,12],[3,14],[1,6],[0,4],[0,4],[-2,4],[-1,3],[0,2],[0,2],[2,3],[1,5],[2,10],[2,11],[0,6],[-2,7],[-1,7],[1,9],[0,4],[-2,2],[-5,1],[-2,0],[-1,-1],[-2,-3],[-1,-1],[-4,-1],[-3,3],[-2,5],[-1,7],[2,7],[1,7],[1,5],[0,2],[-1,3],[-2,4],[-2,5],[-1,3],[-2,0],[-1,-3],[-1,-4],[-1,-1],[-1,1],[0,3]],[[7780,6354],[1,3],[1,13],[2,8],[2,4],[2,1],[3,0],[2,0],[1,2],[0,1],[-2,1],[0,2],[0,4],[1,3],[1,1],[1,4],[2,7],[1,3],[2,0],[3,3],[4,6],[2,6]],[[5975,7089],[1,5],[1,5],[2,8],[2,7],[5,21],[3,9],[1,12],[4,11],[3,4],[2,3],[0,4]],[[5999,7178],[5,0],[3,1],[1,2],[2,-1],[1,-3],[-1,-2],[-2,-3],[1,-1],[1,0],[2,-2],[1,-2],[3,-12],[-2,-5],[-2,-5],[-1,0],[-2,-2],[-1,-3],[-1,-2],[0,-2],[2,-2],[1,-1],[-1,-1],[-2,1],[-2,0],[-1,0],[-2,-1],[-2,-2],[-1,-2],[0,-1],[-1,-4],[1,-3],[1,-1],[0,-1],[0,-1],[-1,-2],[-2,-2],[0,-2],[-1,-2]],[[4790,5434],[-3,1],[-10,8],[-7,5],[-24,27],[-7,11],[-8,16],[-17,32],[-4,5],[-5,3],[-3,2],[-2,3],[-2,9],[-4,5],[-8,8],[-6,13]],[[4680,5582],[1,2],[3,8],[3,8],[2,5],[3,5],[2,4],[3,4],[6,11],[1,2],[1,8],[1,10],[1,3],[4,2],[1,1],[1,7],[1,9],[0,2]],[[5693,6451],[0,-29],[0,-29],[0,-28],[0,-29],[-7,0],[-7,0],[-7,0],[-6,0],[0,-8],[0,-7],[0,-7],[0,-7]],[[5666,6307],[-14,13],[-13,14],[-13,14],[-14,13],[-13,14],[-13,14],[-14,13],[-13,14],[-13,13],[-14,14],[-13,14],[-13,13],[-13,14],[-14,14],[-13,13],[-13,14],[-10,9],[-9,-9],[-8,-7],[-10,-10]],[[5416,6508],[-12,-12],[-9,-9],[-1,0],[-9,16],[-8,12],[-3,4],[-14,6],[-14,7],[-14,6]],[[5264,6925],[3,3],[5,3],[2,3],[1,2],[4,9],[2,5],[2,7],[1,5],[0,4],[0,5],[-2,13],[-2,12],[2,5],[1,2],[2,6],[1,1],[4,2],[2,4],[2,4],[0,3],[2,3],[3,2],[1,4],[5,5],[5,5],[5,5],[4,4],[1,3],[0,3],[-2,7],[0,8],[0,7],[0,4],[1,11],[0,1]],[[5319,7095],[4,-4],[5,-1],[13,-14],[4,-1],[9,-2],[10,6],[4,1],[7,-6],[4,-1],[5,0],[9,-5],[2,-2],[5,-7],[3,-3],[18,-7],[3,-4],[2,-9],[0,-11],[2,-8],[2,-10],[3,-7],[3,-6],[3,-4],[8,-5],[9,-3],[10,0],[15,-8],[14,-9],[3,-4],[7,-4],[13,-21],[7,-8],[6,-1],[4,1],[9,8],[3,4],[8,18],[3,9],[1,7],[0,7],[-1,6],[-2,6],[-2,8],[-1,15],[1,11],[2,6],[2,7],[7,12],[7,8],[13,12],[7,0],[3,1],[5,8],[3,0],[3,-2],[10,1],[4,-2],[5,-5],[7,-3],[4,-3],[5,-4],[1,-10],[-1,-3],[0,-4],[5,-7],[14,-3],[3,-2],[4,-5],[3,-2],[9,0],[6,1],[6,-2],[2,-2],[2,-4],[2,-10],[1,-3]],[[3308,5980],[-1,-6],[-3,4],[-1,4],[0,3],[2,6],[2,3],[1,2],[0,-5],[0,-11]],[[7218,5705],[1,-4],[-2,3],[-2,2],[-1,2],[4,-2],[0,-1]],[[7221,5739],[-2,-1],[-1,4],[-1,1],[1,1],[0,1],[1,-4],[2,-2]],[[7221,5749],[3,0],[3,0],[2,-1],[3,-9],[9,-16],[5,-16],[1,-3],[0,-3],[2,-1],[1,-2],[5,-15],[0,-3],[0,-4],[1,-2],[1,-2],[2,0],[1,-3],[1,-12],[0,-4],[0,-2],[7,-19],[0,-2],[0,-2],[0,-2],[1,-3],[2,-9],[1,-2],[2,-8],[0,-16],[-1,-7],[-1,-8],[-1,-8],[-2,-6],[-2,-5],[-7,-11],[-2,-2],[-10,-7],[-6,-6],[-7,-2],[-6,4],[-5,8],[-2,12],[-2,13],[-2,14],[-2,44],[-1,12],[-2,15],[1,7],[1,7],[0,-15],[0,-1],[1,1],[1,15],[0,6],[3,16],[0,3],[0,6],[0,3],[3,12],[1,6],[1,7],[0,7],[-1,7],[3,-2],[2,-2],[1,-2],[2,1],[1,0],[-1,4],[-3,3],[-6,3],[-2,2],[-1,3],[1,3],[0,1]],[[5798,3450],[-3,-1],[0,-1],[-2,1],[-2,-1],[-2,0],[-1,-1],[-2,-4],[-4,-11],[-1,-2],[0,-4],[-1,-4],[-1,-2],[-1,-1],[-4,1],[-4,1],[-2,4],[-2,4],[-1,3],[-2,2],[0,1],[-2,1],[0,1],[-1,1],[0,2],[-1,2],[0,5],[-1,3],[-2,5],[-1,4],[-2,6],[-1,5],[-1,5],[0,2],[1,2],[3,3],[3,2],[1,3],[2,6],[1,3],[1,2],[1,2],[2,5],[2,6],[2,6],[2,2],[4,2],[4,5],[4,5],[6,5],[3,1],[2,1],[0,-1],[1,-3],[1,-3],[3,-4],[1,-1],[3,-6],[3,-4],[3,-5],[2,-2],[1,-1],[1,-4],[1,-3],[1,-3],[0,-3],[-1,-7],[-2,-7],[-1,-3],[-2,-2],[-1,-3],[-1,-6],[0,-6],[-2,-3],[-2,-2],[-2,-2],[-4,-4]],[[5582,8368],[-2,0]],[[5580,8368],[3,7],[1,4],[1,6],[1,2],[0,-3],[0,-4],[-2,-8],[-2,-4]],[[5652,8291],[0,1],[0,2],[0,5],[-1,3],[-2,4],[-3,2],[-3,2],[-2,1],[-1,1],[-1,1],[0,1],[-1,1],[-3,2],[-2,0],[-1,-2]],[[5632,8315],[-1,2],[-2,6],[1,4],[0,4],[4,11],[-1,2],[-2,4],[-3,2],[-2,5],[-6,0],[-6,0],[-1,0],[-6,3],[-5,3],[-4,2],[-3,2],[-1,3],[-3,-1],[-2,0]],[[5589,8367],[-1,5],[1,6],[-1,9],[-4,12],[0,12],[0,2]],[[5584,8413],[8,7],[9,7],[2,1],[9,4],[1,1],[8,-1],[6,-1],[5,0],[3,1],[2,-1],[3,-3],[2,0],[2,2],[11,-1],[3,0],[3,-1],[5,-2],[3,-1],[7,1],[3,0],[2,0],[5,5],[2,1],[1,1],[2,-1],[1,-4],[4,-7],[4,-1],[10,-3],[2,-2],[6,-6],[4,-3],[2,-3],[3,-5],[2,-3],[4,-3],[4,-2],[1,0]],[[5759,8497],[3,0],[2,-1],[0,-4],[4,-4],[4,-3],[0,-1],[1,-3],[-1,-3],[0,-1],[-1,-2],[-2,-5],[0,-4],[-2,-8],[1,0],[4,1],[1,-1],[1,-1],[0,-5],[2,-2],[1,-4],[0,-2],[3,-3],[0,-2],[2,-7],[1,-5],[0,-3],[-1,-4],[-1,-2]],[[5584,8413],[-1,11],[1,22],[1,11],[5,6],[3,5],[1,6],[0,6],[2,5],[7,15],[6,1],[8,4],[9,4],[2,-5],[1,-3],[10,-12],[3,-3],[4,-14],[10,-7],[8,2],[4,4],[6,6],[3,4],[0,5],[-1,18],[-2,8],[1,5]],[[8153,6465],[0,-1],[-1,-1],[0,-1],[-1,0]],[[3249,6225],[-3,0]],[[3246,6225],[0,1],[2,1],[1,0],[0,-2]],[[4758,6777],[-3,0],[0,-3],[1,-4],[0,-5],[-1,-2],[0,-3],[0,-3],[1,-4],[0,-3],[0,-2],[-1,-2],[-2,-1],[-4,-1],[-2,0],[-3,1],[-2,0],[-2,0],[-2,-1],[-2,-2],[-2,-4],[-3,-4],[-2,-3],[-2,-1],[-2,0],[-3,3],[-1,1],[-1,0],[-2,-2],[-2,-1],[-1,0],[-3,2],[-4,4],[-2,1],[-2,1],[-3,1],[-2,0],[-3,0],[-3,-3],[-3,-1],[-3,-2],[-4,-2],[1,-5],[1,-3],[0,-3],[0,-3],[-2,-3],[-2,-4],[-1,-3],[-1,-4],[-1,-2],[-2,-4],[-1,-4],[0,-3],[-1,-4],[-1,-1],[-3,-1],[-3,-1],[-2,-1],[0,-2],[-1,-4],[0,-3],[-1,-2],[0,-6],[-2,-5],[0,-7],[-1,-6],[-1,-9],[-1,-9],[-2,-8],[-1,-5],[-1,-3],[-2,-3],[-1,-3],[-2,-3],[-3,-3],[-3,-3],[-2,-3],[-1,-1],[-1,-2],[-2,-4],[-2,-6],[-1,-4],[-2,-8],[-1,-4],[-1,-2],[-2,-2],[-3,-2],[-3,-2],[-2,-3],[-3,-2],[-2,-2],[-1,-4],[-1,-4],[-2,-5],[-1,-7],[0,-4],[-2,-14],[-1,-8],[0,-5],[-1,-6],[-1,-10],[0,-8],[0,-5],[0,-3],[-2,-4],[-1,-3],[-2,-4],[-2,-2],[0,-3],[-2,-3],[-1,-4],[-2,-3],[0,-2],[1,-4],[-1,-4],[-1,-5],[-2,-6],[-3,-3],[-3,0],[-5,0],[-4,0],[-5,0],[-4,1],[-4,2],[-5,0],[-3,0],[-4,-1],[-11,0],[-4,-1],[-6,-2],[-2,0]],[[4527,6418],[2,27],[4,15],[3,7],[5,3],[4,15],[2,14],[2,6],[1,5],[-1,4],[3,8],[3,11],[2,7],[3,12],[1,2],[0,3],[-2,-2],[-1,-5],[-2,-3],[0,4],[2,6],[3,6],[6,7],[11,24],[4,4],[4,10],[1,8],[0,20],[2,11],[2,8],[3,15],[2,7],[2,14],[1,5],[3,2],[4,7],[6,5],[7,8],[3,6],[3,8],[2,15],[4,17],[3,13],[3,6],[3,9],[4,3],[9,2],[14,7],[12,10],[3,5],[4,8],[6,11],[11,13],[5,7],[8,18],[5,15],[5,10],[3,8],[2,9],[1,14],[-1,6],[-3,8],[-2,3],[-1,4],[1,8],[0,12],[1,21],[4,16],[9,22],[2,9],[1,14],[0,5],[11,20],[7,15],[2,4],[6,7],[20,15],[12,11],[7,8],[4,10],[11,37],[11,52],[1,6],[5,2],[3,0],[3,2],[4,4],[3,-1],[-2,-3],[0,-6],[3,-8],[4,-8],[7,-11],[6,-4],[8,-3],[10,5],[5,0],[3,2],[3,-3],[5,-1],[5,2],[4,4],[3,5],[0,-2],[0,-3],[1,-2],[2,-6],[1,-3],[3,1],[2,-2],[6,1],[6,-1]],[[5206,7704],[-2,-1]],[[5783,7802],[-1,3],[-2,4],[-1,1],[1,1],[1,1],[1,1],[0,4],[-1,4],[-1,2],[0,4],[0,5],[1,9],[2,12],[1,6],[-1,4],[1,7],[-1,4],[-2,5],[-2,11],[-3,3],[-3,5],[-1,3],[-1,3],[-2,3],[-3,4],[-2,7],[-2,4],[0,1],[-3,5],[-2,4],[-1,4],[0,3],[-2,7],[-2,5],[-2,4],[-1,2],[-2,4],[-3,2],[-3,1],[-2,-1]],[[5739,7963],[0,2],[6,6],[2,-1],[3,0],[6,0],[3,3],[2,-1],[1,2],[3,2],[0,-1],[4,-1],[3,-2],[2,-2],[2,-2],[2,-1],[1,-1],[1,-3],[2,-1],[3,0],[2,-1],[-1,-3],[1,-1],[1,1],[1,-1],[0,-2],[1,-1],[2,3],[2,0],[5,-2],[2,-7],[2,-2],[1,-1],[2,1],[2,1],[0,-1],[2,-4],[1,-6],[0,-3],[-1,-4],[-1,-5],[-1,-3],[1,-2],[0,-2],[2,0],[3,-4],[2,-3],[2,-2],[1,0],[1,-1],[0,-2],[0,-3],[-1,-4],[0,-2],[2,-2],[0,-3],[0,-2],[1,-2],[3,-3],[4,-3],[1,-3],[1,-3],[0,-6],[0,-5],[5,-6],[0,-2],[-1,-1],[-6,-1],[-1,0],[-2,5],[-1,0],[-2,-2],[-1,-1],[-2,1],[-1,1],[-1,1],[-1,1],[-1,-2],[-2,1],[-1,1],[-1,-4],[-1,-1],[0,7],[-1,2],[-1,0],[-3,-2],[-2,-2],[-1,-2],[0,-4],[0,-4],[2,-7],[-1,-2],[0,-5],[-3,-4],[-3,-2],[-1,-5],[-1,-4],[-3,-3],[-2,-4],[0,-3],[0,-2],[0,-2],[0,-1],[-1,-1],[-4,-1],[-1,0],[-2,-2]],[[6386,4210],[-3,-10],[1,8],[4,13],[1,1],[-3,-12]],[[6342,4414],[0,-2],[-3,1],[-1,7],[2,0],[0,3],[1,1],[1,-7],[0,-3]],[[6375,4468],[2,-6],[1,-6],[5,-14],[2,-5],[2,-6],[0,-12],[3,-17],[3,-27],[1,-27],[1,-13],[2,-12],[4,-12],[1,-13],[-3,-14],[-3,-14],[0,-2],[-2,-3],[-1,0],[-2,3],[-2,6],[-3,13],[-1,6],[-1,2],[-3,-1],[-2,-4],[0,-3],[0,-7],[1,-7],[0,-7],[0,-8],[1,-3],[1,-2],[2,-6],[0,-13],[-1,-7],[-2,-5],[0,-3],[1,-4],[-1,-2],[-3,-2],[-1,-2],[-2,-6],[-2,-12],[0,-6],[1,-19],[0,-13],[-3,-25],[-2,-12],[-3,-15],[-4,-18],[-4,-24],[-3,-24],[-3,-15],[-2,-15],[-4,-25],[-4,-26],[-4,-28],[-7,-32],[-1,-4],[-1,-16],[-2,-14],[-2,-14],[-3,-23],[-1,-8],[-1,-6],[-3,-15],[-2,-5],[-1,-6],[0,-7],[-1,-7],[-3,-13],[-4,-11],[-3,-4],[-6,-6],[-3,-1],[-6,0],[-6,-3],[-7,-7],[-6,-7],[-3,-4],[-3,-2],[-8,0],[-2,2],[-9,12],[-3,2],[-6,1],[-2,1],[-2,2],[-2,6],[-5,5],[-1,2],[-1,4],[-1,4],[-1,4],[-1,9],[-2,5],[-4,11],[-1,3],[0,11],[0,8],[0,13],[0,7],[2,6],[-1,6],[-1,6],[-1,7],[-1,6],[-5,12],[-1,5],[-1,6],[-2,18],[0,6],[0,13],[1,7],[1,4],[0,4],[1,3],[1,2],[1,3],[2,17],[2,3],[3,3],[3,4],[2,6],[1,12],[4,12],[2,6],[3,10],[3,13],[1,7],[1,6],[1,15],[0,7],[0,7],[-2,7],[-4,13],[0,3],[0,9],[0,7],[-1,7],[-2,7],[-2,12],[-1,21],[0,7],[-1,7],[-1,6],[1,11],[12,40],[1,4],[-1,13],[0,7],[1,2],[1,2],[2,0],[10,2],[1,1],[3,4],[3,6],[2,2],[1,-1],[1,-2],[1,-2],[4,3],[1,0],[2,0],[1,2],[0,4],[1,3],[1,1],[5,1],[3,1],[5,2],[4,-9],[1,-1],[1,0],[1,1],[-2,5],[-1,3],[0,3],[2,6],[2,5],[6,8],[6,9],[1,0],[2,-1],[1,-11],[0,-1],[1,0],[1,1],[1,4],[0,3],[-1,4],[0,3],[0,2],[2,6],[3,6],[1,7],[1,3],[2,4],[1,-1],[0,-3],[1,-3],[-1,-3],[-1,-3],[0,-4],[1,-1],[2,1],[1,8],[3,7],[1,3],[1,3],[3,-1],[3,-1],[-5,7],[-1,10],[5,18],[1,3],[0,1],[1,2],[-3,6],[-1,3],[1,4],[1,4],[1,3],[2,1],[1,-2],[3,-5],[2,0],[2,4],[2,6],[3,4],[3,2],[5,10],[3,19],[0,5],[0,7],[-2,6],[-1,8],[0,2],[3,-1],[1,1],[2,7],[5,14],[2,0],[1,-3],[1,-3],[1,-3],[3,-6],[1,-5]],[[7039,5370],[-1,0],[0,1],[0,1],[0,1],[1,0],[0,-1],[0,-1],[0,-1]],[[7041,5424],[0,-1],[-1,0],[0,1],[0,1],[1,1],[0,2],[1,0],[0,-1],[0,-1],[-1,-1],[0,-1]],[[2453,6260],[-3,-2],[-1,2],[7,5],[1,0],[0,-1],[-3,-2],[-1,-2]],[[1919,6263],[-2,-1],[-2,4],[0,2],[2,2],[1,-3],[1,-4]],[[2585,6353],[-2,-2],[0,7],[1,6],[1,4],[3,0],[2,1],[0,-1],[-2,-5],[-3,-10]],[[2591,6407],[1,-3],[-1,1],[-1,2],[0,2],[1,0],[0,-2]],[[2041,6429],[0,-5],[-3,2],[0,3],[0,5],[1,0],[1,-2],[1,-1],[0,-2]],[[1950,6575],[-1,0],[-1,3],[-1,7],[0,1],[3,-9],[0,-1],[0,-1]],[[1897,6589],[0,-3],[-9,11],[2,1],[3,-1],[4,-8]],[[1928,6624],[1,-6],[-1,0],[-2,4],[-1,4],[0,2],[0,1],[3,-3],[0,-2]],[[1887,6598],[0,-1],[-3,7],[0,4],[-1,2],[-3,2],[3,9],[1,19],[1,-3],[-2,-20],[0,-2],[1,-3],[1,-4],[0,-4],[2,-4],[0,-2]],[[1914,6683],[0,-3],[-1,1],[-2,-8],[-1,-1],[1,12],[2,1],[1,1],[0,-3]],[[1801,6801],[-1,-2],[-4,4],[2,6],[0,7],[1,2],[1,-3],[1,-9],[0,-5]],[[1715,6851],[-1,-2],[-3,12],[0,3],[1,1],[1,0],[0,-3],[2,-3],[0,-2],[0,-6]],[[1883,6854],[-2,-13],[-2,0],[-5,4],[0,3],[2,16],[1,2],[4,2],[0,-2],[1,-5],[1,-7]],[[1857,6857],[-1,-1],[-2,4],[-7,12],[-2,6],[-1,3],[1,6],[2,-1],[2,-4],[1,-4],[1,-4],[4,-2],[1,-10],[1,-5]],[[1814,7010],[-1,0],[-2,2],[0,3],[1,0],[1,-2],[1,-2],[0,-1]],[[2301,6679],[0,-12],[-2,-10],[-5,-20],[-3,-12],[-4,-36],[-2,-24],[0,-11],[0,-2],[0,-1],[-1,-25],[1,-21],[-1,-3],[-1,-6],[-1,-9],[0,-4],[0,-3],[2,-13],[0,-10],[5,-17],[3,-6],[3,-5],[2,-3],[-1,-7],[-1,-4],[-1,-6],[-1,5],[1,6],[1,4],[0,2],[-2,3],[-4,8],[-5,16],[4,-25],[1,-4],[1,-1],[1,-2],[0,-3],[0,-2],[4,-17],[5,-17],[0,-5],[2,-6],[11,-24],[7,-19],[3,-17],[1,-6],[1,-7],[5,-8],[1,-6],[3,-3],[2,-9],[3,-5],[-1,0],[-3,3],[0,-2],[3,-4],[5,-4],[2,0],[-2,2],[-2,3],[1,0],[3,-3],[11,-1],[4,-8],[6,-3],[4,-9],[3,-10],[3,-1],[2,0],[5,2],[9,6],[3,3],[6,4],[9,1],[3,-1],[7,3],[3,3],[1,3],[0,2],[7,3],[1,0],[6,1],[3,1],[4,1],[3,-5],[0,-2],[-2,-2],[1,-2],[3,-3],[5,-2],[2,1],[3,5],[4,5],[0,5],[-1,3],[-1,0],[0,2],[1,4],[-1,1],[-2,-3],[-1,0],[0,1],[1,2],[8,8],[2,4],[3,3],[6,11],[2,22],[1,4],[4,7],[0,2],[0,4],[0,12],[0,9],[0,10],[1,9],[1,2],[2,15],[5,6],[8,8],[2,1],[26,8],[4,2],[4,5],[3,2],[6,0],[2,1],[1,0],[0,1],[1,1],[3,-1],[7,-3],[2,-1],[6,-3],[6,-2],[1,1],[1,1],[1,2],[-1,2],[-1,0],[-1,-1],[-1,0],[-3,1],[1,1],[2,0],[2,1],[3,2],[2,-2],[4,-7],[2,-2],[0,-11],[1,-2],[0,-3],[-1,-8],[-1,-7],[-2,-6],[-4,-9],[-4,-7],[-6,-16],[-1,-7],[0,-6],[1,-6],[0,-2],[-1,-2],[-1,0],[-2,-3],[-3,-8],[0,-3],[1,-2],[2,1],[2,0],[1,1],[1,0],[0,-5],[-1,-3],[-1,-1],[-2,-1],[-1,-2],[-1,-2],[0,-5],[1,0],[2,4],[1,-1],[0,-1],[-2,-14],[-2,-14],[-2,-9],[-1,-12],[-1,-5],[-2,-5],[-3,10],[-2,2],[0,3],[1,11],[-1,7],[-1,0],[-1,-4],[-2,-3],[0,-4],[-2,-8],[-1,-2]],[[2438,6022],[-1,1],[-8,16],[-7,17],[-3,5],[-3,5],[-4,8],[-11,17],[-5,8],[-5,9],[-5,6],[-4,3],[-2,2],[-2,3],[-1,0],[0,-4],[1,-1],[2,-2],[2,0],[1,-1],[5,-5],[1,-3],[-13,10],[-6,1],[0,2],[2,5],[0,1],[-1,1],[-3,-4],[-1,0],[0,2],[0,2],[-2,4],[-1,-1],[-1,-2],[-3,-4],[0,-2],[5,-1],[2,-1],[-1,-2],[-4,0],[-5,-1],[-9,-12],[-9,-5],[-12,-11],[-5,-1],[-3,-2],[-8,5],[-11,10],[-16,3],[-10,14],[-11,6],[-7,13],[-4,1],[-2,2],[-10,5],[-9,3],[-10,11],[-6,4],[-5,5],[-12,8],[-4,4],[-4,7],[-6,7],[-3,5],[-3,3],[-5,10],[-2,5],[-2,2],[-2,1],[-7,-1],[-9,5],[-4,1],[-9,7],[-12,8],[-3,9],[-4,9],[-6,11],[-3,5],[-7,6],[-3,4],[-6,4],[-9,9],[-3,8],[-2,7],[-5,8],[-5,15],[-2,6],[-1,9],[-1,5],[-1,4],[0,3],[3,3],[5,1],[3,4],[0,3],[0,2],[-2,5],[-3,1],[-2,1],[0,1],[1,2],[2,5],[3,6],[2,5],[0,8],[0,7],[0,7],[-6,7],[-1,3],[-2,9],[-3,9],[0,20],[-4,17],[-4,9],[-2,3],[-6,13],[-5,8],[-4,14],[-5,10],[-6,15],[-4,8],[-19,26],[1,0],[6,-6],[1,0],[0,4],[-1,3],[-1,1],[-1,-1],[-2,1],[-1,1],[-3,1],[-4,5],[-1,4],[-1,5],[-5,11],[-2,6],[1,0],[1,-2],[2,-1],[2,0],[1,1],[-1,2],[-1,1],[-8,6],[-2,4],[-7,7],[-1,2],[-1,7],[-2,0],[-1,-2],[-4,-2],[-1,3],[0,2],[3,2],[2,6],[0,2],[-1,-2],[-2,-3],[-2,-2],[-3,-1],[-2,1],[-1,1],[-3,6],[-1,17],[2,6],[3,6],[1,4],[2,-3],[1,0],[-1,3],[-2,3],[-1,3],[0,2],[-1,5],[-5,10],[-6,-1],[-2,1],[-2,4],[-2,6],[-1,6],[0,3],[0,3],[-9,4],[-3,4],[-3,6],[-1,4],[-1,3],[-1,5],[-1,7],[1,8],[2,4],[-7,3],[-2,0],[-2,-2],[-2,2],[-4,3],[-4,8],[-6,16],[-5,5],[-2,5],[-3,5],[-2,6],[0,3],[-1,1],[-3,4],[-3,7],[-1,6],[-1,9],[-2,3],[-2,1],[0,4],[0,3],[-1,4],[-4,11],[-2,8],[-2,3],[-1,4],[0,8],[-2,10],[-4,12],[-3,8],[-1,8],[1,9],[-1,5],[0,1],[0,2],[1,-1],[1,1],[0,6],[-1,1],[-3,2],[-1,1],[-7,2],[-4,3],[-1,7],[-2,3],[-1,2],[-5,5],[-1,-3],[-1,-3],[-2,-1],[-2,0],[-3,2],[-8,11],[-2,1],[-2,1],[-1,2],[-6,5],[1,-3],[2,-3],[1,-8],[-1,-7],[-1,-22],[1,-4],[2,-7],[2,-11],[0,-8],[2,-7],[-1,-16],[1,-4],[2,-8],[4,-7],[1,-4],[5,-6],[3,-7],[7,-10],[2,-4],[6,-15],[0,-4],[1,-6],[3,1],[2,-4],[0,-2],[0,-2],[2,1],[1,-1],[3,-17],[2,-2],[2,-1],[3,-2],[0,-4],[0,-4],[2,-5],[-1,-6],[2,-6],[0,-5],[0,-4],[5,-10],[7,-8],[1,-10],[2,-9],[3,-3],[3,-3],[-1,-4],[0,-3],[4,-7],[1,-10],[3,-6],[1,1],[-2,6],[-1,4],[0,6],[0,1],[7,-10],[0,-7],[2,-4],[1,-6],[1,-3],[0,-5],[2,-8],[0,-12],[1,-8],[4,-12],[4,-3],[0,-6],[3,-16],[4,-9],[2,-7],[0,-4],[-1,-7],[0,-5],[2,-14],[3,-8],[4,-1],[0,-1],[0,-2],[1,-2],[1,2],[1,3],[-1,4],[0,3],[1,2],[1,0],[7,-10],[1,-4],[2,-4],[2,-5],[1,-5],[2,-3],[1,-8],[5,-4],[2,-7],[1,-4],[-2,-11],[-1,-3],[-3,-5],[-3,-5],[-3,-4],[-3,-2],[-2,0],[-2,7],[-3,19],[-2,4],[-1,6],[-2,5],[-7,8],[-4,8],[-4,5],[-4,8],[-10,13],[-5,7],[-2,6],[-2,0],[-2,-1],[0,2],[0,4],[-1,2],[-6,10],[-2,5],[0,6],[2,16],[0,10],[0,5],[-1,0],[0,3],[-1,8],[-1,8],[-6,18],[-4,3],[-4,3],[-10,15],[-2,8],[-1,4],[0,9],[-2,-5],[-2,-4],[-4,0],[-5,-4],[-3,4],[-1,5],[-2,5],[-3,1],[-2,0],[-3,7],[-2,2],[-4,1],[-3,4],[-1,3],[-1,6],[-1,3],[-5,6],[-4,7],[-3,4],[-2,4],[0,2],[6,0],[7,-3],[4,1],[2,2],[2,2],[0,-2],[0,-3],[2,-4],[2,-2],[2,0],[-2,3],[-1,6],[1,2],[0,3],[-3,-1],[0,2],[2,4],[3,12],[1,12],[-3,10],[-4,8],[-10,21],[-6,10],[-2,4],[-1,2],[-5,3],[-4,6],[-7,8],[-3,5],[-2,10],[-2,1],[0,8],[0,12],[-1,3],[-4,4],[-1,8],[0,8],[-1,6],[-7,10],[0,4],[0,5],[-1,4],[-3,9],[-4,8],[-2,4],[0,8],[-1,2],[1,0],[1,1],[0,5],[-6,9],[-2,11],[-3,7],[-1,2],[-2,11]],[[1746,7058],[8,1],[8,1],[8,1],[8,2],[8,1],[8,1],[8,1],[8,2],[3,0],[-2,-9],[-1,-3],[13,-8],[13,-9],[13,-8],[14,-9],[13,-8],[13,-9],[13,-8],[13,-9],[10,0],[10,0],[10,0],[10,0],[9,0],[10,0],[10,0],[10,0],[0,7],[0,6],[0,7],[0,6],[6,0],[6,0],[6,0],[6,0],[6,0],[7,0],[6,0],[6,0],[0,-1],[3,-5],[2,-7],[3,-6],[4,-3],[6,-9],[8,-15],[6,-10],[5,-5],[4,-4],[1,-4],[3,-7],[4,-19],[0,-8],[2,-8],[3,-10],[3,-6],[2,-2],[3,-3],[3,-6],[3,-3],[4,-2],[5,-5],[7,-8],[5,-4],[2,0],[2,3],[2,5],[2,3],[2,2],[0,2],[0,3],[1,8],[3,11],[3,6],[4,1],[3,3],[1,3],[2,0],[3,-2],[5,-2],[6,-1],[4,0],[1,2],[1,0],[0,-2],[1,0],[2,0],[2,-2],[2,-6],[7,-10],[1,-4],[2,-5],[5,-7],[3,-7],[0,-5],[3,-9],[4,-12],[2,-6],[-1,-1],[1,-4],[1,-6],[2,-4],[3,-4],[3,-8],[3,-10],[4,-8],[4,-5],[3,-5],[0,-5],[0,-4],[0,-3],[0,-4],[1,-3],[1,-3],[-1,-5],[0,-2],[0,-1],[4,-9],[2,-7],[2,-11],[2,-7],[2,-3],[4,-1],[3,-2],[2,-4],[3,-2],[3,-1],[3,-2],[3,-4],[5,-3],[8,-1],[6,-4],[4,-5],[2,-1],[1,1],[0,1],[2,2],[3,1]],[[9711,5520],[0,-2],[-1,0],[0,1],[1,2],[1,5],[1,2],[1,2],[0,-2],[-2,-2],[-1,-6]],[[9765,5590],[1,-1],[2,0],[2,-4],[-1,1],[-1,1],[-1,1],[-1,-1],[-1,1],[0,2]],[[9752,5595],[3,-3],[5,1],[-1,-1],[-2,0],[-1,-1],[-1,0],[-3,2],[-2,3],[0,1],[2,-2]],[[9689,5605],[-1,-1],[-2,0],[-2,2],[1,0],[2,0],[2,-1]],[[9635,5826],[-1,0],[0,1],[1,0],[0,-1]],[[5598,7617],[2,0],[3,1],[2,2],[1,1],[2,0],[2,0],[2,-1],[3,2],[2,2],[1,-1],[1,-2],[1,0]],[[5117,6286],[0,-10],[0,-15],[0,-17],[0,-15],[0,-18],[0,-14],[0,-17],[0,-17],[-1,-2],[0,-10],[0,-12],[-2,-13],[-3,-10],[-1,-9],[-1,-5],[-1,-3],[0,-3],[-1,-5],[-1,-3],[0,-1],[-3,-2],[-6,-9],[0,-8],[-6,2],[-6,2],[-1,0],[-1,-1],[0,-4],[-9,0],[-7,-1],[-9,0],[-7,-1],[-8,-1],[-7,-1],[-5,-8],[-5,-8],[-7,-2],[-7,2],[-5,0],[-1,-1],[0,-3]],[[4683,5898],[0,5],[-1,3],[-1,1],[1,4],[0,9],[0,3],[1,6],[-1,3],[0,2],[-2,4],[-1,4],[-1,4],[0,3],[-2,5],[-1,1],[-2,0],[0,-1],[-1,-3],[-1,0],[-1,3],[-1,2],[0,2],[-2,4],[-2,7],[0,6],[2,3],[0,2],[0,3],[0,3],[-1,3],[0,5],[0,8],[-2,4],[-1,3],[-2,3],[-1,5],[0,6],[1,5],[-3,9]],[[4658,6037],[5,-4],[1,1],[2,3],[2,4],[2,6],[1,8],[0,7],[1,6],[1,4],[2,5],[2,4],[3,3],[1,0],[3,-5],[5,-11],[5,-7],[1,-5],[2,0],[2,8],[2,7],[1,1],[3,1],[3,0],[2,0],[4,-1],[2,-1],[2,-1],[5,-1],[6,2],[4,2],[4,1],[0,3],[0,4],[1,3],[1,2],[1,1],[0,-9],[1,-1],[4,-1],[5,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[6,0],[6,0],[5,0],[2,17],[1,16],[2,13],[-5,9],[-3,7],[-1,14],[0,14],[-1,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,15],[-1,14],[-1,14],[0,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,14],[-1,15],[-1,14],[0,14],[-1,15],[-1,14],[-1,14],[-1,15],[0,14],[-1,14],[-1,15],[-1,14],[-1,14],[0,15],[-1,14],[-1,14],[-1,13],[9,0],[9,0],[9,0],[13,0],[10,1]],[[5404,7249],[-1,-2],[-3,0],[-2,3],[0,6],[3,-1],[2,-4],[1,-2]],[[5397,7259],[-2,-1],[-1,2],[-1,1],[3,1],[1,-1],[0,-2]],[[7727,5756],[-2,-3],[0,5],[3,4],[2,1],[-1,-3],[-1,-3],[-1,-1]],[[7727,5815],[3,-10],[-1,-2],[0,-1],[-1,1],[0,5],[-2,4],[-2,-1],[1,4],[1,1],[1,-1]],[[7737,5815],[-1,0],[-1,0],[0,1],[1,6],[1,-7]],[[7728,5845],[-1,-1],[0,1],[0,5],[1,5],[1,6],[1,1],[0,-3],[-1,-7],[0,-4],[-1,-3]],[[7737,5860],[-1,-12],[-2,2],[-2,7],[1,2],[-1,4],[4,1],[1,-4]],[[7724,5857],[0,-3],[-2,3],[0,10],[1,-6],[1,-1],[0,-3]],[[7736,5870],[-1,-1],[-1,10],[0,1],[2,-5],[2,-3],[-1,-1],[-1,-1]],[[7725,5884],[0,-1],[-1,1],[-2,4],[1,3],[0,1],[1,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-2]],[[7723,5897],[0,-2],[-1,-4],[-2,3],[0,1],[1,3],[2,-1],[0,1],[0,-1]],[[7733,5909],[1,-1],[0,-6],[-2,-7],[-1,-1],[-1,0],[1,10],[-1,6],[0,4],[2,-2],[1,-3]],[[7730,5938],[0,-9],[-1,4],[-1,6],[1,4],[0,1],[0,-1],[1,-2],[0,-3]],[[7633,6095],[-1,-1],[-1,1],[2,7],[1,-3],[-1,-4]],[[7624,6102],[-2,-5],[-1,8],[3,5],[2,4],[1,3],[1,-3],[-2,-8],[-2,-4]],[[7710,6120],[-1,-1],[-2,4],[0,9],[1,2],[1,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-8]],[[7602,6260],[-1,-1],[-3,5],[-2,7],[4,1],[3,-2],[0,-3],[0,-5],[-1,-2]],[[7602,6310],[4,-4],[1,0],[2,-3],[0,-1],[0,-3],[-1,-2],[-3,-2],[-1,2],[-1,5],[-2,3],[-1,2],[2,3]],[[7596,6330],[1,-8],[-2,3],[-1,4],[0,4],[2,-3]],[[7583,6331],[0,-5],[-1,2],[-2,8],[0,5],[1,-3],[2,-7]],[[7780,6354],[-3,4],[-1,2],[-2,0],[-2,-2],[-1,-3],[-2,0],[-2,-1],[-3,2],[-2,1],[0,-1],[1,-5],[0,-4],[0,-3],[-1,-1],[-2,-2],[-1,-1],[-2,0],[-2,2],[-2,0],[-2,-1],[-1,-1],[0,-2],[-1,-10],[-1,-3],[-1,-2],[-1,-1],[-2,1],[-1,0],[-8,-4],[-1,-1],[-2,0],[-2,0],[-2,0],[-3,4],[-2,1],[-1,-2],[-1,-5],[-2,-4],[-3,-7],[0,-12],[0,-7],[-2,-8],[-1,-4],[2,-18],[-1,-2],[-2,-1],[-2,-2],[-2,-2],[-1,0],[-2,1],[-1,0],[0,-1],[2,-8],[2,-3],[2,0],[1,-1],[0,-2],[1,-4],[2,-8],[0,-6],[-1,-6],[0,-2],[1,-1],[2,-6],[3,-8],[4,-10],[3,-7],[3,-6],[5,-9],[1,-5],[0,-9],[1,-6],[1,-4],[1,-3],[2,-11],[1,-1],[4,6],[1,-1],[0,-2],[0,-3],[-1,-4],[-1,-3],[-6,-8],[-1,-6],[0,-10],[0,-12],[0,-9],[0,-2],[-1,-1],[-2,0],[-3,-4],[-2,-1],[-1,-1],[-1,-2],[-1,-4],[1,-10],[1,-9],[3,-7],[2,-5],[2,-8],[2,-6],[4,-7],[6,-11],[3,-6],[2,-7],[1,-6],[1,-8],[0,-5],[0,-15],[-1,-3],[-1,-4],[1,-5],[1,-4],[0,-4],[1,-8],[2,-5],[3,-4],[0,-2],[0,-5],[1,-4],[0,-5],[1,-7],[2,-6],[2,-18],[0,-1],[-1,-4],[-1,-3],[-1,-1],[-1,-4],[-3,-9],[-4,-17],[-5,-10],[-4,-8],[-3,-4],[-1,-3],[0,-2],[1,-4],[0,-7],[-1,-5],[-1,-5],[0,-4]],[[7741,5771],[-1,-1],[-3,-8],[-1,4],[-1,4],[1,10],[-2,19],[1,2],[1,1],[2,8],[2,7],[0,8],[2,6],[0,5],[0,6],[0,5],[0,4],[1,5],[3,3],[-1,1],[-1,2],[-3,-3],[-2,1],[0,4],[0,3],[0,3],[2,2],[0,6],[-1,4],[1,6],[-2,0],[-1,1],[1,3],[1,3],[-1,5],[1,6],[0,7],[-1,6],[0,5],[-1,8],[-1,10],[-2,7],[-2,11],[-5,15],[0,6],[0,5],[-1,3],[-1,-19],[-1,4],[-1,10],[-1,5],[1,10],[-3,10],[0,8],[-2,11],[0,2],[3,-2],[-2,6],[-2,-1],[-2,7],[0,18],[-2,7],[1,8],[-2,25],[-3,9],[1,7],[0,6],[0,12],[1,3],[2,3],[-2,-1],[-1,-1],[-3,0],[-4,-1],[-1,9],[-2,4],[-1,9],[-1,10],[0,1],[-3,4],[0,3],[-3,6],[-3,5],[0,-3],[1,-2],[-1,-6],[1,-10],[-1,-7],[-2,-8],[-1,-4],[-4,-8],[-3,-3],[-2,-1],[-2,1],[-2,5],[-1,3],[0,6],[-1,1],[-1,0],[2,-8],[-1,-4],[3,-7],[-1,-2],[-4,-4],[-2,1],[-1,-1],[0,-3],[-1,-2],[-7,-5],[-1,-5],[-1,-6],[-3,-8],[-5,-7],[-1,1],[-1,1],[0,7],[1,7],[0,6],[-1,-4],[-3,-9],[-1,-3],[-3,1],[-3,-1],[-2,9],[0,4],[0,2],[0,3],[0,3],[-1,-5],[0,-4],[-1,-3],[-4,-4],[0,5],[-1,4],[1,4],[0,6],[1,9],[0,3],[0,4],[-1,-5],[0,-5],[-1,-2],[-1,-1],[-3,-6],[-1,-5],[-4,-5],[-2,0],[-1,7],[2,22],[1,3],[1,4],[1,13],[2,5],[0,11],[1,2],[2,8],[1,15],[-1,7],[-2,7],[-2,22],[-4,18],[-1,6],[-2,7],[2,0],[-4,6],[-1,3],[-1,15],[1,8],[-1,-1],[-1,-5],[-1,-2],[0,-9],[0,-2],[-1,-4],[-3,4],[-3,4],[-3,9],[-3,10],[1,2],[2,0],[4,-7],[2,-2],[2,2],[2,3],[1,7],[-1,2],[-2,1],[-1,2],[-2,4],[0,2],[-1,3],[-2,2],[-1,3],[1,4],[1,4],[-3,0],[-4,5],[-1,2],[-1,1],[-3,1],[-3,-2],[1,-8],[0,-3],[-2,1],[-3,12],[1,3],[1,3],[-1,1],[-1,-1],[1,12],[0,1],[-1,-3],[-1,-4],[-3,-7],[-1,1],[-1,2],[1,4],[1,1],[1,2],[-2,5],[-1,3],[-2,5],[-1,0],[1,-6],[0,-9],[-3,10],[-7,14],[-1,4]],[[5533,7691],[0,-3],[0,-2],[3,-2],[3,-4],[4,-7],[1,-2],[2,-1],[3,-3],[2,-1],[2,-1],[7,-6],[2,-2],[2,-3],[1,-2],[0,-1]],[[5537,7595],[-5,5],[-1,6],[-7,11],[-7,8],[0,1],[0,1],[0,1],[-1,1],[-1,-1],[-1,0]],[[7439,8015],[3,1],[1,1],[1,2],[3,2],[0,2],[0,5],[2,4],[4,1],[2,1],[1,-1],[3,1],[2,0],[2,-1],[1,-1],[3,0],[1,2],[0,3],[1,0],[1,-2],[1,-1],[1,-1],[3,2],[1,2],[1,3],[1,2],[2,-1],[2,0],[3,3],[3,2],[2,1],[0,2],[-1,5],[0,4],[3,3],[4,0],[3,2],[0,5],[2,1],[1,1],[3,0],[3,2],[1,1],[5,3],[3,1],[2,2],[1,2],[3,1],[2,3],[3,3],[1,0],[5,2],[1,0],[1,1],[3,0],[0,3],[3,2],[2,1],[1,2],[2,3],[2,2],[5,0],[4,0],[2,0],[2,4],[1,3],[0,2],[2,0],[2,-3],[1,-2],[3,-2],[1,-3],[2,0],[1,2],[1,4],[3,0],[2,0],[1,-2],[0,-2],[1,-4],[2,-2],[4,0],[1,0],[3,0],[3,-1],[4,-1],[1,0],[4,0],[5,-1],[2,1],[5,-1],[1,-3],[1,-6],[1,-6],[0,-5],[1,-2],[2,-1],[1,-2],[2,-2],[1,-4],[2,0],[1,1],[3,0],[3,0],[2,-2],[1,-2],[2,-2],[2,0],[4,1],[2,-1],[1,-1],[3,0],[1,1],[4,2],[2,2],[2,0],[1,-1],[1,-2],[2,1],[0,2],[2,0],[1,-1],[3,-2],[3,-3],[1,0],[3,1],[1,0],[1,-1],[2,-1],[1,1],[2,1],[7,-2],[2,-3],[1,-2],[1,-2],[2,-2],[5,1],[1,2],[4,4],[1,4],[2,1],[2,1],[1,0],[2,0],[3,3],[2,1],[2,3],[1,2],[1,4],[1,3],[1,4],[1,7],[1,4],[-1,2],[-1,2],[-3,0],[-1,2],[-2,3],[-1,3],[-1,4],[0,3],[0,2],[-1,2],[-2,3],[0,2],[0,4],[2,7],[0,3],[0,2],[0,1],[1,4],[1,2],[1,4],[2,2],[3,0],[1,1],[0,5],[1,3],[1,2],[1,3],[8,4],[4,6],[1,3],[1,7],[1,3],[2,-1],[2,-4],[2,0],[2,-2],[7,-4],[3,-2],[2,0],[3,-1],[2,-3],[4,-4],[3,-1],[5,-1],[7,0],[2,-1],[5,-3],[5,-3],[5,-3],[4,-2],[2,-2],[2,-2],[3,1],[3,0],[7,-2],[4,-3],[4,-1],[1,-3],[0,-3],[0,-2],[0,-6],[1,-4],[0,-4],[1,-4],[0,-5],[0,-2],[1,-1],[1,-3],[0,-3],[-1,-2],[1,-3],[1,-2],[2,0],[2,-1],[2,-4],[4,-4],[2,-1],[2,-2],[5,-2],[4,-1],[2,-1],[2,-4],[3,-1],[2,-1],[4,-1],[2,1],[3,1],[1,0],[3,-1],[3,0],[3,0],[2,3],[3,4],[3,1],[4,1],[2,1],[8,3],[4,0],[2,2],[2,2],[4,1],[4,-2],[4,-1],[5,-1],[4,-2],[2,-2],[4,-2],[4,1],[6,1],[3,-1],[4,-4],[3,-3],[3,-6],[2,-3],[3,-3],[3,0],[8,0],[4,-2],[4,0],[1,-2],[-1,-4],[1,-6],[-1,-3],[1,-2],[1,-1],[1,-3],[2,-1],[3,-3],[6,-7],[3,-3],[2,-1],[4,0],[5,0],[9,0],[6,-2],[2,-1],[6,-2],[7,-2],[5,-2],[4,3],[3,0],[2,-2],[3,-3],[2,0],[4,2],[10,8],[4,3],[2,-1],[3,1],[1,1],[5,1],[3,0],[2,1],[5,1],[8,5],[3,1],[6,-2],[3,1],[3,3],[4,3],[1,4],[2,6],[4,4],[3,4],[4,4],[4,3],[5,3],[5,6],[4,3],[2,1],[3,-2],[4,0],[4,0],[1,-1],[4,-3],[4,-2],[2,-5],[5,-6],[3,-2],[2,-1],[4,-1],[4,0],[2,1],[3,3],[6,3],[2,0],[4,-2],[6,-3],[2,-2],[1,-3]],[[9034,5999],[-1,-2],[-1,0],[-1,1],[0,2],[2,1],[1,0],[0,-2]],[[9045,6046],[-1,-3],[-1,5],[0,2],[1,1],[1,0],[0,-5]],[[9048,6055],[0,-1],[-2,0],[0,1],[1,5],[2,3],[1,0],[-1,-2],[0,-3],[-1,-3]],[[9047,6125],[-1,0],[-1,0],[0,1],[-1,1],[2,0],[1,-1],[0,-1]],[[9048,6225],[-1,-1],[2,6],[0,1],[1,-3],[-2,-3]],[[9047,6264],[-1,-2],[-1,2],[0,3],[1,0],[1,-1],[0,-2]],[[5913,3637],[-3,0],[-5,0],[-3,0],[-4,0],[-4,1],[-3,0]],[[5891,3638],[0,18],[-1,4],[0,6],[-1,4],[1,4],[0,6],[0,5],[-3,3],[0,1]],[[5887,3689],[-1,4],[0,6],[2,8],[0,16],[0,6],[0,11],[0,13],[0,12],[0,10],[-1,5],[0,2],[-1,6],[-2,11],[-1,9],[-2,5],[-1,3],[-1,4],[-2,7],[-1,4],[-1,4],[0,8],[-2,15],[-1,11],[-2,12],[-1,8],[0,1],[0,3]],[[5869,3893],[3,6],[4,9],[5,10],[4,8],[4,8],[5,11],[5,10],[1,1],[0,1],[-2,9],[4,11],[0,7],[0,7],[0,3],[1,3],[4,5],[3,9],[2,8],[4,14],[0,3],[0,3],[-1,5],[-2,7],[-2,6],[-1,10],[1,9],[1,5],[0,2],[-1,3],[-1,2],[-2,1],[0,4],[0,4],[0,2],[4,4],[1,2],[0,2],[0,4],[1,8],[2,7],[0,3],[-1,2],[0,5],[0,6],[0,19],[1,18],[-1,11],[-2,12],[0,9],[1,7],[1,3],[-2,1],[-2,0],[-2,1],[-3,5],[-5,5],[-6,3],[-8,2],[-7,12],[-6,2],[-2,1],[-5,8],[-8,1],[-9,0],[-5,0],[-1,1],[0,11],[0,9]],[[5844,4283],[-1,8],[-1,9],[-1,3],[-1,6],[-1,7],[0,3],[0,1],[6,5],[3,3],[3,2],[7,4],[6,3],[6,4],[5,3],[3,3],[3,2],[7,5],[2,1],[4,3],[2,1],[8,5],[9,6],[3,3],[6,4]],[[5922,4377],[1,-2],[4,-14],[3,-9],[4,-7],[1,2],[2,1],[6,1],[2,0],[2,3],[3,1],[3,1],[1,-1],[4,-10],[0,-8],[1,-11],[0,-5],[0,-7],[0,-9],[-3,-11],[-1,-5],[-1,-8],[-2,-4],[-1,-3],[0,-3],[1,-3],[2,-5],[1,-3],[0,-3],[0,-4],[0,-3],[1,-2],[3,-2],[2,-7],[4,-7],[5,-12],[2,-3],[2,-1],[1,-4],[-1,-4],[-1,-2],[0,-4],[1,-2],[1,-1],[2,0],[2,1],[1,1],[-1,17],[-1,9],[-1,4],[-1,1],[1,3],[1,8],[2,7],[1,3],[1,2],[6,2],[3,2],[2,2],[1,6],[0,16],[1,15],[-1,9],[1,13],[1,8],[0,2],[-1,11],[-4,12],[-6,15],[-3,8],[-3,9],[-7,15],[-3,5],[-2,2],[-5,2],[-1,3],[-1,4],[-1,9],[0,6],[-1,10],[-1,15],[0,5],[-2,11],[-1,10],[0,3],[0,3],[3,8],[1,5],[1,3],[2,8],[0,4],[1,2],[5,1],[4,0]],[[5971,4517],[6,0],[6,0],[1,-1],[2,-1],[1,1],[2,1],[2,3],[2,4],[4,0],[5,-5],[2,-4],[1,-3],[3,-2],[6,-1],[4,2],[3,4],[3,2],[3,1],[2,-2],[1,-3],[3,-2],[5,-2],[4,2],[5,6],[3,5],[1,6],[1,4],[1,1],[2,1],[5,0],[4,-2],[5,-6],[3,4],[5,7],[5,4],[5,0],[5,2],[3,5],[3,3],[4,2],[3,2],[5,6],[5,7],[5,8],[3,5]],[[6123,4581],[2,-6],[2,-5],[-1,-3],[-2,-3],[3,-4],[-2,-6],[0,-4],[0,-1],[1,-3],[-2,-6],[-2,-5],[0,-4],[1,-7],[0,-12],[1,-10],[1,-6],[0,-4],[-1,-6],[1,-11],[0,-5],[-1,-6],[2,-2],[1,-6],[-1,-7],[0,-4],[-3,-4],[0,-2],[0,-3],[3,0],[0,-4],[0,-4],[0,-6],[0,-4],[1,-5],[-1,-5],[0,-4],[0,-5],[1,-13],[0,-16],[0,-2],[2,-2],[1,-1],[0,-4],[-2,-6],[0,-4],[0,-5],[3,7],[1,0],[1,-3],[0,-3],[0,-2],[0,-4],[1,-5],[0,-4],[-2,-3],[-2,-5],[0,-5],[0,-3],[-2,-1],[0,-2],[1,-4],[0,-4],[-3,-12],[-7,-17],[-3,-6],[-2,-7],[0,-2],[-1,-3],[-3,-9],[-3,-1],[-2,-3],[1,-8],[-2,-2],[-4,-6],[-11,-12],[-1,-3],[-3,-8],[-3,-2],[-2,-2],[-4,-1],[-1,1],[-1,0],[-1,-2],[-7,-5],[-7,-4],[-2,-2],[-1,-3],[-6,-4],[-9,-10],[-7,-10],[-5,-10],[-2,-1],[-2,-4],[0,-5],[-1,-2],[-4,-11],[-6,-12],[-1,-3],[-2,-7],[0,-4],[-3,-2],[-1,5],[-1,-9],[-2,0],[-1,2],[-4,-5],[-4,-4],[-5,-10],[-8,-19],[-12,-18],[-1,-1],[-1,0],[-4,7],[-2,0],[2,-4],[1,-3],[0,-6],[0,-9],[-2,-18],[0,-4],[2,-6],[3,-6],[3,-8],[4,-22],[0,-12],[4,-14],[0,-7],[2,-16],[0,-12],[-1,-8],[2,-4],[1,3],[0,5],[0,8],[1,4],[1,-1],[1,-3],[0,-4],[1,-3],[0,-4],[-2,-16],[1,-7],[2,-11],[-3,-13],[-3,-30],[0,-5],[1,-2],[1,-1],[1,4],[1,0],[1,-2],[-2,-14],[-1,-6],[-5,-15],[-3,-7],[-5,-6],[-10,-10],[-22,-14],[-8,-7],[-5,-4],[-11,-13],[-5,-9],[-2,-10],[-1,-5],[-2,-6],[1,-5],[2,-4],[2,-2],[1,-3],[1,-1],[1,8],[1,2],[1,0],[-1,-9],[-1,-34],[0,-1]],[[5962,4492],[-1,1],[-1,1],[-1,0],[0,-2],[1,-3],[1,0],[1,3]],[[5964,4486],[1,2],[0,1],[0,2],[-1,1],[-1,0],[-1,-2],[0,-3],[1,-1],[1,0]],[[4545,6319],[-2,-6],[-1,2],[0,4],[1,5],[1,3],[2,1],[-1,-9]],[[4658,6037],[-3,4],[-2,5],[-2,4],[-3,3],[-2,2],[-1,4],[-1,2],[-2,1],[0,1],[1,1],[-1,3],[-2,7],[-1,3],[-2,-1],[-1,1],[0,2],[0,2],[-2,2],[-1,0],[-2,5],[-1,9],[-1,7],[-2,5],[-1,2],[-1,0],[0,1],[-1,1],[-1,1],[-2,-2],[-2,1],[0,2],[-2,0],[-1,-2],[-2,1],[-1,3],[-1,3],[-1,3],[-3,6],[-6,10],[-6,4],[-7,0],[-4,0],[-1,1],[-1,0],[-1,-1],[-1,-1],[-1,1],[0,-3],[-3,-1],[-5,0],[-3,-2],[-3,-2],[-4,-2],[-6,1],[-3,1],[-1,1],[-2,1],[-2,-1],[-1,-5],[-2,-8],[-1,-5],[-1,-1],[-1,-6],[-1,-10],[-1,-5]],[[4540,6096],[0,26],[2,10],[0,8],[3,19],[4,15],[4,20],[1,20],[0,19],[-1,18],[-2,11],[-2,16],[-2,9],[-5,8],[-1,4],[1,2],[3,1],[2,6],[-4,-3],[4,19],[2,12],[-1,8],[1,5],[-3,11],[-3,13],[-1,2],[-2,2],[0,-4],[-1,-2],[-1,1],[-3,10],[-4,16],[-2,2],[-1,-2],[-1,-2],[-1,-14]],[[4526,6382],[0,6],[0,6],[1,8],[1,10],[4,0],[6,0],[7,0],[6,0],[6,0],[7,0],[6,0],[6,0],[7,0],[6,0],[7,0],[6,1],[6,0],[7,0],[6,0],[6,0],[7,0],[4,0],[0,7],[0,6],[-1,8],[0,9],[0,8],[-1,7],[0,8],[0,7],[0,7],[-1,3],[-1,8],[0,3],[0,4],[1,4],[3,7],[3,5],[5,6],[3,4],[2,1],[5,2],[4,3],[4,4],[2,1],[0,7],[0,7],[0,8],[0,7],[0,8],[0,8],[0,8],[0,8],[0,8],[0,7],[0,8],[0,8],[0,8],[0,8],[0,8],[0,8],[0,7],[0,8],[0,7],[4,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[5,0],[5,0],[6,0],[5,0],[5,0],[0,7],[0,9],[0,13],[0,13],[0,11],[0,12],[0,9]],[[3273,6148],[0,-3],[-2,1],[0,3],[1,3],[1,0],[0,-4]],[[6601,4004],[-4,-2],[-4,1],[-1,3],[0,1],[1,1],[0,4],[0,7],[1,2],[2,3],[1,5],[2,3],[2,0],[2,-6],[2,-6],[-1,-7],[-1,-2],[-1,-4],[-1,-3]],[[5922,4377],[-2,4],[-1,-1],[-2,-3],[-1,-1],[0,1],[-1,2],[-1,5],[-2,4],[-1,1],[-1,2],[0,2],[1,1],[-1,1],[0,2],[-3,3],[0,1],[2,2],[2,3],[1,3],[1,5],[1,6],[1,2],[0,4],[0,4],[1,6],[0,5],[-1,2],[0,3],[0,6],[2,4],[6,5],[4,3],[1,2],[2,3],[0,4],[0,1],[-4,0],[0,1],[-3,11],[1,13],[1,5],[0,6],[-1,5],[-1,2],[-1,2],[1,7],[1,1],[2,9],[1,5],[-2,4],[-1,6],[0,4],[-1,1],[1,3],[2,2],[1,1],[2,1],[5,11],[0,2],[-1,4],[-2,5],[0,3],[0,6],[-1,2],[-3,5],[-2,5],[0,4],[1,6],[-1,3],[-2,3],[-1,4],[0,3],[-2,2],[-1,0],[-1,-2],[-1,0],[-1,1],[0,2],[0,3],[-1,3],[-1,2],[0,2]],[[5914,4642],[1,1],[5,-6],[2,0],[3,-1],[3,-6],[1,0],[2,0],[4,1],[2,-1],[3,-3],[1,0],[1,0],[1,1],[0,1],[-1,4],[1,2],[1,2],[2,-3],[7,-11],[0,-1],[4,-11],[1,-5],[0,-2],[2,-10],[0,-5],[0,-3],[0,-3],[0,-4],[0,-1],[2,-6],[0,-5],[0,-5],[0,-4],[-1,-7],[-1,-3],[1,-2],[1,-3],[1,-3],[1,-4],[1,-4],[0,-1],[1,0],[1,-1],[2,-2],[1,-4],[0,-5],[1,-2]],[[8093,5323],[-1,-1],[-1,2],[0,18],[1,1],[1,-3],[0,-8],[0,-7],[0,-2]],[[7894,5341],[-1,0],[-1,0],[0,2],[1,5],[0,1],[1,-5],[0,-3]],[[7814,5356],[-2,-1],[0,1],[0,2],[1,2],[1,-1],[0,-3]],[[8267,5424],[1,2],[0,3],[1,0],[1,0],[4,-4]],[[7785,5489],[-1,-2],[-2,1],[1,10],[1,1],[2,-2],[0,-2],[-1,-6]],[[7773,5556],[2,-6],[-1,-3],[-1,0],[-1,0],[-1,-2],[-1,0],[-1,4],[-2,2],[0,2],[2,1],[1,-1],[2,2],[1,1]],[[7835,5543],[5,-2],[2,-2],[5,-18],[8,-12],[3,-5],[2,-2],[3,-7],[3,-8],[6,-24],[1,-10],[0,-16],[-1,-24],[-2,-12],[1,-6],[2,-8],[-1,-9],[1,-6],[0,-19],[1,-6],[1,-3],[8,-12],[0,-4],[4,-14],[7,-31],[2,-14],[0,-4],[-1,-1],[-2,-2],[-2,3],[0,2],[0,3],[-1,2],[-1,3],[-1,2],[0,-4],[0,-5],[-2,-1],[-3,2],[-3,-2],[-4,-6],[-2,-1],[-2,6],[-1,4],[-1,3],[-13,14],[-4,4],[-5,10],[-11,12],[-8,12],[-3,7],[-7,6],[-3,8],[-1,1],[-2,3],[2,7],[-1,8],[-1,6],[-5,13],[-3,9],[-4,8],[-2,5],[-2,6],[1,2],[1,2],[-1,4],[-3,7],[-1,9],[0,16],[-4,22],[-3,32],[0,11],[0,11],[-3,12],[-3,8],[-1,7]],[[7780,5555],[1,3],[0,8],[1,2],[1,1],[1,0],[3,-8],[6,-5],[1,-1],[3,2],[1,-1],[1,-2],[1,-6],[1,-4],[3,0],[2,0],[0,-1],[1,-4],[0,-8],[0,-4],[-2,-6],[-1,-5],[1,-2],[2,-3],[1,-3],[1,1],[1,1],[1,4],[1,3],[4,4],[4,3],[1,0],[0,-2],[2,-4],[1,-1],[1,-1],[2,1],[2,2],[1,5],[1,4],[3,7],[0,5],[1,3]],[[8044,5301],[2,-8],[1,-2],[4,-6],[3,-2],[4,-1],[4,-1],[1,1],[1,1],[2,-1],[8,-9],[2,-2],[4,1],[1,-1],[4,-7],[2,0],[2,0],[-3,3],[-2,2],[-1,5],[1,4],[2,3],[1,3],[0,9],[1,5],[1,5],[1,4],[-2,3],[0,6],[0,5],[1,3],[2,-2],[1,-2],[2,0],[1,1],[0,2],[0,5],[0,8],[2,6],[3,4],[3,2],[11,4],[17,9],[5,3],[2,2],[1,2],[3,8],[5,13],[3,10],[8,15],[6,14],[1,3],[1,7],[0,4],[-1,4],[1,1],[1,1],[1,0]],[[8198,5466],[6,2],[2,2],[2,5],[1,2],[1,6],[-3,3],[-2,5],[0,5],[4,8],[1,3],[1,-4],[2,0],[1,-1],[2,1],[2,4],[1,7],[4,9],[1,7],[1,7],[10,22],[1,4],[6,23],[1,0],[2,-2],[0,-7],[0,-3],[-1,-5],[-1,-5],[1,0],[3,3],[3,8],[1,7],[2,3],[3,-1],[0,-2],[0,-5],[0,-2],[1,-7],[3,-3],[3,-3],[3,-3],[1,-2],[1,-3],[0,-4],[1,-5],[-3,-4],[1,-7],[0,-5],[-1,-3],[-3,-3],[9,3],[2,2],[3,4],[2,-4],[1,-7],[-1,-1],[-4,-3],[0,-1],[1,-4],[2,1],[3,2],[3,4],[1,0],[2,-1],[3,-2],[1,-2],[2,-3],[0,-5],[4,-2],[7,-7],[1,-1],[1,0],[4,1],[1,-1],[1,-3],[0,-3],[0,-4],[0,-3],[-1,-2],[-3,-3],[-6,-5],[-6,-3],[-4,0],[-4,3],[-2,-1],[-2,-1],[-2,-9],[4,-9],[7,-10],[0,-2],[0,-3],[-1,-2],[-1,-1],[-4,-1],[-4,-2],[-3,-1],[-3,-2],[-3,0],[-4,5],[-1,0],[-2,-2],[-1,-6],[-1,-2]],[[8253,5597],[-2,-3],[0,3],[0,5],[2,4],[4,1],[0,-3],[0,-4],[-1,-2],[-3,-1]],[[5649,4168],[6,2],[6,2],[6,3],[5,1],[2,1],[12,-2],[6,-2],[2,-1],[2,-4],[5,-9]],[[5554,3757],[0,-24],[0,-26],[0,-26],[0,-25],[0,-26],[0,-26],[0,-25],[0,-26],[0,-8],[-2,0],[-6,-3],[-4,-4],[-1,-5],[-2,-3],[-3,-1],[-1,-3],[0,-4],[-1,-3],[-2,-2],[-4,1],[-5,3],[-7,1],[-8,-2],[-6,1],[-3,3],[-4,2],[-4,1],[-2,1],[-5,3],[-1,4],[0,4],[-2,3],[0,3],[1,2],[0,4],[0,5],[-2,2],[-1,0],[-2,2],[0,3],[-1,3],[-3,3],[-3,-2],[-2,-3],[-1,-6],[-1,-2],[0,-5],[0,-3],[-1,-3],[-1,-1],[-1,0],[-2,-1],[-4,-5],[-1,-3]],[[5456,3535],[-3,5],[-9,18],[-3,4],[-5,11],[-10,33],[-2,7],[-2,16],[-2,12],[0,7],[1,4],[-1,5],[-1,5],[-4,6],[-1,21],[-2,13],[0,11],[-1,10],[0,7],[1,12],[-2,14],[-4,14],[-4,20],[0,9],[0,23],[-1,10],[1,11],[-2,12],[0,6],[1,5],[0,-2],[1,0],[1,6],[0,6],[-2,15],[-4,15],[-9,24],[-3,9],[-1,8],[-11,32],[-5,23],[-3,19],[-3,9],[-16,64],[-4,10],[-7,12],[-1,4],[-3,11],[-4,16],[-2,14],[0,17],[1,12]],[[9653,3881],[-1,-2],[-1,0],[-1,1],[0,1],[0,4],[3,-2],[0,-2]],[[9666,3949],[1,-1],[3,1],[-1,-10],[-3,-2],[-1,0],[-1,2],[-2,2],[0,3],[-1,8],[3,1],[1,2],[0,-2],[1,-2],[0,-2]],[[9649,3965],[-1,0],[-2,4],[-4,2],[-2,3],[-1,5],[2,1],[2,6],[-1,2],[-3,0],[0,2],[5,3],[1,-2],[1,-1],[0,-10],[2,-2],[2,-7],[0,-2],[-1,-4]],[[9625,3992],[-1,-1],[2,5],[0,4],[0,6],[0,2],[2,0],[1,-2],[-2,-2],[0,-2],[0,-4],[0,-1],[0,-3],[-2,-2]],[[9560,4018],[3,-4],[4,2],[4,-6],[11,-17],[3,-4],[3,-1],[1,-3],[2,-4],[2,-3],[1,-3],[0,-3],[1,-2],[4,-6],[2,-5],[3,-3],[1,-3],[2,-1],[2,-3],[3,-3],[7,-8],[5,-9],[2,-5],[3,-5],[4,-3],[3,-5],[2,-9],[-1,-4],[-2,-2],[-2,0],[-1,-1],[-6,6],[-1,1],[-2,0],[-1,1],[0,2],[-4,3],[-3,3],[-1,3],[0,3],[-1,2],[-5,3],[-3,3],[-2,4],[-3,4],[-6,6],[-2,2],[-3,3],[-6,11],[-3,3],[-2,5],[-5,12],[-3,5],[-3,4],[-2,5],[-2,6],[-4,9],[0,4],[0,4],[-1,2],[-2,2],[0,2],[0,4],[0,2],[4,-6]],[[9442,4071],[0,-1],[0,9],[0,4],[1,-7],[-1,-5]],[[5416,6508],[3,-33],[2,-29],[0,-18],[0,-4],[1,-4],[2,-3],[9,-26],[-2,-5],[1,-8],[3,-4],[7,-15],[1,-3],[-1,-3],[-5,-18],[0,-5],[-1,-23],[-1,-17],[-1,-23],[-1,-27],[-1,-23],[-2,-30],[-1,-29],[-7,-16],[-13,-28],[-10,-23],[-6,-15],[-10,-30],[-5,-19],[-3,-11],[-2,-4],[2,-14],[2,-25]],[[5377,5973],[-5,0],[-2,-2],[-4,-5],[-4,-3],[-5,-5],[-3,-4],[-3,-3],[-4,-7],[-1,-6],[-4,-1],[-6,1],[-3,6],[-9,6],[-5,2],[-3,1],[-12,1],[-14,-2],[-6,-3],[-2,-1],[-3,-4],[-4,-4],[-8,-18],[-12,0],[-7,2],[-5,3],[-9,9],[-10,13],[-4,2],[-3,1],[-1,0],[-12,-13],[-2,0],[-3,-1],[-2,-4],[-1,-1],[-2,-1],[-2,1],[-2,2],[-2,4],[-4,15],[-1,2],[-3,5],[-3,6],[-3,4],[-1,0],[-2,0],[-9,6],[-10,6],[-2,-1],[-2,-1],[-3,-5],[-4,-1],[-5,1],[-3,0],[-4,-1],[-3,-2],[-4,-3],[-5,-9],[-1,-1],[-1,-1],[-2,-23],[-1,-7],[-3,-9],[-5,-9],[-3,-5],[0,-8],[-1,-11],[0,-8],[1,-6],[-1,-2],[0,-3],[0,-3],[1,-2],[0,-2],[0,-1],[-2,-3]],[[9664,3512],[1,0],[0,-1],[0,-1],[0,-1],[0,-1],[-1,1],[-1,0],[0,1],[0,1],[1,0],[0,1],[-1,0],[0,1],[1,-1]],[[5202,5438],[-2,-1],[-2,0],[2,8],[1,-2],[2,-1],[-1,-4]],[[5377,5973],[5,-12],[4,-14],[4,-10]],[[5237,5458],[-1,-2],[-2,1],[-1,4],[-2,1],[-2,5],[-1,-1],[3,-14],[-1,-6],[-8,0],[-6,-2],[-4,0],[-2,3],[-1,5],[-1,-1],[0,-3],[-1,-2],[-5,0],[-2,3],[-2,5],[-2,1],[0,-1],[2,-4],[0,-6],[-4,-7],[-2,0],[-2,3],[-1,4],[0,7],[-1,5],[-1,0],[1,-4],[0,-4],[0,-7],[2,-5],[-3,-2],[-1,0],[-2,0],[-1,2],[0,4],[-1,2],[0,-8],[-2,-1],[-1,0],[-5,-1],[-1,0],[0,1],[1,3],[0,3],[-2,-3],[0,-5],[-1,-1],[-3,1],[-3,3],[-1,3],[-3,3],[-6,11],[-1,5],[-2,7],[-1,6],[-2,10],[1,1],[1,-1],[1,2],[-3,1],[0,1],[-1,4],[1,4],[2,2],[1,1],[1,2],[1,3],[-5,-4],[-4,5],[-1,3],[0,2],[2,0],[3,0],[2,2],[-1,1],[-2,0],[-1,1],[0,4],[0,-1],[-1,-3],[-3,-2],[-1,2],[-1,5],[0,2],[-1,2],[-5,13],[-7,11],[-5,7],[-9,4],[-18,0],[-1,1],[1,2],[2,1],[6,6],[-1,1],[-6,-4],[-2,0],[-3,-8],[-15,-1],[-2,0]],[[2690,6047],[-1,-2],[-1,-1],[-2,-7],[0,-1],[0,5],[-1,1],[-2,-2],[0,-2],[1,-4],[1,0],[1,-1],[3,-23],[-1,-4],[-2,-7],[-1,-6],[-2,-3],[-3,-15],[-2,-24],[2,-22],[-1,-20],[1,-4],[0,-6],[-2,-1],[-1,3],[0,4],[1,3],[0,5],[0,3],[-1,-6],[-2,-2],[-1,-1],[-1,-3],[1,-6],[2,-4],[0,-2],[0,-4],[-1,-12],[0,1],[-1,1],[-1,0],[0,-4],[0,-3],[-1,-2],[-1,-2],[1,-1],[1,-1],[2,0],[1,-6],[0,-5],[-3,-4],[0,-4],[-2,-4],[-1,-4],[0,-3],[1,-10],[2,-7],[1,-4],[2,-1]],[[2618,5821],[0,1],[-2,7],[-4,7],[-14,24],[-5,14],[-3,10],[-3,5],[-7,11],[-2,4],[-8,15],[-5,8],[-1,4],[3,4],[1,0],[1,-3],[2,-4],[1,0],[2,2],[0,1]],[[283,4085],[-3,-4],[-1,4],[1,5],[2,1],[1,-4],[0,-2]],[[3105,5883],[-1,-6],[-1,3],[0,5],[-1,2],[-1,1],[-1,2],[1,2],[4,-4],[0,-5]],[[3251,6192],[0,-2],[-1,0],[0,2],[0,2],[0,-1],[1,-1]],[[5093,8143],[2,1],[4,0],[4,-1],[4,-1],[4,2],[3,-2],[3,2]],[[5109,8164],[3,-3],[0,-1],[1,-1],[-4,-2],[-3,4],[-3,-1],[-1,2],[0,1],[3,1],[4,0]],[[5135,8241],[-3,-4],[-1,1],[-1,1],[1,3],[4,5],[0,-6]],[[5141,8254],[-5,-4],[0,1],[3,3],[2,0]],[[5117,8144],[-3,0],[-3,3],[-5,-2],[-4,2],[-3,0],[-2,2],[-2,3],[2,3],[1,0],[5,1],[4,-2],[8,-6],[1,0],[2,0],[-1,2],[-2,1],[-2,2],[-2,3],[5,0],[-1,2],[-1,2],[-5,8],[1,2],[1,5],[2,4],[1,1],[2,2],[5,8],[3,7],[2,7],[3,22],[1,3],[2,4],[2,-1],[1,-1],[5,3],[8,8],[3,7],[2,3],[10,6],[5,2],[8,0],[6,2],[7,0],[2,-4],[2,-3],[3,-1],[3,-1]],[[5166,8107],[-5,0],[-2,0],[-1,1]],[[5147,8259],[-2,-1],[-1,1],[6,2],[4,1],[1,0],[-8,-3]],[[5164,8263],[-5,-1],[-2,1],[1,1],[5,0],[1,-1]],[[5175,8266],[-3,-2],[-1,0],[0,1],[3,1],[1,0]],[[5187,8270],[-3,0],[1,1],[2,2],[1,0],[-1,-3]],[[5141,8657],[0,-6],[-3,0],[-1,3],[0,1],[0,4],[-1,4],[1,2],[1,1],[2,-4],[1,-5]],[[5137,8702],[-2,-1],[-2,1],[1,6],[1,0],[1,1],[2,-3],[-1,-4]],[[5225,8832],[-3,0],[-3,1],[-2,2],[-1,1],[4,2],[4,2],[1,-3],[1,-3],[-1,-2]],[[5235,8851],[-3,0],[-2,1],[4,3],[7,2],[1,2],[1,0],[1,-2],[0,-3],[0,-1],[-9,-2]],[[5311,8920],[-1,-2],[-3,2],[-7,-1],[-2,1],[2,3],[6,3],[3,0],[3,-4],[-1,-2]],[[5332,8964],[-2,-2],[-3,1],[-1,1],[1,3],[2,1],[3,0],[1,-1],[-1,-3]],[[5347,8980],[-2,-1],[0,3],[1,2],[2,1],[3,1],[3,0],[0,-1],[-1,-2],[-6,-3]],[[5344,8988],[-2,-1],[0,3],[2,2],[1,2],[1,2],[1,1],[3,-1],[0,-4],[-1,-3],[-5,-1]],[[5360,9093],[-4,-3],[1,6],[2,5],[3,4],[2,-2],[-1,-2],[0,-3],[0,-1],[-3,-4]],[[5385,9116],[1,-1],[5,0],[1,0],[-1,-2],[-2,-2],[-4,-1],[-2,-3],[-1,0],[-3,0],[-2,-1],[-3,-3],[-2,2],[0,-1],[-1,-2],[-1,-1],[-3,-1],[-1,6],[2,1],[1,3],[2,0],[1,0],[4,5],[4,1],[2,0],[3,0]],[[5422,9155],[3,-6],[2,-3],[-1,-7],[-4,-3],[-5,-1],[-4,1],[-2,1],[-1,2],[-1,0],[-4,-2],[-2,0],[-3,2],[-1,2],[3,4],[2,3],[4,-1],[3,-1],[1,3],[0,3],[1,1],[4,-1],[0,6],[2,1],[1,-1],[1,-1],[1,-2]],[[5437,9133],[1,-1],[3,6],[5,2],[0,2],[1,1],[0,4],[1,2],[2,1],[2,1],[1,0],[3,-2],[1,-2],[2,-5],[-1,-5],[-5,-4],[-4,-1],[-4,-5],[-2,-3],[-2,-1],[-1,0],[-1,1],[-2,0],[-2,-3],[-7,-2],[-2,0],[-1,3],[-1,0],[-3,-4],[-2,-1],[-2,0],[-3,1],[-8,-6],[-8,-1],[-2,0],[-1,4],[6,5],[4,4],[14,2],[9,10],[2,11],[2,4],[-1,2],[-3,0],[0,4],[2,4],[4,5],[3,2],[4,6],[2,1],[2,0],[3,-1],[-1,-3],[-3,-6],[-5,-6],[0,-3],[2,-3],[1,-5],[0,-5],[-4,-7],[-1,-3]],[[5486,9192],[3,-3],[1,1],[3,1],[3,-2],[1,-2],[3,0],[1,-3],[1,-3],[-2,-3],[-2,-1],[-1,-3],[1,-4],[-5,-2],[-6,-1],[-2,2],[-4,-3],[-5,-6],[-2,-1],[0,2],[-3,1],[-5,0],[1,2],[0,1],[4,1],[1,3],[-1,5],[1,3],[0,2],[2,2],[8,-1],[1,2],[-1,1],[-4,3],[1,1],[3,1],[2,1],[1,2],[0,1],[1,0]],[[5832,9204],[-6,-2],[0,2],[1,2],[1,4],[2,0],[3,-2],[1,-2],[-2,-2]],[[5577,9221],[-2,-1],[-2,-1],[-1,1],[-2,0],[-2,0],[-2,3],[0,2],[3,2],[4,2],[4,-1],[1,0],[-1,-7]],[[5534,9220],[3,-4],[2,1],[1,1],[1,0],[3,-1],[0,-3],[-4,-4],[-3,-5],[-4,-1],[-2,1],[-4,-3],[-2,-3],[-3,-4],[0,-2],[-1,-2],[-10,-1],[-4,-1],[-4,1],[-2,3],[1,1],[4,1],[0,2],[1,2],[1,0],[1,3],[2,1],[3,-1],[2,3],[1,0],[1,-2],[1,3],[-1,2],[1,1],[3,4],[2,3],[2,2],[3,0],[0,3],[0,2],[0,2],[2,5],[2,0],[1,-4],[0,-6]],[[5549,9228],[1,-1],[1,1],[2,-1],[2,-3],[2,-1],[0,-1],[-2,-2],[-3,0],[-3,0],[-1,2],[-1,3],[-3,3],[0,3],[2,0],[3,-3]],[[5655,9247],[1,-2],[0,-3],[-2,-3],[-6,-4],[0,-1],[-2,-1],[-3,-1],[-2,1],[0,3],[0,1],[-3,-1],[-2,2],[0,2],[1,1],[2,3],[4,1],[2,0],[9,6],[0,-1],[1,-3]],[[5667,9248],[-6,-2],[-3,2],[-1,2],[0,5],[0,2],[3,2],[2,-1],[0,-1],[3,-1],[3,-3],[-1,-5]],[[5651,9263],[-1,-2],[-1,-2],[-2,-2],[-7,-7],[-4,-1],[-1,-1],[-1,-1],[-5,1],[-2,-2],[-1,-1],[-3,0],[-2,0],[-6,3],[-3,3],[-2,3],[5,-1],[2,1],[3,0],[2,2],[4,0],[8,2],[3,-1],[7,6],[2,0],[3,1],[2,-1]],[[5857,9203],[1,-7],[0,-3],[0,-3],[-1,-1],[-2,0],[-5,0],[-7,3],[-4,3],[-1,0],[-1,-1],[1,-2],[0,-3],[-1,-2],[-1,-2],[-1,-2],[-2,-2],[-5,-2],[-12,-4],[-1,-1],[-4,-10],[-1,-2],[-2,-1],[-4,-2]],[[5572,9160],[-3,0],[-11,-1],[5,-5],[1,-2],[1,-3],[-1,-5],[-2,-5],[-3,-4],[-5,-3],[8,-4],[-5,-5],[-3,-2],[-3,0],[-5,2],[-12,4],[-5,2],[-5,0],[-3,0],[-11,4],[-2,-1],[-4,-1],[0,-4],[0,-8],[0,-7],[-1,-4],[-2,-2],[-4,-8],[-10,5],[-6,3],[-5,-4],[-10,-8],[-6,-15],[-3,-4],[-5,-2],[-3,-1],[-2,-5],[5,-6],[2,-4],[2,-5],[0,-4],[-1,-2],[-4,-4],[-10,-12],[-9,-13],[-4,-3],[2,-11],[-3,-3],[-7,-4],[-3,-1],[-3,-1],[-11,-1],[2,-12],[1,-5],[0,-3],[-1,-3],[-1,-5],[-2,-20],[-2,-2],[-2,-5],[-6,-13],[-6,-9],[-7,-12],[6,-4],[6,-3],[1,-5],[0,-7],[0,-5],[-2,-4],[-2,-4],[-1,-1],[-8,1],[-10,2],[-3,0],[-6,-1],[-5,-3],[-3,-2],[-1,-1],[-3,-6],[-7,-10],[-3,-4],[1,-6],[-6,-12],[4,-11],[0,-1],[2,-4],[-2,-4],[-1,-1],[0,-6],[1,-6],[-1,-3],[0,-4],[5,-18],[0,-4],[0,-2],[-2,-11],[-2,-15],[4,-4],[5,-5],[3,-2],[5,-5],[3,-5],[0,-4],[-1,-4],[-2,-3],[-1,-3],[-1,-3],[0,-1],[-6,0],[-3,-1],[-2,-2],[1,-6],[3,-12],[3,-8],[1,-5],[-1,-6],[-1,-3],[0,-4],[-1,-7],[-2,-4],[-3,-4],[-3,-3],[-3,-1],[-3,-1],[-1,-1],[-1,-5],[-2,-5],[-4,-6],[0,-2],[2,-7],[1,-8],[-1,-8],[-1,-8],[-2,-5],[-3,-2],[-2,1],[-2,7]],[[5316,8584],[0,2],[-1,2],[-6,2],[-1,0],[-3,2],[-1,0],[-4,1],[-2,6],[-3,6],[0,2],[0,10],[-1,4],[0,5],[-2,-4],[1,-6],[-2,-3],[-3,-1],[1,-4],[1,0],[0,-4],[-1,-6],[-5,-12],[-1,-2],[-1,-1],[-2,1],[-4,-4],[-3,0],[-1,4],[-5,5],[-2,0],[2,-3],[2,-3],[-1,-3],[-1,-1],[-2,-1],[-7,-4],[2,-3],[-2,-3],[-2,-1],[-1,-1],[-1,-3],[-7,-6],[-11,-15],[-6,-5],[-4,-4],[-3,0],[-5,-4],[-11,-3],[-8,1],[-5,-1],[-3,3],[0,1],[0,1],[0,2],[-3,0],[0,-1],[-1,-3],[-1,-1],[-3,2],[-1,2],[1,3],[2,2],[0,1],[-1,2],[-1,0],[-3,-1],[-3,1],[-9,6],[-2,3],[-8,6],[-3,5],[-2,6],[0,6],[1,9],[1,2],[7,-3],[7,-5],[1,0],[2,4],[4,3],[-1,1],[-6,-4],[-2,2],[-4,5],[0,2],[2,2],[0,3],[-1,3],[1,3],[3,4],[4,4],[3,4],[3,3],[-1,0],[-3,-1],[-3,-3],[-4,-4],[-5,-4],[-4,-1],[-1,-1],[-3,-1],[-3,-5],[-3,-2],[-5,-1],[-1,4],[2,13],[1,7],[2,4],[3,1],[2,3],[1,0],[1,-1],[6,-2],[2,4],[4,1],[6,4],[0,1],[-4,-1],[-3,0],[-3,-1],[-2,1],[-1,3],[1,3],[6,7],[2,3],[1,2],[0,2],[1,4],[6,7],[5,3],[1,-3],[-1,-8],[0,-3],[4,12],[1,3],[2,2],[5,1],[1,2],[-5,0],[-13,-5],[-6,-4],[-1,-4],[-4,-4],[-2,-4],[0,-4],[-2,-3],[-3,-1],[-4,-6],[-2,-4],[-4,-4],[-2,-3],[-1,-1],[-1,-3],[-2,0],[-1,2],[0,3],[1,6],[2,4],[0,4],[-1,4],[1,3],[2,0],[3,-1],[3,0],[6,3],[-1,2],[-3,0],[-4,0],[-4,3],[-3,5],[-1,8],[1,3],[11,8],[2,3],[-1,1],[-4,-5],[-6,-2],[-3,3],[-2,4],[-1,9],[0,5],[0,6],[2,1],[3,-1],[2,0],[6,1],[14,3],[8,-2],[4,0],[5,3],[5,1],[3,-3],[2,-2],[0,-4],[2,-2],[1,0],[-1,3],[0,5],[14,5],[2,1],[-6,1],[-1,5],[2,6],[0,1],[-3,-3],[-1,-5],[0,-4],[0,-2],[-3,-1],[-7,0],[-4,1],[-4,1],[-1,1],[1,3],[-1,1],[-2,-3],[-1,-5],[-3,-1],[-9,2],[-12,-1],[-5,-3],[-4,1],[-6,4],[-2,4],[-1,7],[0,3],[5,2],[3,0],[2,1],[-2,1],[-3,3],[-2,4],[-3,1],[-2,4],[0,6],[0,4],[2,1],[4,-1],[9,1],[9,-4],[7,-2],[12,1],[7,3],[-1,1],[-8,-2],[-7,0],[-13,4],[-5,2],[-6,-1],[-3,1],[-2,4],[1,8],[3,2],[2,-2],[1,0],[2,3],[2,2],[1,4],[5,4],[2,0],[4,2],[2,-1],[1,-1],[1,-2],[4,0],[10,3],[1,1],[2,3],[-6,-1],[-6,-2],[-3,-1],[-1,3],[2,2],[2,2],[1,4],[2,1],[2,0],[5,1],[4,1],[6,-1],[9,-1],[6,-4],[2,0],[2,1],[1,2],[-4,1],[-1,2],[1,2],[7,2],[8,1],[-1,2],[-18,-3],[-4,2],[-4,0],[-2,-1],[-7,-2],[-1,1],[1,4],[4,7],[0,1],[2,2],[11,4],[5,4],[2,1],[2,-1],[4,1],[6,-1],[4,-6],[2,-1],[9,-7],[0,2],[-8,9],[-3,2],[-2,5],[1,4],[2,3],[9,2],[1,1],[1,3],[-2,2],[-3,0],[-3,1],[0,3],[1,2],[5,4],[2,1],[5,2],[8,-3],[1,-2],[-2,-4],[0,-2],[2,0],[4,6],[6,1],[2,2],[3,0],[4,-5],[1,-2],[1,-1],[2,-5],[1,0],[1,2],[3,2],[5,1],[7,-2],[3,1],[1,0],[-1,4],[-1,2],[1,3],[2,2],[5,3],[4,1],[3,2],[4,3],[0,2],[-1,2],[-3,0],[-1,1],[3,3],[5,3],[-1,2],[-3,1],[-3,-1],[-4,-3],[-4,-3],[1,-2],[2,-3],[-3,-4],[-16,-12],[-8,-3],[-4,1],[-1,3],[-1,2],[-2,5],[-3,0],[-2,-1],[-1,1],[2,5],[2,4],[4,3],[3,4],[2,6],[6,5],[9,14],[7,5],[3,4],[5,2],[3,4],[3,1],[6,3],[3,4],[-2,0],[-5,-2],[-3,-1],[0,4],[2,4],[4,4],[18,12],[2,-2],[2,-3],[6,0],[6,7],[5,7],[-2,-1],[-3,-3],[-6,-4],[-3,-1],[-1,1],[-1,3],[-2,0],[-2,0],[-1,2],[-1,5],[3,7],[1,4],[2,4],[8,10],[2,6],[3,3],[5,-1],[1,1],[-1,3],[-5,3],[0,2],[16,5],[8,0],[3,2],[4,2],[3,2],[-1,2],[-8,-3],[-6,-1],[-2,0],[-2,-1],[-6,0],[-2,11],[1,6],[3,0],[0,6],[3,4],[4,1],[2,1],[3,3],[4,-1],[5,1],[-1,1],[-6,2],[-1,4],[2,1],[2,2],[2,0],[4,6],[2,3],[3,-1],[4,3],[3,-1],[4,2],[5,1],[18,1],[0,2],[-4,1],[-13,0],[-6,0],[-3,0],[-1,1],[0,1],[2,2],[1,3],[5,7],[6,4],[4,-1],[5,-4],[4,-1],[1,-1],[2,-6],[2,0],[-1,5],[3,5],[-1,1],[-4,-1],[-4,1],[-3,4],[-1,3],[2,3],[2,1],[-1,2],[-8,-5],[-5,-1],[-2,1],[1,4],[0,4],[6,8],[3,1],[4,-1],[3,-2],[3,0],[3,2],[0,2],[-7,1],[-2,2],[1,1],[5,2],[4,4],[6,1],[4,3],[1,-1],[1,-1],[1,-10],[4,-8],[2,0],[-2,7],[1,2],[2,1],[1,2],[-2,0],[-2,3],[-2,8],[1,2],[5,4],[6,1],[7,-3],[2,0],[4,1],[7,2],[4,1],[2,0],[1,1],[-2,1],[-1,1],[-1,0],[-7,-1],[-17,0],[-2,2],[0,2],[2,4],[2,2],[6,3],[7,0],[8,7],[2,4],[2,7],[4,6],[11,3],[1,2],[-1,2],[0,6],[3,6],[2,2],[1,0],[2,-2],[3,-4],[4,-2],[6,-1],[2,1],[-5,3],[-3,3],[0,3],[1,2],[3,0],[3,0],[3,2],[0,2],[1,2],[0,2],[5,5],[13,3],[1,-1],[0,-10],[-2,-6],[0,-4],[3,4],[3,13],[3,6],[3,3],[2,1],[2,1],[3,2],[1,-2],[1,-3],[-2,-11],[0,-3],[-1,-5],[-7,-10],[1,-2],[1,1],[2,1],[9,10],[7,-1],[0,1],[-3,3],[-2,3],[-1,3],[0,9],[2,4],[6,-1],[4,1],[2,-2],[3,0],[3,7],[5,0],[4,-4],[5,-3],[5,-4],[1,1],[-2,10],[-3,3],[-5,2],[-6,5],[-2,2],[1,1],[5,2],[6,-2],[6,4],[2,-1],[5,1],[2,-2],[2,1],[1,3],[8,2],[4,-2],[3,-2],[1,-4],[2,-7],[3,-5],[2,-2],[3,0],[1,2],[-2,2],[-1,3],[1,6],[2,2],[8,9],[6,4],[4,1],[7,10],[2,2],[2,0],[-1,3],[-3,1],[-1,3],[5,4],[6,6],[3,1],[2,-2],[6,-3],[4,-3],[2,-2],[2,1],[1,2],[2,1],[4,0],[2,-2],[2,0],[1,-1],[1,-2],[-4,-3],[-5,-6],[-6,-6],[-1,-4],[-2,-10],[-4,-6],[-1,-4],[2,-2],[5,2],[6,5],[1,6],[14,17],[7,9],[8,7],[4,2],[2,-5],[-2,-7],[-3,-4],[3,-2],[-1,-5],[-1,-2],[0,-3],[0,-3],[2,1],[9,5],[2,6],[3,4],[1,4],[3,3],[7,0],[0,1],[-8,5],[-1,2],[3,3],[7,6],[4,-1],[2,-1],[9,-1],[7,-4],[0,-6],[-2,-3],[-1,-1],[-9,-5],[-2,-2],[3,-1],[6,2],[2,-2],[-2,-5],[0,-8],[-1,-5],[0,-4],[1,-2],[2,9],[1,2],[3,4],[2,6],[3,8],[4,5],[2,1],[8,0],[3,-2],[3,-3],[2,-2],[7,-2],[2,-2],[0,-1],[2,0],[5,3],[3,0],[4,-4],[-1,-4],[1,-1],[5,0],[5,-1],[9,-7],[1,-4],[0,-4],[-13,-4],[-6,-4],[-9,-2],[-32,3],[1,-3],[22,-7],[1,-2],[-1,-4],[0,-3],[1,-2],[1,-2],[3,-1],[5,1],[3,-2],[2,2],[1,6],[1,1],[3,-2],[2,-6],[1,0],[1,4],[3,0],[4,0],[4,-1]],[[5710,9281],[8,-2],[2,0],[4,-4],[2,1],[-1,-3],[-3,-1],[-6,-1],[-1,0],[-5,0],[-3,3],[-4,1],[0,1],[3,3],[4,2]],[[4751,9264],[-3,0],[-1,1],[4,3],[12,7],[5,6],[9,3],[1,-4],[-1,-4],[-8,-4],[-9,-2],[-9,-6]],[[5533,9469],[-3,-3],[-5,4],[-3,4],[1,2],[9,0],[2,-2],[1,-2],[-2,-3]],[[5600,9711],[3,-2],[9,1],[4,-10],[3,-10],[4,-1],[8,1],[7,1],[4,-1],[6,-3],[3,-2],[-3,-2],[-5,-1],[-1,-6],[6,-2],[9,-5],[6,0],[10,2],[9,-4],[9,-5],[-21,-5],[-2,-2],[-3,-4],[-3,-3],[-3,-2],[-7,-4],[-3,-1],[-8,0],[-3,-1],[-2,-3],[-3,-2],[-7,-1],[-4,3],[2,1],[0,2],[-1,4],[6,4],[2,2],[-1,1],[-2,0],[-5,1],[-1,0],[-4,-3],[-6,-1],[-5,-1],[-23,-3],[-3,1],[-2,6],[9,4],[2,5],[2,3],[3,3],[5,6],[1,0],[-12,5],[-5,3],[-6,6],[-1,5],[-7,4],[1,6],[-6,-1],[-4,4],[4,2],[19,3],[11,2],[5,0]],[[5746,9714],[-4,0],[-8,4],[-1,4],[1,1],[4,0],[6,-5],[6,-1],[-4,-3]],[[5312,9712],[0,-4],[5,0],[5,-4],[6,-2],[2,-2],[1,-2],[3,-4],[2,-4],[-4,-1],[-6,6],[-5,4],[-6,3],[-4,0],[-3,1],[-7,11],[-2,2],[-4,4],[-2,5],[0,3],[6,0],[5,-3],[4,-5],[1,-2],[-2,-2],[2,-3],[3,-1]],[[5806,9729],[9,0],[8,1],[1,-1],[-10,-3],[-12,1],[-11,1],[-13,-4],[-4,2],[7,3],[7,1],[1,2],[2,0],[10,0],[5,-3]],[[5466,9786],[1,0],[2,1],[1,1],[1,1],[7,-1],[10,-3],[3,-2],[4,-3],[3,-5],[-2,-4],[-4,-4],[-1,-2],[1,-3],[0,-3],[-2,-3],[6,3],[11,10],[2,0],[1,0],[6,-2],[4,-5],[1,-1],[1,-2],[1,-3],[-1,-3],[0,-1],[-3,-2],[-1,-1],[3,0],[3,-1],[3,-4],[3,-1],[11,1],[7,-1],[4,-6],[6,1],[0,3],[2,1],[8,0],[4,-2],[4,-3],[-7,-4],[6,-4],[10,-3],[6,-4],[2,-1],[1,-2],[-4,-2],[-5,-2],[-10,0],[-9,-1],[-17,-2],[-3,0],[-1,-1],[-1,-2],[-6,-5],[-7,-6],[-2,-3],[-2,-5],[-1,-3],[1,-3],[0,-3],[-5,-2],[-3,0],[-4,0],[-3,-1],[-1,-2],[1,-3],[-1,-8],[-1,-7],[-2,-6],[-2,-3],[-3,-1],[-8,-1],[-6,-5],[-5,-10],[-3,-4],[-5,-6],[1,-3],[2,-2],[-3,-4],[-5,-5],[0,-2],[2,-3],[0,-4],[-3,-3],[-7,-1],[-6,1],[-3,2],[-3,4],[-4,2],[-3,1],[-13,7],[-11,12],[-11,4],[-7,2],[-3,2],[-4,3],[-3,3],[-2,4],[-2,3],[0,3],[1,2],[1,1],[9,1],[3,0],[3,-2],[3,-1],[6,10],[36,5],[11,1],[12,0],[-2,2],[-2,4],[-1,0],[-9,-1],[-13,-2],[-7,0],[-7,1],[-6,-1],[-7,-3],[-7,-1],[-7,-1],[-14,0],[-4,2],[-4,3],[-2,2],[-1,2],[-1,6],[2,2],[1,1],[1,0],[4,0],[3,-1],[7,-3],[-2,4],[21,4],[10,4],[5,1],[5,0],[-2,2],[0,2],[4,1],[2,1],[8,1],[17,0],[7,1],[4,3],[-5,-1],[-5,-1],[-2,1],[-5,2],[-3,3],[7,7],[3,3],[-7,-1],[-3,-1],[-8,-6],[-6,-2],[-7,-1],[-7,0],[-2,1],[-2,3],[-1,2],[0,2],[3,3],[1,3],[0,3],[-2,0],[-3,-2],[-2,-4],[-3,-2],[-4,0],[-1,2],[-2,2],[-1,1],[-2,0],[-3,-1],[-3,-2],[1,-2],[1,-3],[-2,-2],[-1,-3],[4,-2],[2,-3],[-4,-1],[-4,-2],[-3,-3],[-4,-2],[-5,0],[-7,-1],[-14,-1],[-7,4],[-1,2],[-1,1],[-5,2],[-6,5],[-5,7],[-3,0],[-5,2],[-3,2],[-2,3],[-1,3],[0,2],[3,1],[-7,3],[-7,4],[3,2],[2,0],[20,-4],[2,0],[2,2],[-1,1],[-3,1],[-5,0],[-1,0],[-2,3],[-1,3],[-1,2],[0,2],[3,3],[2,3],[-3,2],[-8,0],[-3,-1],[1,-4],[-2,-3],[-6,-3],[-3,2],[-3,5],[-4,5],[-1,2],[-1,4],[-2,3],[-2,3],[-1,2],[1,2],[2,3],[-2,3],[-2,2],[0,2],[2,2],[2,0],[1,0],[5,-2],[3,-3],[1,1],[2,3],[3,1],[10,1],[11,-4],[3,-2],[2,0],[-1,2],[-1,3],[2,1],[9,-2],[4,0],[10,3],[16,2],[6,-3],[0,-1],[0,-2],[0,-1],[-4,-2],[-20,-1],[-14,-7],[19,1],[3,-1],[1,-5],[2,-1],[4,-1],[3,-1],[4,-3],[3,-2],[2,0],[1,2],[-1,3],[0,3],[0,3],[0,3],[4,2],[6,6],[6,4],[6,-2],[7,-5],[5,-8],[5,-7],[6,-10],[3,-4],[3,-1],[12,-10],[1,0],[-2,8],[-6,13],[-5,10],[-1,4],[0,5],[0,2],[1,1],[3,6],[4,3],[-2,4],[2,3],[4,3],[4,0],[3,-2],[8,-7]],[[5903,9799],[-26,-3],[-3,2],[43,6],[2,1],[8,1],[7,-2],[-2,-1],[-29,-4]],[[5520,9809],[-6,-3],[-10,2],[1,3],[3,1],[6,0],[6,-3]],[[5580,9806],[3,-1],[15,1],[3,-2],[1,-3],[2,-1],[4,-1],[8,-4],[3,0],[2,2],[2,6],[0,6],[-1,4],[1,2],[3,1],[3,-1],[4,2],[2,2],[4,0],[6,-2],[2,-1],[-2,-2],[0,-4],[-3,-8],[6,0],[9,2],[3,2],[5,3],[5,0],[3,0],[1,2],[0,1],[3,0],[4,-3],[2,-1],[4,1],[1,0],[3,-1],[16,-3],[5,-1],[3,-1],[2,-1],[17,0],[12,-1],[4,-2],[4,-4],[1,-9],[-3,-2],[-24,-11],[-6,-3],[-3,-4],[-5,-7],[-2,-2],[-11,-3],[-3,0],[-8,1],[-3,0],[-10,-4],[-4,-2],[-3,-3],[-5,-1],[-6,1],[-23,1],[-4,2],[-2,4],[5,5],[-27,-2],[-29,1],[-2,1],[-1,2],[-10,1],[-7,1],[-7,3],[-6,3],[2,2],[2,1],[5,0],[5,-1],[9,1],[2,3],[3,1],[3,2],[-9,2],[-10,0],[-6,-2],[-7,-1],[-7,0],[-12,0],[-6,2],[-9,4],[-3,2],[-1,1],[0,3],[9,2],[4,1],[3,3],[-14,1],[-6,2],[-6,3],[5,2],[19,1],[5,-1],[5,-2],[6,-2],[5,3],[-5,1],[-4,5],[-1,2],[0,2],[3,0],[1,-1],[7,-4],[5,-1],[2,4],[0,1],[-1,2],[-3,3],[-2,3],[4,1],[3,0],[7,-3],[7,-1],[3,-2],[6,-4],[6,-3]],[[9637,5154],[-1,-2],[-1,2],[1,1],[0,1],[1,-1],[0,-1]],[[9698,2160],[2,-3],[-3,-1],[-1,1],[-1,1],[-1,2],[2,0],[1,1],[1,-1]],[[9616,2260],[1,-5],[-2,0],[-3,1],[-1,3],[-2,-2],[-2,0],[1,3],[4,5],[1,6],[0,2],[3,0],[1,0],[1,-1],[-1,-1],[-1,-2],[0,-3],[0,-2],[-1,-1],[1,-2],[0,-1]],[[9670,2485],[0,-3],[-3,1],[0,-2],[2,-2],[1,-2],[2,1],[1,-3],[-1,-2],[-1,-2],[-5,-1],[-3,-4],[-3,1],[-3,-4],[-4,-2],[-1,1],[1,3],[2,3],[0,4],[1,2],[3,2],[0,3],[1,3],[-1,6],[1,6],[4,0],[6,-9]],[[9631,2554],[0,-3],[-1,-1],[-1,0],[-1,0],[-1,1],[-1,0],[-1,1],[1,3],[3,1],[1,-1],[1,-1]],[[9637,2582],[2,-7],[-3,1],[-1,2],[2,3],[0,1]],[[106,2631],[-1,-1],[0,4],[0,2],[2,1],[1,-3],[-2,-3]],[[106,2664],[-1,-1],[-2,0],[-2,-6],[0,5],[-1,1],[-3,0],[0,-1],[1,-1],[1,-1],[-2,-2],[2,-6],[1,0],[2,-4],[0,-1],[-3,-2],[-2,-2],[-2,0],[-1,0],[0,4],[0,2],[1,3],[2,3],[-1,3],[-3,2],[-4,-1],[-1,1],[2,3],[3,0],[2,3],[11,-2]],[[9830,2830],[-4,-3],[0,2],[1,5],[2,3],[1,0],[1,2],[0,-4],[-1,-5]],[[9808,2806],[3,0],[3,4],[3,4],[3,2],[5,7],[1,1],[4,1],[1,2],[1,0],[-1,-4],[-2,-1],[0,-2],[1,-2],[-2,-3],[1,-4],[-2,-4],[2,1],[2,3],[-1,2],[1,4],[2,1],[-1,3],[0,2],[3,-1],[1,0],[1,1],[1,0],[1,-2],[2,0],[-1,-3],[-2,-3],[0,-2],[-3,-3],[-2,-2],[3,0],[4,4],[3,4],[0,-5],[-2,-4],[-2,-3],[-2,-1],[-2,-2],[-1,-3],[0,-3],[1,-2],[2,-3],[-2,-6],[2,0],[1,-1],[2,-3],[-1,-5],[-1,-2],[-4,-9],[-2,-4],[-3,-3],[0,-5],[-1,-3],[-7,-12],[-1,-2],[-6,-19],[-3,-8],[-2,-2],[-2,-2],[-6,-4],[-2,-4],[-2,-4],[-3,-1],[0,-1],[2,-1],[1,-2],[-1,-3],[-2,-2],[-2,0],[-1,-2],[5,1],[1,-1],[1,-3],[0,-2],[1,-4],[4,-2],[4,-1],[0,-1],[1,-6],[-1,-3],[-1,-1],[-1,-1],[-3,0],[-2,1],[-2,3],[-6,-1],[-1,-1],[-1,1],[3,4],[-2,1],[-1,1],[-1,-1],[-1,-2],[0,-3],[-1,-1],[-2,-1],[-2,3],[-2,3],[-3,4],[0,-3],[3,-5],[1,-4],[-3,-2],[-3,-3],[-2,-1],[-3,-2],[-2,-3],[-2,-1],[-4,0],[-2,-1],[0,-5],[-2,-2],[-3,-1],[1,-1],[1,-1],[-3,-13],[0,-5],[0,-9],[-2,-8],[-4,0],[1,-2],[3,-2],[-1,-3],[-3,-7],[-2,-4],[-1,-9],[-2,-8],[-3,-10],[0,-1],[1,-3],[1,-2],[0,-3],[0,-1],[-2,-1],[-1,-1],[-7,-2],[-2,-3],[-2,-5],[-3,-5],[-7,-10],[-4,-8],[-1,-3],[-1,-2],[-10,-3],[-7,-1],[-3,1],[-4,2],[-2,1],[-4,-2],[-1,-1],[-3,1],[-3,-1],[0,1],[-1,3],[0,3],[0,3],[-2,1],[-1,2],[-1,1],[-3,1],[-5,-1],[-2,0],[-3,8],[-1,2],[-4,3],[-1,-1],[-3,-4],[-1,-1],[-7,0],[-8,1],[-3,2],[0,4],[6,10],[-2,-2],[-4,-4],[-2,1],[2,4],[1,2],[-1,3],[-3,-4],[-3,-1],[-1,4],[1,4],[0,1],[9,2],[4,2],[1,2],[-5,1],[-1,3],[1,2],[5,4],[-4,-1],[-3,1],[0,4],[1,3],[4,0],[-2,3],[0,3],[1,0],[4,-4],[3,-2],[-1,3],[0,3],[1,0],[2,1],[0,1],[-3,1],[-2,2],[0,3],[0,3],[2,4],[2,-3],[2,1],[-1,2],[-1,3],[0,2],[6,8],[2,-8],[0,3],[0,2],[0,2],[0,2],[0,2],[3,2],[3,6],[3,2],[2,-2],[1,-2],[0,2],[-1,2],[0,6],[4,8],[5,8],[5,8],[2,3],[6,3],[3,-1],[1,0],[5,6],[2,1],[2,-2],[1,-1],[-1,6],[1,2],[4,5],[6,4],[4,2],[3,3],[2,0],[-1,2],[1,3],[1,-1],[1,1],[-2,2],[5,4],[2,5],[1,1],[2,1],[1,4],[2,1],[1,-1],[1,-1],[0,2],[-2,2],[2,2],[2,2],[2,-1],[2,-2],[-2,3],[0,2],[2,2],[2,0],[2,-4],[-1,3],[1,3],[3,5],[3,7],[1,-2],[1,-3],[-1,-4],[1,1],[0,3],[0,7],[4,11],[1,1],[1,1],[2,0],[-1,2],[-1,2],[1,5],[1,7],[1,6],[2,6],[2,10],[1,3],[4,0],[1,2],[3,4],[3,6],[2,6],[2,14],[2,14],[3,11],[6,8],[5,6],[2,1],[3,1],[3,-2],[-6,-1],[0,-4],[-1,-4],[1,-3],[1,-3],[3,-2],[3,-2],[2,-6],[0,-7],[0,-6],[2,-6]],[[9875,3094],[0,-3],[-2,1],[-1,3],[-2,2],[0,1],[-1,4],[2,3],[0,1],[1,0],[0,-2],[2,-4],[1,-6]],[[9812,3172],[0,-3],[2,2],[1,3],[2,3],[0,-5],[1,-1],[6,-3],[1,-3],[1,-1],[1,1],[1,1],[2,-1],[5,-5],[1,-2],[-1,-3],[1,-2],[0,-2],[2,-1],[2,3],[1,1],[2,-5],[0,-2],[1,-3],[1,-2],[2,-8],[0,-2],[-1,-3],[2,-6],[-1,-1],[-4,1],[0,-1],[3,-5],[2,-7],[1,-4],[6,-14],[-1,-4],[0,-3],[-1,-3],[2,-7],[-1,-2],[-1,-7],[-1,-2],[0,-2],[3,-1],[1,-1],[1,-2],[1,2],[1,1],[2,-3],[6,-4],[1,-1],[1,-3],[1,-6],[1,-3],[2,-1],[2,1],[1,2],[-1,7],[-1,10],[0,4],[0,3],[0,4],[-1,3],[-1,2],[-1,2],[0,3],[2,2],[1,-3],[1,-3],[4,-10],[3,1],[0,-4],[2,-4],[0,-5],[2,-14],[2,-14],[3,-5],[0,-3],[-2,1],[0,-1],[0,-1],[2,-2],[2,-2],[2,0],[1,-1],[9,-8],[4,-4],[11,-5],[3,-1],[2,1],[3,2],[3,3],[3,5],[2,6],[2,3],[3,2],[1,2],[2,2],[7,-1],[2,-3],[4,-2],[1,-2],[0,-4],[-2,-6],[-2,-6],[-1,-14],[-1,-14],[-1,-6],[-3,-4],[-2,-4],[-3,-2],[-1,-7],[-1,-10],[0,-2],[1,-2],[1,-3],[-2,-5],[-1,0],[-1,5],[-1,2],[-4,2],[-4,0],[-3,0],[-3,-2],[-5,-4],[-1,-2],[-1,-3],[-3,-6],[0,-7],[0,-4],[1,-2],[4,-4],[-4,-14],[-4,-14],[-2,-4],[-2,-4],[-2,-9],[-4,-7],[-2,-6],[-2,-5],[-2,-7],[-4,-8],[-1,-6],[-3,-5],[-4,-6],[-4,-5],[-6,-8],[-2,-2],[-2,-2],[-3,2],[0,2],[-1,5],[0,2],[-3,2],[-4,-3],[-1,1],[0,1],[0,7],[0,2],[-1,1],[-1,0],[0,-2],[1,-1],[-3,-2],[-2,-1],[-1,1],[0,2],[1,2],[0,2],[5,9],[5,12],[4,13],[1,7],[1,12],[-1,5],[-2,5],[-4,10],[-5,5],[-4,1],[-3,2],[-3,4],[-3,5],[-6,5],[-5,3],[-4,5],[-1,3],[0,3],[0,3],[0,3],[1,3],[1,1],[6,7],[7,3],[1,0],[1,1],[2,2],[3,5],[1,3],[1,10],[0,10],[2,12],[3,7],[1,5],[-1,7],[1,3],[1,1],[1,1],[-2,7],[-3,11],[0,3],[0,3],[1,3],[-2,1],[-1,3],[-2,10],[0,2],[2,-1],[2,-8],[0,4],[2,2],[1,2],[2,0],[-4,8],[-1,0],[-2,-2],[-2,-1],[-2,1],[-1,2],[-1,3],[-1,7],[-1,2],[-5,14],[1,0],[5,-6],[0,2],[1,3],[0,3],[-1,3],[-2,2],[0,3],[1,2],[0,2],[-2,4],[-1,1],[-1,-2],[1,-3],[-1,0],[-6,7],[-1,6],[-2,7],[0,-3],[0,-4],[2,-7],[4,-8],[1,-3],[-1,-2],[-1,-1],[-1,2],[-2,7],[-1,3],[-15,37],[2,4],[3,4],[1,2],[0,2],[-1,1],[-1,-1],[-2,-2],[-1,-2],[-1,-5],[-1,-1],[-2,3],[0,2],[0,3],[-1,1],[-1,1],[-2,5],[-1,2],[2,5],[0,6],[-2,6],[-3,6],[-4,10],[-5,10],[5,2],[5,0],[-2,-6],[1,-4],[1,-3],[3,-9],[1,-3],[1,-2],[1,-2]],[[245,4645],[-1,1],[1,0],[0,-1]],[[209,4690],[0,-1],[0,1],[-1,1],[0,1],[1,-1],[0,-1]],[[6631,6348],[-2,-1],[-1,1],[0,7],[4,9],[3,11],[2,-10],[-3,-5],[-2,-9],[-1,-3]],[[6566,6623],[3,-16],[4,-14],[3,-8],[4,-10],[6,-10],[3,-3],[11,-7],[6,-3],[8,-2],[5,-6],[2,0],[3,2],[3,0],[5,-8],[2,-7],[2,-3],[2,-6],[1,-6],[5,-9],[3,-10],[3,-8],[3,-5],[5,-2],[3,-2],[0,-5],[0,-6],[-1,-5],[-3,-10],[-1,-6],[-3,-10],[-4,-16],[-2,-4],[-7,-8],[-5,-10],[-5,-18],[-5,-17],[-1,-6],[-4,-1],[-2,1],[-2,1],[1,5],[0,5],[-2,0],[-2,-1],[-4,-13],[-2,-6],[-1,-7],[-1,-10],[-2,-8],[0,-8],[0,-4],[1,-10],[0,-10],[1,-6],[0,-8],[-2,-2],[-2,-1],[-6,-1],[-7,-2],[-7,-5],[-3,-4],[-5,-10],[-3,-24],[-4,-10],[-4,-2],[-7,-1],[-11,-3],[-4,-2],[-6,-15],[0,-5],[1,-3],[0,-4],[0,-4],[-3,-9],[-3,-7],[-8,-4],[-3,2],[-3,2],[-5,0],[-9,-2],[-3,-5],[-5,-3],[-4,-6],[-9,-2],[-6,-4]],[[6474,6143],[-2,7],[-1,8],[-2,7],[-2,8],[-1,5],[-2,2],[-1,6],[-1,6],[-2,5],[-1,6],[-1,6],[-1,6],[-2,5],[-1,6],[-1,6],[-1,6],[-1,5],[-2,6],[-1,6],[-1,6],[-1,5],[-2,6],[-1,6]],[[6443,6278],[4,3],[5,3],[5,3],[4,4],[5,3],[5,3],[5,3],[5,4],[4,3],[5,3],[5,4],[5,3],[4,3],[5,4],[5,3],[5,3],[5,3],[3,3],[1,7],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[1,7],[1,6],[1,6],[-2,6],[-2,7],[-3,8],[-2,8],[-2,5],[-2,7]],[[6557,6685],[2,8],[1,2],[1,-1],[2,1],[2,4],[0,3],[1,0],[1,-2],[0,-7],[-1,-5],[-1,-18],[-1,-3],[-1,-2],[0,-4]],[[6893,6558],[-1,-4],[-1,-2],[-1,4],[-1,1],[-1,-1],[-1,0],[-3,5],[-1,-5],[-4,-1],[-1,4],[0,3],[-2,-3],[-2,4],[0,4],[-1,1],[-1,2],[-1,1],[-2,5],[0,5],[-1,6],[-3,23],[-2,2],[-11,4],[0,4],[0,10],[0,7],[-4,9],[-1,6],[-2,5],[-3,1],[-3,0],[-2,-2],[-1,-4],[7,1],[1,-1],[2,-3],[-2,0],[-2,2],[-3,0],[-10,-3],[-5,-4],[-8,1],[-9,-3],[-8,-1],[-4,-7],[-1,2],[-2,1],[-11,6],[0,2],[-2,2],[-2,-3],[-2,-1],[-6,3],[-4,-2],[-2,-3],[0,-5],[-6,1],[-3,1],[-4,-1],[-10,2],[-3,-1],[-3,-3],[-2,-2],[-2,-1],[-2,3],[-1,2],[-1,-1],[-2,-3],[-5,-2],[-5,1],[-4,2],[0,1]],[[2733,5606],[-2,0],[-3,2],[-2,5],[0,2],[0,1],[1,5],[2,2],[2,-6],[-1,-2],[0,-4],[3,-2],[0,-3]],[[2803,5659],[-1,-2],[0,2],[1,3],[0,-3]],[[2808,5660],[0,-2],[-2,5],[0,2],[0,5],[2,1],[1,0],[0,-1],[1,-5],[-1,-3],[-1,-2]],[[2715,5724],[0,-3],[-2,5],[1,1],[1,0],[0,-3]],[[2836,5600],[-1,2],[-7,16],[-5,21],[-2,9],[2,1],[1,-1],[1,2],[1,3],[-1,6],[3,5],[1,3],[1,-1],[2,-5],[2,-3],[4,-5],[2,-1],[-3,5],[-4,6],[-2,4],[-1,6],[-1,-2],[-1,-2],[-1,-2],[-1,2],[0,2],[-3,0],[0,2],[-1,1],[0,-4],[1,-2],[0,-3],[-1,0],[-1,3],[-1,2],[-1,11],[-3,5],[-2,1],[-1,1],[-1,3],[-3,2],[-2,5],[-4,4],[-5,1],[-5,0],[-2,-3],[-1,-2],[-1,-1],[-3,-3],[-1,-5],[-1,-3],[-1,-5],[1,-2],[-10,-14],[-2,-2],[-5,-2],[-1,-1],[-1,-3],[0,-4],[0,-4],[1,-3],[1,-2],[3,-8],[5,-11],[1,-3],[1,-6],[-1,-3],[-2,-1],[-4,0],[-2,-3],[-1,-3],[-2,-3],[-6,-3],[-5,0],[-2,3],[0,9],[-3,16],[-1,11],[-1,-2],[-2,-1],[0,-2],[-1,-9],[0,-2],[-2,0],[-3,3],[-3,3],[-5,17],[-1,3],[0,4],[-4,1],[-3,3],[-4,0],[-1,-1],[-2,2],[-1,5],[-3,-3],[-5,1],[-4,2],[-3,-1],[-2,-3],[0,-9],[0,-1]],[[2706,5735],[2,-3],[4,-5],[0,-3],[0,-2],[1,-8],[1,-1],[2,2],[1,-2],[-1,-1],[-1,-2],[0,-6],[3,-3],[2,-3],[5,2],[2,-1],[1,1],[-1,5],[-2,4],[0,1],[1,-1],[1,-3],[3,-3],[5,-11],[5,-2],[4,0],[4,1],[6,5],[5,7],[3,4],[12,7],[4,8],[2,1],[2,1],[3,6],[2,4],[2,3],[6,-2],[4,-2],[3,0],[3,-1],[1,-4],[1,-1],[7,0],[5,-1],[12,-10],[7,-10],[3,-10],[9,-13]],[[1436,3779],[0,-1],[-1,0],[0,2],[0,2],[0,1],[1,-1],[0,-2],[0,-1]],[[3044,4127],[-2,4],[-9,13],[-4,7],[-3,3],[-8,11],[-1,4],[-1,11],[-1,4],[-2,4],[-7,5],[-3,3],[-2,5],[-4,3],[-5,8],[-2,6],[-3,3],[-9,6],[-5,5],[-8,8],[-4,5],[-9,6],[-3,2],[-9,14],[-6,5],[-5,8],[-16,16],[-2,5],[-2,9],[-4,4],[-3,12],[-6,6],[-6,9],[-2,8],[-3,10],[-1,5],[-3,6],[-1,10],[-2,5],[2,3],[1,1],[2,16],[-1,9],[-5,15],[-2,7],[-2,9],[-2,6],[-3,11],[-3,11],[-4,7],[-1,3],[-1,3],[-2,3],[-1,8],[-1,15],[-3,8],[-9,14],[0,5],[-1,10],[-2,11],[-10,33],[-2,10],[-3,16],[-2,9],[-2,16],[-4,12],[-2,11],[-3,13],[0,7],[-5,13],[-2,11],[-4,9],[-4,7],[-2,5],[-6,24],[-1,8],[-4,13],[-4,9],[-2,8],[-4,7],[-19,21],[-7,9],[-2,4],[-1,7],[0,3],[2,4],[3,-3],[2,1],[1,5],[0,7],[-2,9],[-6,18],[1,4],[1,4],[-3,9],[-2,7],[-2,5],[2,20],[1,5],[10,20],[2,9],[4,5],[5,8],[4,7]],[[8339,5487],[0,-4],[-1,-2],[-1,1],[-1,2],[-1,-2],[-2,-2],[-2,-4],[-2,-1],[-1,1],[0,3],[4,6],[3,2],[2,4],[1,0],[1,-3],[0,-1]],[[8365,5534],[1,-4],[2,1],[3,-1],[1,-3],[0,-1],[-4,-4],[-2,4],[-3,-3],[-2,2],[-3,-2],[-1,4],[0,3],[4,5],[4,-1]],[[8391,5554],[-3,-1],[-1,0],[-2,6],[0,3],[-2,3],[0,3],[3,0],[4,4],[6,-6],[1,-2],[-2,-1],[-1,-6],[-3,-3]],[[8493,5585],[0,-3],[-2,7],[-1,2],[1,7],[2,-3],[0,-10]],[[8414,5611],[0,-2],[0,-1],[-3,-3],[-1,0],[0,5],[1,2],[1,-2],[1,2],[1,-1]],[[8251,5638],[-1,-4],[-2,5],[1,7],[0,1],[2,2],[0,-11]],[[8259,5657],[-2,-1],[0,3],[0,4],[1,-1],[1,-1],[0,-4]],[[8466,5710],[-1,-3],[-3,3],[-1,2],[1,3],[1,1],[1,0],[2,-3],[0,-3]],[[8435,5716],[0,-6],[-2,-2],[-2,2],[-1,3],[0,2],[1,-1],[2,4],[1,0],[1,-2]],[[8498,5736],[0,-1],[-1,3],[1,7],[0,1],[1,-4],[-1,-6]],[[8499,5721],[3,-4],[3,1],[-1,-9],[1,-2],[3,-8],[0,-6],[-2,-6],[-1,-2],[-2,-4],[0,-2],[1,-2],[3,-1],[2,-4],[1,-9],[2,-7],[0,-3],[-1,-13],[0,-5],[2,-4],[1,-2],[1,-3],[1,-8],[0,-12],[-1,-5],[-1,-4],[-3,-9],[-4,-8],[-2,1],[-1,-3],[2,-6],[-1,-15],[-1,-10],[-1,5],[-1,6],[-1,14],[-1,6],[-1,6],[-1,5],[-2,5],[-2,12],[-1,0],[-2,-4],[-1,-2],[0,-4],[-1,-3],[-3,-5],[-2,-6],[-1,-7],[-1,-6],[1,-5],[2,-2],[2,-4],[1,-2],[2,-14],[0,-14],[-2,-6],[-4,-12],[-3,-4],[-2,2],[-1,7],[0,3],[1,7],[0,6],[-1,2],[-1,0],[-1,-1],[-3,-8],[-1,-2],[-1,0],[-2,0],[-8,7],[-6,7],[-5,7],[-4,10],[-1,7],[0,8],[-2,11],[0,4],[0,4],[2,7],[2,3],[1,3],[1,2],[1,4],[-1,4],[0,2],[-4,8],[-2,5],[-6,5],[-1,2],[-2,2],[-1,1],[-2,0],[-1,-1],[-1,-3],[0,-3],[0,-3],[-2,-15],[-3,4],[-3,3],[-1,3],[0,3],[-1,2],[0,2],[-2,-5],[-1,-4],[-2,0],[-3,-1],[0,2],[-1,10],[-2,3],[-3,-1],[-3,-5],[-1,-2],[0,-5],[-4,-12],[-2,-10],[-2,-10],[-1,-3],[-1,-2],[-2,1],[-2,2],[-2,6],[1,7],[2,5],[1,5],[2,17],[0,6],[1,3],[3,7],[2,5],[2,1],[5,3],[3,2],[3,0],[3,2],[3,3],[0,4],[0,4],[0,3],[1,2],[1,2],[2,2],[4,2],[1,1],[1,3],[2,5],[2,-1],[1,-2],[4,-2],[3,-4],[1,-6],[1,-4],[0,-11],[0,-2],[-3,-5],[1,-1],[4,5],[2,2],[4,2],[1,2],[1,2],[1,7],[2,7],[1,3],[1,2],[1,1],[5,-5],[3,2],[1,7],[0,11],[1,3],[2,3],[2,-1],[3,-4],[2,-1],[1,3],[1,6],[1,0],[4,-2],[3,1],[1,7],[0,8],[-3,23],[1,5],[2,0],[3,-6],[7,-8],[2,-5],[1,-6]],[[8501,5746],[-1,0],[-1,4],[0,6],[2,7],[2,-6],[0,-3],[0,-2],[1,-4],[-1,-2],[-2,0]],[[8479,5759],[0,-3],[-3,7],[-1,6],[1,-1],[2,-2],[1,-7]],[[8460,5748],[0,-3],[-2,1],[-1,-1],[-2,-5],[-1,-2],[-7,-1],[-5,1],[-2,3],[-1,5],[0,3],[1,4],[1,2],[4,5],[1,3],[2,5],[5,1],[0,-1],[1,-1],[1,0],[2,-3],[3,-3],[-1,-8],[1,-3],[0,-2]],[[8491,5755],[-1,-2],[-1,4],[-1,3],[-2,5],[-1,2],[1,4],[0,7],[1,3],[1,1],[1,3],[1,0],[0,-3],[-1,-8],[2,-10],[-1,-6],[1,-2],[0,-1]],[[8330,5788],[-3,-2],[-1,6],[2,5],[3,-2],[2,-2],[-1,-2],[-2,-3]],[[8452,5795],[0,-1],[1,6],[1,0],[0,-1],[0,-3],[-2,-1]],[[8406,5787],[-1,-1],[-2,-2],[-1,4],[1,7],[2,5],[1,1],[1,1],[1,0],[0,-2],[1,-3],[-2,-9],[-1,-1]],[[8419,5706],[-1,-1],[-2,1],[-2,2],[-2,13],[-2,3],[-3,2],[-2,2],[-1,2],[-5,12],[0,8],[1,4],[1,4],[2,1],[3,0],[2,0],[4,6],[0,2],[0,9],[0,7],[-1,6],[1,3],[1,2],[2,6],[0,4],[0,4],[0,3],[2,1],[5,5],[1,0],[7,-4],[1,-6],[1,-2],[-2,-7],[0,-5],[-3,-7],[-2,-7],[-1,-12],[-1,-4],[-2,-7],[-1,-4],[0,-9],[0,-3],[0,-3],[4,-14],[1,-3],[0,-2],[-1,-3],[-2,-6],[-1,-2],[-2,-1]],[[8426,5728],[-1,-1],[0,3],[0,5],[2,18],[0,5],[3,10],[2,9],[4,10],[0,5],[3,10],[3,13],[0,5],[0,2],[1,3],[0,3],[2,5],[0,-3],[0,-6],[0,-4],[0,-1],[0,-6],[-1,-9],[1,-10],[-1,-11],[-2,-5],[-2,-3],[-2,-2],[-3,-6],[-1,-6],[-1,-6],[-3,-19],[-4,-8]],[[8437,5834],[1,-8],[-2,0],[-1,6],[1,1],[1,1]],[[8258,5670],[-3,-4],[1,5],[0,5],[3,10],[2,3],[3,8],[2,3],[4,8],[4,8],[1,1],[1,0],[2,1],[2,4],[7,15],[5,11],[5,14],[3,4],[0,1],[5,13],[2,2],[2,1],[1,2],[1,2],[2,6],[0,6],[0,4],[-1,5],[1,8],[1,3],[4,15],[1,3],[1,-2],[0,-2],[0,-7],[0,-3],[0,-3],[-1,-5],[3,-14],[2,-9],[0,-3],[-3,-6],[-1,-1],[-4,-2],[-1,-1],[-2,-5],[-2,-5],[0,-3],[-1,-3],[-7,-4],[-3,-2],[-1,-2],[-1,-3],[0,-6],[-5,-19],[-2,-6],[-2,-4],[-2,-3],[-4,-2],[-2,-4],[-2,-7],[-2,-6],[-3,-4],[-3,-4],[-3,-3],[-3,-2],[-1,-3],[0,-3],[-2,-2],[-1,-1],[-3,-3]],[[8329,5848],[0,-3],[-1,-5],[0,-1],[-1,2],[-2,1],[0,3],[1,0],[2,2],[1,1]],[[8460,5837],[2,-2],[2,1],[2,5],[3,-2],[2,-7],[1,-2],[1,-5],[-1,-10],[0,-10],[0,-2],[2,-2],[1,-2],[1,-2],[1,-4],[0,-7],[2,-6],[0,-2],[-1,-3],[-2,0],[-1,-2],[0,-2],[-1,1],[-1,6],[-2,3],[1,-10],[0,-5],[0,-4],[-3,3],[-3,3],[-1,1],[1,7],[0,3],[-2,6],[2,14],[0,3],[-1,3],[-1,5],[-2,5],[-1,0],[-3,-3],[-2,1],[-1,13],[-1,13],[-1,3],[-1,3],[1,3],[1,-1],[2,-3],[2,-2],[1,-2],[1,-3]],[[8461,5846],[-4,-1],[-1,3],[-2,8],[2,1],[2,0],[1,-3],[2,-5],[0,-3]],[[8467,5852],[0,-3],[-1,0],[-1,2],[-1,4],[0,4],[2,-2],[0,-4],[1,-1]],[[8402,5853],[3,-3],[3,2],[3,0],[3,-4],[-1,-3],[0,-2],[6,6],[1,-1],[0,-5],[0,-5],[-1,-4],[-1,-5],[-2,-5],[-2,-3],[-2,-2],[-2,-2],[0,-3],[0,-4],[-1,-3],[-2,-1],[-4,-6],[-9,-4],[-3,-3],[-2,-4],[-1,-3],[-1,-1],[-1,2],[0,1],[2,9],[-1,3],[0,3],[0,7],[2,6],[0,7],[1,13],[1,18],[0,3],[-1,2],[-4,2],[-1,2],[1,4],[1,2],[2,0],[1,-2],[6,-5],[3,-4],[3,-5]],[[8334,5858],[-2,-2],[-1,1],[0,3],[0,2],[-2,10],[1,2],[1,-1],[1,-2],[2,-1],[0,-3],[0,-2],[1,-2],[-1,-5]],[[8335,5885],[2,-1],[1,1],[1,3],[1,-5],[2,-4],[-1,-3],[-2,-1],[-2,1],[-2,-1],[-2,0],[-2,4],[-1,6],[-1,1],[0,3],[0,2],[0,1],[1,1],[2,-2],[3,-5],[0,-1]],[[8406,5893],[-1,-2],[-3,6],[-2,3],[0,1],[1,2],[4,0],[2,-4],[0,-2],[-1,-4]],[[8478,5905],[2,-4],[0,-4],[0,-3],[1,-2],[2,-1],[2,-2],[1,-3],[-1,-3],[1,-5],[-2,-6],[0,-10],[1,-4],[0,-3],[0,-3],[0,-3],[3,-10],[0,-3],[0,-3],[-1,-2],[2,0],[2,-4],[1,-5],[0,-2],[-2,4],[-1,1],[-6,-1],[-3,2],[-2,0],[-2,7],[-2,1],[-2,3],[-2,8],[-1,5],[2,4],[0,4],[0,3],[-1,0],[-2,1],[-2,4],[0,3],[-2,2],[-2,5],[-3,2],[-1,2],[-2,4],[-2,5],[-1,9],[-1,10],[7,-3],[8,1],[9,2],[2,-3]],[[8436,5892],[5,-7],[4,-12],[0,-9],[0,-3],[-2,4],[-4,5],[-2,1],[-1,1],[0,3],[-1,3],[-1,1],[-1,1],[-2,6],[-2,1],[-2,-1],[-3,-9],[-4,-6],[0,2],[2,8],[1,13],[0,4],[-1,5],[0,6],[3,-3],[4,-2],[2,-3],[1,-3],[4,-6]],[[8397,5905],[-1,-1],[-1,0],[0,3],[1,2],[1,-4]],[[8391,5895],[-3,-14],[-1,5],[1,3],[-2,3],[0,2],[0,3],[2,3],[0,9],[3,3],[1,1],[0,-3],[0,-4],[-1,-11]],[[8437,5901],[0,-5],[-1,2],[-3,10],[-1,3],[1,3],[3,-4],[1,-9]],[[8424,5924],[2,-9],[-3,6],[-3,4],[-3,7],[-2,3],[-1,1],[1,3],[1,0],[1,0],[5,-12],[2,-3]],[[8352,5960],[1,0],[5,1],[2,0],[1,-4],[1,-1],[2,-1],[2,2],[2,-3],[2,-6],[3,-5],[2,-3],[0,-2],[-1,-4],[-1,-5],[1,-6],[1,-11],[0,-3],[-2,-5],[-1,-5],[0,-2],[-1,-1],[0,-4],[-1,1],[-1,-1],[-1,-1],[-1,-3],[-2,1],[-1,1],[-1,2],[0,3],[-1,1],[-3,5],[-1,3],[0,4],[-1,4],[-1,4],[-1,2],[-1,3],[0,2],[0,8],[-3,9],[0,2],[-3,3],[-1,3],[-1,2],[-1,5],[0,1],[-2,0],[-1,0],[0,4],[2,2],[2,1],[5,-2],[1,-1]],[[8386,5964],[1,0],[1,0],[3,-5],[0,-2],[0,-3],[-1,-6],[-1,-2],[-1,-2],[-3,5],[-2,3],[0,5],[1,8],[2,-1]],[[8340,5976],[0,-4],[-5,6],[0,2],[0,1],[1,1],[2,-2],[2,-4]],[[8453,5969],[0,-4],[-1,2],[-2,-1],[-2,-3],[-3,4],[0,4],[2,7],[0,11],[1,3],[1,2],[1,1],[2,-8],[1,-1],[2,-3],[0,-7],[0,-4],[-2,-3]],[[8393,5993],[0,-2],[-6,8],[0,2],[0,1],[0,1],[6,-10]],[[8389,6048],[0,-2],[-2,-4],[2,-8],[-1,-6],[-2,0],[0,1],[0,2],[0,2],[0,3],[-1,3],[-1,4],[-1,3],[1,4],[3,0],[2,-2]],[[8363,6256],[4,-3],[10,-11],[3,-2],[4,-2],[3,-1],[2,2],[1,3],[2,7],[2,0],[1,-2],[1,-3],[1,-5],[-1,-5],[-2,-4],[-1,-6],[-1,-17],[0,-6],[1,-5],[2,-8],[1,-2],[2,-3],[1,-2],[0,-4],[0,-4],[2,-1],[1,-2],[0,-4],[-1,-4],[-1,-9],[-6,-23],[0,-4],[-2,-10],[-5,-2],[-5,-4],[-3,-4],[-2,-4],[-1,-7],[1,-2],[0,-3],[0,-4],[-1,-2],[-2,-7],[-1,-5],[-1,-3],[-1,-3],[0,-3],[1,-3],[3,-12],[4,-12],[0,-2],[1,-1],[-2,-4],[0,-5],[0,-6],[3,-14],[1,-4],[1,-3],[1,-3],[2,-3],[4,-4],[2,-1],[2,0],[0,3],[2,1],[0,3],[-2,4],[0,2],[1,1],[1,1],[3,4],[3,4],[3,-1],[4,-1],[3,-2],[2,-4],[2,-6],[2,-7],[0,-3],[-1,-4],[0,-3],[2,-2],[3,0],[2,5],[0,6],[-1,2],[1,3],[1,2],[1,-2],[2,-4],[5,-4],[2,0],[1,0],[2,-3],[2,-2],[-2,-5],[-5,-1],[-2,-3],[2,-7],[2,-6],[2,-4],[2,-5],[0,-4],[-1,-5],[2,0],[2,-1],[4,-4],[1,0],[1,1],[-1,-14],[-2,-13],[-2,1],[-3,6],[1,6],[1,7],[-1,1],[-1,0],[-2,-2],[-2,0],[-3,0],[-6,7],[-3,1],[0,3],[0,7],[-2,8],[-1,3],[-1,2],[-7,9],[-1,1],[-2,7],[-5,10],[-2,1],[-1,0],[-1,-2],[1,-4],[0,-3],[0,-4],[0,-3],[3,-5],[0,-3],[2,-7],[0,-8],[-2,-3],[-3,4],[0,3],[0,3],[-3,7],[0,2],[-5,7],[-4,8],[-8,9],[-1,0],[-2,-1],[-1,-1],[-4,-4],[-1,-3],[0,-4],[-3,-4],[-4,-1],[-3,3],[-3,4],[-2,0],[-2,8],[-3,0],[-3,-5],[0,11],[0,11],[0,3],[2,3],[6,12],[1,3],[0,5],[-2,4],[-2,3],[-3,1],[-2,2],[-1,4],[-1,-7],[1,-10],[0,-6],[-1,-2],[-2,0],[-1,0],[-1,3],[-1,6],[-3,5],[-1,6],[-1,1],[-2,-1],[-1,3],[-1,8],[0,7],[-1,7],[-2,6],[0,6],[-2,23],[0,2],[0,2],[-2,3],[-1,3],[0,3],[0,11],[1,3],[1,1],[1,-2],[2,-3],[1,-1],[1,-2],[3,-7],[1,-1],[3,0],[2,1],[1,3],[0,3],[0,3],[-1,10],[-1,8],[0,7],[0,6],[3,11],[0,8],[0,11],[0,6],[0,3],[-1,6],[-1,6],[5,30],[1,6],[1,6],[0,8],[3,2],[3,3],[2,0],[1,-1],[4,2],[1,0]],[[8386,6272],[-2,-4],[-1,1],[1,4],[0,2],[1,3],[1,1],[2,-3],[-2,-4]],[[8367,6283],[0,-4],[-1,2],[-1,3],[1,2],[0,3],[1,-3],[0,-3]],[[8375,6299],[0,-5],[-2,0],[-2,3],[0,2],[0,1],[0,1],[4,-2]],[[8387,6357],[-1,-1],[0,6],[2,1],[1,0],[-2,-6]],[[8385,6381],[-2,-5],[-1,0],[0,3],[2,5],[1,-3]],[[8643,5358],[-1,0],[0,1],[0,1],[1,0],[0,-1],[0,-1]],[[8738,5609],[-2,-1],[-1,4],[1,5],[1,4],[1,1],[0,1],[1,5],[1,-3],[-1,-9],[-1,-4],[0,-3]],[[9264,4523],[5,-3],[1,-4],[-1,-1],[-5,-1],[0,2],[-4,2],[-1,4],[-2,-2],[1,3],[-2,3],[-1,4],[0,2],[3,-2],[6,-7]],[[9285,4529],[-1,-3],[-1,1],[-3,-1],[-1,0],[-1,3],[0,1],[2,-1],[0,3],[3,-1],[2,-2]],[[9191,4575],[-1,-4],[-2,1],[0,1],[0,3],[2,0],[1,-1]],[[9196,4607],[1,0],[2,4],[2,1],[1,-2],[-2,-13],[-2,2],[-6,3],[0,6],[-1,2],[-1,5],[-2,6],[-1,4],[1,-2],[2,-4],[5,-8],[0,-2],[1,-2]],[[9180,4645],[4,-4],[2,1],[2,-1],[2,-5],[0,-4],[1,-4],[0,-1],[-2,-2],[0,2],[-1,1],[-3,0],[-3,1],[-4,0],[2,4],[0,2],[-2,5],[0,3],[0,2],[2,1],[0,-1]],[[9175,4637],[0,-1],[-2,1],[-4,8],[1,5],[2,4],[3,-4],[1,-5],[0,-2],[-1,-6]],[[9239,4668],[1,-1],[4,0],[1,-3],[1,-1],[2,-2],[1,-2],[0,-1],[0,-1],[-1,-1],[0,-3],[-1,1],[-2,-2],[-3,3],[-1,1],[0,2],[-2,4],[-3,3],[1,2],[2,1]],[[8988,4687],[0,-3],[-4,3],[-4,6],[-2,2],[-1,4],[2,-3],[5,-3],[4,-6]],[[9196,4681],[1,-4],[-2,4],[1,5],[0,3],[0,1],[-2,3],[1,4],[1,1],[1,1],[0,-6],[0,-3],[-1,-9]],[[8988,4695],[-2,0],[-4,4],[-2,3],[6,-1],[1,-1],[1,-3],[0,-2]],[[9111,4848],[-1,0],[-1,2],[-2,3],[-3,7],[0,6],[1,1],[1,1],[6,-7],[0,-3],[0,-6],[-1,-4]],[[9331,4799],[0,-6],[-1,-1],[-1,2],[-2,-2],[-1,-2],[-1,-1],[-3,0],[-3,1],[-3,3],[-2,4],[-2,5],[-2,6],[1,7],[-1,5],[-4,5],[-1,1],[-2,6],[-2,3],[-2,5],[-1,2],[-1,7],[0,4],[0,11],[0,6],[1,0],[2,-3],[1,-1],[4,-1],[2,-5],[3,-9],[0,-3],[1,-2],[3,-4],[1,-2],[3,-10],[1,-2],[2,-1],[1,-2],[3,-4],[2,-5],[2,-5],[1,-5],[1,-7]],[[9087,4871],[-1,0],[-3,5],[0,2],[0,3],[3,4],[2,-4],[1,-7],[-2,-3]],[[9295,4871],[-1,-1],[-1,8],[0,5],[-1,4],[0,2],[2,5],[0,1],[2,-2],[0,-5],[1,-5],[-1,-9],[-1,-3]],[[9055,4912],[-2,-2],[-1,1],[-1,4],[1,4],[2,2],[1,1],[1,-2],[0,-3],[-1,-5]],[[9219,4936],[1,-1],[5,6],[2,-4],[3,-2],[3,-1],[-2,-9],[1,-4],[1,-4],[-1,-6],[-1,-5],[-3,-8],[-1,-1],[-1,-1],[-4,0],[-1,-4],[0,-5],[2,-5],[2,-7],[-2,-6],[-3,-4],[-2,-2],[-5,2],[-5,-1],[-1,-2],[0,-4],[-1,-3],[-1,-2],[-2,-6],[-3,-4],[-4,-5],[-1,-1],[-4,0],[-3,-3],[-1,-2],[-2,-2],[-3,-3],[-3,-4],[-1,-1],[-7,0],[-9,-1],[-3,0],[-3,0],[-1,2],[-4,8],[-2,3],[-3,0],[-5,-3],[-8,12],[-3,3],[-2,2],[-4,1],[-3,3],[-1,5],[0,7],[2,5],[4,-2],[1,0],[2,1],[1,-1],[2,-1],[6,2],[3,-2],[4,-3],[3,-1],[3,1],[5,3],[1,0],[4,0],[4,4],[1,18],[1,6],[1,1],[1,0],[1,-3],[-1,-4],[-1,-3],[0,-7],[1,-7],[2,-5],[3,-1],[3,4],[3,0],[3,-3],[3,0],[2,3],[1,1],[2,0],[1,1],[2,6],[1,7],[2,5],[6,9],[1,1],[2,1],[3,-1],[3,4],[0,7],[0,7],[-3,17],[0,2],[0,3],[1,3],[3,0],[3,-1],[2,-3],[1,-2]],[[9267,4948],[0,-2],[-1,2],[1,3],[0,-3]],[[9240,5003],[-1,-5],[-1,3],[-2,4],[1,2],[2,2],[1,-6]],[[9224,5014],[0,-3],[-1,0],[-2,6],[-1,1],[1,2],[2,-4],[1,-2]],[[9220,5021],[-1,0],[0,4],[1,3],[1,-2],[1,-4],[-2,-1]],[[8915,5022],[0,7],[0,4]],[[8915,5033],[1,0],[3,0],[2,-1],[14,-12],[4,-5],[1,-1],[2,0],[1,-1],[6,-7],[10,-7],[10,-6],[3,-2],[3,0],[7,-3],[3,-2],[6,-8],[2,-3],[3,-4],[4,-5],[1,-1],[1,-1],[4,0],[4,1],[1,-1],[1,-1],[2,-1],[0,-4],[3,-4],[3,-2],[3,-4],[2,-5],[2,-5],[2,-5],[4,-1],[3,-1],[12,-25],[1,-4],[0,-16],[-1,-13],[3,-4],[4,-2],[5,-3],[6,-4],[17,-17],[3,-2],[3,0],[4,0],[1,-1],[3,-3],[1,-2],[3,-6],[2,-6],[1,-2],[1,-1],[0,-3],[1,-11],[0,-6],[-1,-2],[-3,-1],[-10,-2],[-6,2],[-5,-7],[0,-3],[0,-2],[4,-14],[3,-12],[2,-5],[3,-4],[2,-5],[3,-5],[5,-10],[2,-3],[3,-3],[6,-7],[0,-3],[2,-10],[1,-7],[0,-3],[0,-3],[5,-6],[1,-2],[2,-14],[1,-7],[3,-2],[3,0],[9,4],[1,1],[1,-1],[2,-3],[0,-6],[-1,-7],[0,-6],[1,-5],[5,-4],[1,-1],[8,-2],[3,-1],[3,-2],[1,-1],[-1,-3],[-1,-1],[-2,-1],[-3,-2],[0,-4],[2,-3],[1,-5],[2,-2],[1,-1],[3,-1],[3,-2],[3,-3],[2,-1],[5,-1],[3,-3],[5,1],[-4,-4],[-2,-2],[-5,2],[-1,-2],[2,-5],[4,-3],[1,-2],[-1,-2],[-4,-5],[-1,-1],[-3,0],[-5,2],[-4,3],[-1,3],[-1,2],[-3,5],[-2,2],[-3,1],[-3,0],[-5,3],[-12,2],[-3,1],[-3,4],[-2,1],[-1,-1],[-5,-1],[-1,0],[-3,3],[-4,2],[-1,-1],[-1,-1],[-5,3],[-3,1],[-3,3],[-2,3],[-1,3],[-2,7],[-2,7],[-3,5],[-7,9],[-1,2],[-3,8],[0,6],[1,5],[-1,-2],[-2,0],[-4,4],[-2,4],[-3,12],[-2,6],[-4,11],[-1,6],[-2,6],[-1,2],[-1,2],[-1,3],[-1,3],[-7,4],[-1,2],[-1,1],[-4,0],[-3,1],[-5,4],[-3,1],[-3,1],[-3,1],[-1,2],[-1,2],[-1,6],[-2,0],[-3,1],[-2,2],[-3,1],[-1,-2],[-1,-5],[-1,0],[-1,1],[-1,0],[-1,-3],[-2,-2],[-2,0],[-5,3],[-2,2],[-2,3],[-1,4],[-2,3],[-1,2],[2,-5],[6,-23],[-2,0],[-1,0],[1,-4],[-2,-1],[-1,0],[-3,2],[-3,1],[-1,-1],[0,-2],[1,-4],[1,-6],[-4,-2],[-5,-1],[-5,-3],[-5,0],[-3,1],[-3,1],[-2,-1],[-3,-2],[-2,1],[-1,3],[-1,3],[-1,2],[-2,0],[-2,-1],[4,0],[1,-3],[0,-4],[3,-3],[3,2],[6,-1],[6,-6],[1,0],[1,-1],[4,-6],[2,-5],[2,-6],[0,-2],[0,-6],[0,-3],[-4,-5],[-4,-3],[-7,-6],[-5,-7],[-4,1],[-2,4],[-1,1],[-3,2],[-2,1],[-7,-2],[-7,-1],[-3,0],[-3,1],[-3,3],[-3,-1],[-2,-3],[-3,0],[-4,6]],[[9248,4910],[-2,-5],[-1,5],[-2,3],[-1,4],[-2,8],[0,4],[1,4],[0,4],[-1,9],[-2,8],[-7,19],[-2,4],[-2,5],[-2,1],[-3,1],[-1,1],[-3,3],[-2,4],[-6,10],[-4,3],[-1,4],[-10,12],[-2,3],[-4,0],[-3,2],[3,2],[0,4],[0,4],[4,-7],[5,-6],[2,-5],[2,0],[5,-4],[3,-3],[3,-4],[3,-6],[6,-4],[1,-2],[3,-8],[4,-6],[2,-4],[18,-30],[3,-8],[0,-6],[-1,-2],[-2,-5],[0,-6],[0,-5],[-2,-5]],[[9178,5030],[-6,0],[-2,1],[-1,3],[-2,5],[-2,1],[0,1],[4,4],[3,1],[6,-4],[0,-3],[0,-2],[0,-5],[0,-2]],[[9107,5052],[-1,-3],[-2,1],[-1,0],[1,1],[1,3],[1,0],[1,-2]],[[9084,5071],[10,-4],[0,2],[1,-1],[0,-3],[-2,0],[-1,0],[-1,-2],[-3,-5],[-2,1],[-2,-1],[-4,0],[-5,2],[-1,-2],[-2,1],[-1,-3],[-1,1],[-1,3],[0,1],[3,2],[-1,5],[2,2],[3,0],[2,2],[6,-1]],[[9159,5094],[0,-2],[-2,1],[-4,6],[0,4],[1,3],[2,-1],[2,-4],[1,-7]],[[5544,8321],[1,-1],[8,-1],[8,-1],[12,0],[14,-1],[13,-1],[15,-1],[16,-1],[1,1]],[[5655,8151],[2,-4],[0,-3],[0,-2],[0,-3],[1,-2],[4,-8],[2,-8],[2,-3],[3,-4],[0,-2],[-1,-1],[-1,0],[-1,-1],[0,-1],[0,-1],[1,-3],[2,-6],[0,-5],[-1,-1],[-2,-3],[-1,-3],[-7,-2],[-2,-2],[-4,-6],[-2,-3],[-4,-6],[-7,-10],[-2,-4],[-2,-4],[-5,-9],[-1,-4],[0,-3],[2,-7],[0,-4],[0,-3],[-1,-3],[0,-1],[2,-2],[2,-3],[0,-1],[0,-2],[-1,-1],[-3,1],[-3,3],[-1,-1]],[[5626,8010],[-2,1],[-8,4],[-5,3],[0,2],[-1,3],[-2,3],[-5,2],[-2,2],[-8,1],[-4,0],[-2,-1],[-2,0],[-2,-4],[-2,-2],[-2,0],[-2,1],[-2,2],[-3,2],[-2,-1],[-2,1],[-1,0],[-1,-1],[-1,0],[-2,-1],[-1,-1],[-2,-2],[-2,-2],[-1,-5],[-4,2],[-2,-1],[-1,-1],[-2,1],[1,2],[0,2],[0,2],[0,4],[-1,1],[-2,0],[-1,1],[0,1],[-1,1],[-2,3],[-1,4],[-2,2],[-1,-2],[-2,-3],[-2,0],[-3,-7],[-5,0],[0,3],[0,3],[-3,1]],[[5396,8279],[6,-4],[3,-2],[-1,2],[0,2],[0,3],[0,4],[-6,2],[-4,1]],[[5394,8291],[1,-1],[4,0],[9,5],[16,7],[17,7],[4,0],[4,2],[2,2],[1,2],[2,4],[5,7],[9,2],[4,4],[7,4],[16,5],[7,1],[6,0],[6,-4],[7,-4],[1,-3],[-4,1],[-5,5],[-1,0],[4,-13],[2,-5],[5,-4],[4,-1],[12,2],[4,3],[1,2]],[[3114,6224],[0,1],[-1,1],[0,1],[0,1],[2,0],[0,-1],[0,-1],[0,-1],[-1,-1]],[[3182,6227],[-2,-1],[-1,1],[-1,1],[3,2],[3,0],[2,-1],[0,-1],[-4,-1]],[[3163,6246],[1,-1],[0,3],[6,-2],[3,-2],[4,-1],[0,-8],[-3,-4],[-2,-3],[-1,-4],[-4,-5],[-4,-1],[-3,0],[-2,0],[-1,1],[-2,-1],[-3,2],[-2,-1],[-5,1],[-2,-2],[-2,0],[-1,0],[-2,1],[-3,0],[-2,1],[1,9],[0,4],[-1,4],[-1,2],[-1,3],[2,1],[1,3],[0,3],[1,1],[2,1],[7,-2],[17,-1],[1,0],[1,-2]],[[8469,7461],[-2,-2],[0,3],[1,3],[2,0],[-1,-4]],[[8625,7634],[1,-4],[1,-3],[1,-3],[1,-2],[0,-2]],[[8629,7620],[-1,-1],[-2,1],[-3,0],[-4,-5],[-2,-2],[-2,-4],[-3,-3],[-2,-4],[-2,-5],[-1,-5],[-4,-6],[-1,-6],[-1,-6],[3,-6],[0,-5],[-2,-11],[1,-11],[-1,-4],[-10,-7],[-3,-4],[-3,-10],[-5,-4],[-3,-4],[-4,-2],[-2,-7],[-3,-4],[-3,-2],[-3,-3],[-5,0],[-4,-3],[-3,-5],[-8,-7],[-1,-5],[0,-7],[0,-6],[-1,-5],[-1,1],[-1,-1],[-1,-5],[0,-5],[3,-2],[2,-2],[3,-1],[3,-2],[5,-11],[4,-4],[1,-2],[3,-3],[2,-3],[1,-4]],[[8517,7360],[-1,0],[-1,1],[-6,5],[-4,-3],[-1,-4],[-2,-1],[-1,7],[-3,0],[-5,7],[-2,-2],[-1,-2],[-2,-6],[-4,-5],[-1,-1],[-2,1],[1,1],[-2,6],[-6,2],[-2,2],[-1,1],[6,6],[1,1],[-1,1],[-1,1],[-5,-1],[-2,2],[-4,-1],[-2,2],[5,6],[0,4],[0,2],[3,8],[2,5],[7,6],[3,1],[2,-1],[2,1],[-2,2],[-2,2],[-3,-1],[-4,4],[0,4],[7,24],[0,2],[-1,6],[-1,5],[-5,4],[-2,0],[-6,7],[-3,3],[-1,-1],[0,-5],[-1,-1],[-2,-1],[-1,5],[-1,5],[-4,4],[-2,2],[1,6]],[[4522,7077],[4,-3],[3,1],[5,-3],[2,-1],[-2,-3],[-2,-4],[-5,1],[-4,4],[-2,2],[0,2],[1,4]],[[4304,7313],[0,-1],[-1,0],[-2,0],[-1,3],[1,1],[2,0],[1,-1],[0,-2]],[[4287,7363],[2,0],[9,1],[2,-1],[0,-4],[-2,-2],[-5,-1],[-8,3],[-3,4],[0,2],[0,1],[1,1],[4,-4]],[[4218,7399],[2,-3],[-3,0],[-2,-1],[-2,1],[-4,0],[-2,3],[0,3],[1,2],[3,0],[7,-5]],[[4204,7403],[-3,0],[-3,4],[4,2],[2,-1],[0,-2],[1,-2],[-1,-1]],[[4228,7405],[-1,-1],[-8,4],[-2,2],[-4,5],[10,-6],[5,-4]],[[4247,7410],[0,-1],[-6,2],[-1,2],[-1,4],[1,1],[2,1],[4,-1],[2,-3],[0,-3],[-1,-2]],[[4135,7454],[-2,-3],[-2,1],[0,1],[0,6],[2,1],[2,-2],[0,-4]],[[4794,7325],[-3,0],[-9,-10],[-3,0],[-5,4],[-10,2],[-3,1],[-4,-3],[-3,0],[-3,-3],[-1,1],[2,8],[3,15],[0,9],[0,8],[-1,8],[-1,5],[2,13],[0,7],[-2,8],[6,-1],[-2,3],[-2,2],[-2,0],[-1,0],[-5,-3],[-3,-1],[0,6],[-1,6],[2,2],[2,1],[2,3],[1,3],[0,6],[1,5],[4,5],[-2,-1],[-2,-3],[-4,-10],[-1,-6],[-3,-1],[-3,-1],[-2,0],[-2,2],[0,4],[0,3],[2,6],[0,9],[2,7],[0,3],[-1,3],[2,3],[2,2],[2,6],[4,16],[5,17],[0,2],[-1,2],[0,5],[3,20],[1,2],[1,6],[1,10],[0,6],[0,3],[0,4],[-2,8],[-2,16],[0,5],[1,3],[-2,0],[-1,3],[0,4],[3,7]],[[5949,6988],[6,9],[2,6]],[[1153,3982],[-1,-1],[0,2],[-1,3],[0,1],[1,-2],[1,-3]],[[1214,4116],[-1,-2],[0,2],[-2,1],[-1,2],[-1,0],[0,1],[1,0],[2,-2],[1,-1],[1,-1]],[[1092,4125],[0,-2],[0,1],[-2,2],[-1,2],[3,-3]],[[1195,4127],[0,-1],[-3,6],[2,-1],[1,-4]],[[1088,4136],[0,-1],[-1,1],[-1,3],[-2,3],[0,2],[1,-2],[1,-2],[2,-4]],[[1089,4155],[0,-1],[-1,0],[-1,1],[0,2],[1,2],[1,2],[1,2],[2,2],[1,1],[0,-1],[-4,-4],[-1,-3],[0,-2],[1,-1]],[[852,4165],[4,-3],[1,-4],[-1,-3],[-2,1],[-1,1],[-1,5],[-4,-1],[-3,1],[-2,7],[0,3],[1,2],[3,2],[3,-1],[2,-4],[0,-6]],[[838,4173],[0,-1],[-2,1],[0,1],[0,2],[0,2],[3,-1],[-1,-4]],[[794,4212],[-1,0],[-1,0],[0,6],[1,2],[1,-2],[1,-6],[-1,0]],[[1015,4227],[2,-3],[-2,2],[-3,0],[1,1],[2,0]],[[1012,4226],[-1,-1],[-3,4],[1,0],[2,-2],[1,-1]],[[793,4224],[-1,0],[-1,1],[0,2],[0,2],[2,-2],[0,-1],[0,-2]],[[959,4243],[0,-1],[-1,0],[-1,3],[0,3],[-1,3],[-1,2],[0,2],[0,3],[1,-5],[1,-4],[1,-3],[1,-3]],[[1041,4257],[0,-1],[0,5],[1,0],[-1,-4]],[[971,4271],[0,-3],[-1,2],[-2,4],[0,2],[3,-5]],[[1148,4578],[-1,-1],[0,6],[2,-1],[0,-1],[0,-2],[-1,-1]],[[1137,4612],[-2,-5],[0,5],[1,1],[1,-1]],[[1138,4625],[4,-3],[2,1],[-2,-3],[-4,-2],[-1,-1],[-2,1],[-1,3],[4,4]],[[1109,4641],[-1,-1],[-1,3],[0,2],[2,2],[1,-1],[-1,-5]],[[1123,4669],[-1,-1],[-1,3],[1,2],[1,0],[1,0],[1,-2],[0,-1],[-2,-1]],[[1109,4671],[-3,-2],[-1,0],[-1,5],[0,3],[1,1],[4,-1],[1,-2],[0,-2],[-1,-2]],[[6423,6601],[-2,-1],[-2,-1],[-2,0],[-2,0],[-1,1],[-2,5],[-1,7]],[[6411,6612],[0,3],[1,2],[-2,17],[-1,13],[0,2],[2,3],[1,7],[1,6],[3,15],[3,6],[4,4],[4,-8],[4,-6],[1,-7],[-1,-6],[-1,-9],[0,-4],[0,-4],[2,-6],[1,-8],[0,-5],[-1,-5],[-1,-5],[-3,-12],[-1,-2],[-4,-2]],[[5783,7802],[3,-6],[4,-3],[8,-4],[1,1],[0,1],[-1,1],[1,2],[1,0],[2,-2],[4,2],[5,5],[5,1],[5,-3],[2,-3],[2,-3]],[[5825,7791],[-1,-4],[0,-3],[-1,-9],[-1,-4],[-2,-4],[-14,-5],[1,2],[0,4],[-1,3],[2,3],[-4,1],[-1,-1],[-1,-3],[1,-6],[-2,-4],[0,-2],[0,-4],[-1,-2],[0,-2],[2,0],[-1,-4],[-4,-7],[-2,-5],[0,-18],[-1,-11],[-1,-3]],[[5630,7732],[0,3],[-1,1],[-2,2],[-2,2],[-1,3],[1,3],[1,3],[2,2],[2,-1],[1,1],[0,2],[-3,3],[-4,3],[-4,-2],[-4,-7],[-3,-1],[-2,5],[-3,2],[-5,1],[-3,2],[-1,3],[-2,2],[-4,2],[0,2],[2,0],[2,1],[1,1],[0,1],[-2,1],[-2,1],[-1,1],[0,1],[0,1],[0,1],[1,0],[0,1],[1,2],[1,2],[0,1],[0,1],[0,2],[-1,1],[-2,1],[-4,2],[-2,3],[-1,0],[-3,1],[-2,3],[-2,3],[-2,3],[0,1],[-1,1],[1,1],[0,1],[-1,3],[1,4],[0,3],[0,2],[-1,0],[-1,-1],[-2,3],[-2,5],[-1,2],[-3,2],[-2,2],[-2,4],[-1,4]],[[5635,7945],[1,1],[4,3],[1,2],[1,3],[2,-1],[6,-5],[6,0],[1,0],[1,0],[8,-3],[1,0],[1,0],[3,-2],[3,0],[3,2],[3,0],[2,0],[2,-4],[5,-6],[2,-3],[2,1],[3,1],[3,4],[8,5],[6,2],[6,2],[7,1],[2,4],[1,3],[1,5],[4,2],[4,1],[1,0]],[[9056,7684],[-1,1],[1,1],[1,0],[0,-1],[-1,-1]],[[9051,7687],[1,0],[1,0],[0,-1],[0,-1],[-1,0],[-1,1],[0,1]],[[9065,7697],[-1,-1],[-1,1],[-1,0],[1,0],[0,1],[1,0],[1,-1]],[[9074,7703],[0,-1],[-2,1],[0,3],[0,1],[6,3],[1,-2],[1,-1],[-6,-4]],[[9060,7747],[5,-4],[5,0],[-1,-3],[-2,0],[-4,-6],[-4,0],[-1,-2],[-6,-8],[0,-3],[-4,-6],[-5,-6],[-1,-10],[-3,4],[0,4],[1,4],[5,7],[3,4],[0,4],[3,3],[1,3],[1,2],[5,13],[2,0]],[[9127,7794],[-5,-4],[-5,-2],[-7,-8],[-2,-5],[-4,-2],[-3,1],[-1,-1],[-1,-4],[-1,-3],[-7,-9],[-3,-7],[-3,-1],[-5,-8],[1,7],[1,3],[4,5],[1,6],[2,5],[5,6],[4,6],[3,2],[3,6],[3,2],[0,4],[1,5],[1,-1],[3,-6],[2,0],[5,1],[8,12],[3,2],[2,0],[1,-1],[0,-1],[0,-2],[0,-2],[0,-3],[-1,-3],[-5,0]],[[6332,7804],[0,-1],[-2,5],[0,3],[1,2],[1,-5],[0,-4]],[[9157,7813],[-4,-3],[-3,0],[6,14],[4,2],[5,9],[9,10],[1,1],[6,-1],[-9,-11],[-1,-5],[-4,-4],[-3,-2],[-1,-2],[-6,-8]],[[9221,7885],[-5,-6],[-2,0],[0,2],[-1,1],[5,1],[4,9],[4,5],[2,2],[1,0],[-8,-14]],[[9252,7935],[-1,-3],[-2,0],[0,1],[1,4],[1,1],[1,-3]],[[9279,7994],[-1,-3],[-1,1],[0,1],[2,3],[1,5],[2,0],[1,-1],[0,-2],[-4,-4]],[[9299,8024],[-2,-2],[-3,1],[0,5],[6,15],[2,-1],[-1,-3],[-2,-6],[1,-7],[-1,-2]],[[9330,8081],[-3,-6],[-5,-1],[-3,-2],[-2,-4],[-1,-2],[-3,1],[-2,2],[0,7],[-1,3],[1,2],[3,0],[3,4],[7,2],[2,5],[3,11],[3,4],[3,1],[1,-6],[-1,-6],[-1,-6],[-4,-9]],[[9344,8102],[-1,-2],[-2,1],[-3,3],[-1,2],[1,3],[5,4],[2,0],[1,-1],[0,-5],[-2,-5]],[[9323,8111],[-3,-1],[-1,2],[-1,2],[0,2],[2,2],[2,-2],[1,-4],[0,-1]],[[8965,8317],[6,-15],[0,-3],[-1,-3],[-1,-4],[0,-5],[1,-4],[-1,-1],[5,-17],[4,-11],[1,-5],[0,-5],[1,-10],[1,-15],[-1,-5],[0,-5],[-1,-3],[-2,-2],[-1,-5],[0,-15],[1,-8],[1,-6],[2,-6],[0,-6],[0,-3],[3,-4],[1,-3],[0,-4],[0,-5],[1,-2],[1,-1],[6,-43],[2,-13],[6,-22],[3,-14],[2,-6],[1,-7],[1,-7],[2,-7],[2,-8],[5,-7],[2,-3],[1,-3],[0,-11],[-1,3],[-2,7],[-2,5],[-3,5],[-4,5],[-4,8],[-3,2],[-2,2],[-4,2],[-2,0],[-10,-1],[-4,-2],[-4,-3],[-2,-6],[-1,-11],[-9,-38],[-2,-10],[-1,-11],[0,-9],[1,-3],[2,-8],[2,-5],[2,-2],[2,-2],[1,-1],[1,-2],[1,-6],[3,-13],[2,-9],[1,-3],[3,1],[2,0],[2,-1],[1,-2],[1,-11],[1,-9],[0,-3],[-2,-7],[0,-4],[0,-3],[-1,-3],[-1,-2],[0,11],[-1,8],[-1,7],[-2,5],[-6,1],[-6,1],[-1,1],[-2,3],[-1,2],[-2,1],[-1,-1],[-3,-4],[-2,-5],[-2,-5],[-1,-6],[-3,-16],[-1,-5],[-2,-4],[-2,2],[-2,3],[0,4],[-1,5],[-2,16],[1,14],[4,20],[1,6],[-1,6],[-1,6],[0,11],[0,3],[1,6],[2,6],[2,6],[1,6],[-2,16],[-3,11],[-3,10],[-1,3],[0,3],[3,13],[1,6],[1,13],[2,7],[1,8],[0,37],[0,6],[-2,11],[-1,7],[1,8],[2,7],[1,6],[0,13],[-3,12],[-2,5],[-4,7],[-3,3],[-1,3],[1,1],[1,2],[-2,3],[-2,5],[0,20],[1,5],[2,5],[1,6],[2,14],[0,14],[-1,5],[0,12],[0,3],[4,4],[4,2],[2,-1],[3,-4],[2,0],[1,0],[3,2],[2,5],[-2,3],[1,4],[3,1],[1,4],[-2,0],[2,5],[0,4],[-1,4],[-5,11],[-4,7],[6,0],[2,2],[1,3],[1,3],[2,-1]],[[9667,8327],[1,-3],[-11,10],[-6,6],[-1,3],[2,0],[2,-3],[4,-2],[4,-4],[5,-7]],[[8810,8357],[-4,-10],[-2,0],[-2,2],[-4,0],[-1,0],[2,3],[6,5],[2,0],[2,1],[1,-1]],[[8831,8357],[2,-2],[4,0],[1,-1],[-3,-3],[-2,-5],[-1,-5],[-1,-1],[-2,-3],[-2,-3],[-2,-2],[-2,0],[-4,10],[-1,2],[-6,-4],[-1,0],[1,5],[3,7],[2,1],[3,8],[1,2],[9,-5],[1,-1]],[[5544,8321],[4,4],[3,6],[2,6],[1,5],[0,5],[4,2],[8,0],[3,2],[5,7],[4,7],[2,3]],[[5582,8368],[-3,-6],[-7,-11],[2,-2],[3,0],[3,-3],[3,0],[5,2],[1,10],[0,9]],[[9628,8342],[0,-8],[-3,4],[-2,4],[-2,0],[-2,2],[-2,4],[-4,5],[-1,3],[0,4],[-2,3],[-7,6],[2,0],[3,3],[8,-2],[2,0],[-1,-4],[0,-5],[4,-9],[2,-3],[3,-3],[2,-4]],[[9182,8583],[-2,0],[-1,1],[0,1],[3,3],[2,3],[2,-2],[0,-1],[-4,-5]],[[9544,8559],[-4,-5],[-1,1],[0,1],[0,2],[4,3],[4,10],[2,7],[-1,3],[0,2],[12,5],[9,7],[2,0],[1,-6],[1,-9],[-1,-4],[-10,-3],[-9,-6],[-9,-8]],[[5994,8938],[1,-2],[0,-4],[0,-2],[0,-2],[-2,-2],[-2,5],[-2,0],[-2,2],[-1,3],[2,1],[1,0],[3,2],[2,-1]],[[6944,9014],[-5,0],[-5,4],[-5,9],[1,2],[3,-1],[5,0],[3,-2],[5,-1],[-1,-4],[0,-1],[2,-2],[-2,-3],[-1,-1]],[[6186,9026],[-1,-1],[-6,3],[0,2],[0,1],[2,0],[3,-1],[1,-2],[1,-2]],[[6396,9169],[0,-6],[-2,-2],[-1,-1],[-1,4],[-1,1],[-5,-4],[-2,-4],[-6,-7],[-13,-5],[-7,-2],[-7,0],[-6,4],[-4,8],[0,2],[-1,3],[0,4],[1,5],[1,5],[2,4],[6,5],[6,4],[3,0],[8,1],[21,-12],[5,-3],[3,-4]],[[6870,9189],[-2,-5],[-5,0],[-1,1],[-1,1],[5,5],[4,0],[0,-2]],[[9484,9152],[-1,0],[1,4],[0,2],[-3,3],[-5,2],[-1,1],[0,5],[1,8],[-2,4],[0,4],[6,4],[3,3],[2,3],[1,0],[2,-3],[0,-5],[-2,-4],[-4,-1],[-1,-3],[1,-4],[0,-6],[0,-5],[3,-5],[1,-3],[-1,-2],[-1,-2]],[[9699,9192],[-8,-1],[-16,5],[-5,3],[-4,4],[-5,2],[-1,1],[1,2],[1,2],[5,4],[4,2],[5,1],[28,-8],[1,-2],[1,-1],[-1,-3],[-2,-1],[-1,-2],[-1,-6],[-1,-1],[-1,-1]],[[6679,9212],[0,-3],[0,-5],[-1,-4],[-3,-1],[-3,-1],[-5,1],[-3,-1],[-3,0],[-3,1],[-2,1],[-2,1],[0,3],[-2,4],[-3,1],[-3,1],[-4,1],[-1,0],[-3,-2],[-1,1],[-8,9],[-1,2],[-1,2],[-1,2],[-2,6],[1,3],[3,2],[1,0],[4,5],[5,1],[2,0],[1,-1],[6,-4],[3,-3],[3,-4],[3,-3],[9,-5],[6,-5],[6,-3],[2,-2]],[[6848,9247],[0,-2],[-1,0],[-2,3],[-1,3],[0,7],[0,1],[1,1],[1,0],[-1,-4],[3,-9]],[[9463,9263],[-1,-1],[-4,1],[-2,2],[0,4],[3,0],[2,-2],[2,-4]],[[6469,9294],[2,-4],[3,-3],[2,0],[1,-1],[0,-4],[-3,-5],[-1,-2],[2,-2],[0,-1],[-3,-1],[0,3],[-2,2],[-3,2],[-1,2],[-2,4],[-5,4],[-3,-1],[-4,2],[-1,1],[-1,2],[2,2],[6,1],[3,0],[3,-1],[0,2],[0,1],[1,-1],[4,-2]],[[8831,9303],[-7,-5],[-2,0],[-3,3],[-2,0],[-1,0],[-2,-1],[-2,0],[-5,2],[-1,2],[1,1],[1,0],[1,0],[4,2],[14,0],[2,0],[2,-2],[0,-2]],[[0,9304],[4,1],[5,2],[4,0],[4,-1],[4,0],[4,2],[3,-1],[3,0],[12,-3],[3,0],[4,-3],[2,-1],[2,-2],[2,-2],[5,-3],[6,-3],[2,-2],[0,-2],[0,-3],[-8,-6],[-7,-1],[-13,-2],[-18,-4],[-7,-1],[-2,0],[-7,3],[-7,1],[9996,-1],[-7,-5],[-14,-1],[-8,-3],[-2,0],[-4,10],[0,3],[1,3],[4,5],[2,3],[10,5],[8,7],[5,1],[5,3],[-9996,1]],[[7156,9348],[-14,-1],[-6,1],[-1,1],[0,3],[7,4],[3,3],[4,4],[5,4],[5,0],[15,-4],[2,-3],[0,-1],[-6,-4],[-4,-2],[-6,-4],[-4,-1]],[[7208,9372],[-2,0],[-16,2],[-5,3],[-1,3],[0,2],[14,12],[6,-3],[1,-3],[4,-4],[0,-9],[-1,-3]],[[7073,9381],[-2,1],[-4,1],[-7,4],[-2,3],[1,3],[1,2],[6,1],[6,-1],[3,0],[7,-3],[-7,-2],[-2,-3],[0,-3],[1,-1],[-1,-2]],[[8340,9394],[-7,-3],[-6,0],[-4,5],[3,1],[6,1],[3,0],[4,-3],[1,-1]],[[6536,9406],[13,-2],[10,-1],[6,-2],[2,-1],[-1,-4],[-2,-1],[-4,-5],[0,-2],[0,-5],[0,-3],[-2,-3],[-1,-1],[-7,0],[-3,-1],[0,-3],[0,-2],[-3,-5],[-5,-1],[-1,-1],[1,-3],[-2,-2],[0,-4],[1,-1],[0,-4],[4,-5],[-1,-3],[-3,-4],[0,-5],[-3,-5],[5,-4],[2,-5],[2,-5],[6,-10],[6,-10],[12,-14],[12,-10],[5,-3],[11,-5],[2,-1],[2,-2],[-5,-4],[-5,-2],[0,-1],[-3,-1],[-14,3],[-1,0],[-1,3],[-2,2],[-3,0],[-4,-1],[2,-2],[2,-1],[4,-4],[-1,-2],[-2,0],[-8,6],[-1,-1],[-1,-2],[-4,2],[-1,-1],[-3,-1],[-2,2],[0,2],[-1,1],[-12,-2],[-5,0],[-6,1],[-6,3],[-1,-1],[0,-2],[-2,1],[-5,3],[-4,1],[-13,3],[-10,3],[3,2],[4,0],[0,2],[-1,3],[0,3],[2,2],[5,-1],[0,4],[2,0],[5,-2],[2,2],[-8,4],[-8,5],[1,2],[-3,1],[-3,0],[-3,3],[1,5],[2,3],[-1,0],[-13,-2],[-6,0],[-8,2],[-6,-2],[-7,-1],[-3,1],[-4,2],[-3,2],[-2,5],[-2,7],[0,3],[0,6],[1,3],[3,5],[2,2],[4,2],[3,1],[5,-2],[5,0],[2,2],[2,2],[2,3],[3,2],[1,1],[1,2],[1,3],[1,3],[1,3],[3,4],[-1,2],[0,2],[2,2],[-6,1],[-2,1],[-3,2],[1,2],[1,1],[6,5],[3,2],[3,1],[3,-1],[4,0],[3,1],[-4,3],[0,2],[-1,5],[0,3],[2,2],[3,2],[4,1],[3,1],[4,2],[3,1],[6,-2],[3,1],[3,1],[10,4],[4,1],[3,0],[6,-2],[5,-3]],[[6962,9394],[-8,-3],[-2,0],[-5,1],[-2,-1],[-3,2],[0,3],[1,2],[1,3],[0,8],[4,5],[5,2],[17,2],[2,0],[3,-2],[3,-2],[3,-4],[3,-2],[4,-3],[1,-4],[0,-2],[-8,-1],[-13,-3],[-6,-1]],[[7131,9414],[-2,0],[-12,2],[-4,3],[1,1],[3,0],[14,-6]],[[7097,9415],[-5,-2],[1,3],[5,4],[10,2],[4,-1],[0,-1],[-4,-4],[-2,-1],[-9,0]],[[8949,9440],[7,-2],[5,-3],[20,-14],[2,-3],[1,-3],[1,-12],[-1,-1],[-7,-1],[-10,2],[-7,0],[-7,0],[-6,2],[-15,1],[-11,5],[-12,3],[-3,1],[-7,-1],[-10,-5],[-3,0],[-4,0],[-3,4],[7,1],[6,1],[7,1],[5,5],[3,4],[6,8],[2,3],[3,2],[3,1],[3,0],[11,2],[7,0],[7,-1]],[[8459,9437],[-2,0],[-3,2],[-1,2],[0,1],[3,1],[3,-1],[2,-2],[1,0],[-3,-3]],[[7320,9450],[-1,-1],[-2,0],[-1,-1],[-7,2],[-9,1],[2,3],[7,1],[10,-2],[3,-2],[-2,-1]],[[7297,9451],[-3,-2],[-4,1],[-2,2],[-2,2],[2,1],[4,0],[2,0],[2,-3],[1,-1]],[[8782,9441],[-2,-2],[-2,3],[-9,8],[-2,3],[-5,3],[-2,2],[0,3],[7,-2],[11,-8],[6,-6],[-2,-4]],[[8916,9446],[-14,-5],[-3,1],[-6,4],[-2,11],[2,3],[3,1],[3,0],[13,1],[2,-1],[3,-1],[1,-2],[0,-2],[-1,-7],[-1,-3]],[[7354,9473],[-2,-4],[-7,2],[-2,1],[5,2],[3,2],[6,0],[-3,-3]],[[8149,9469],[-1,-3],[-2,-2],[-1,-2],[-2,-2],[-6,-3],[-4,-5],[-1,0],[-16,3],[-3,0],[-5,4],[-8,3],[-3,4],[1,1],[2,1],[7,-1],[2,1],[1,4],[0,3],[1,1],[2,2],[24,-4],[9,-3],[3,-2]],[[7406,9503],[3,-1],[7,1],[1,0],[2,-3],[-3,-4],[-2,-2],[-7,1],[-8,0],[-4,3],[2,2],[5,2],[3,1],[1,0]],[[7282,9528],[1,-2],[0,-2],[-1,-1],[-4,0],[-2,-5],[-2,1],[-1,3],[-4,-2],[-2,0],[-2,3],[-1,0],[-1,2],[6,5],[4,-3],[2,0],[0,3],[0,2],[3,1],[4,0],[0,-5]],[[9077,9525],[7,0],[11,4],[1,0],[26,-2],[2,-1],[1,-3],[-1,-1],[-1,-3],[4,-2],[8,0],[5,2],[16,-1],[13,-2],[5,-3],[3,-2],[3,-2],[3,2],[2,2],[2,0],[2,0],[-5,-13],[-2,-1],[-7,-3],[-14,-4],[-6,-1],[-16,0],[-21,1],[-5,2],[-4,1],[-6,5],[-3,1],[-10,2],[-4,1],[-6,3],[-6,3],[-15,5],[1,6],[2,5],[2,5],[3,5],[3,1],[6,-4],[-1,-5],[2,-3]],[[8775,9527],[-5,-1],[-8,0],[0,4],[2,2],[2,5],[-1,3],[0,5],[1,3],[3,4],[2,-2],[2,-4],[1,-2],[6,-4],[2,-1],[-6,-5],[0,-2],[1,-3],[-2,-2]],[[9246,9568],[-3,-2],[-6,4],[2,1],[5,2],[0,-1],[1,-1],[1,-3]],[[8889,9551],[3,-1],[4,1],[3,-1],[3,-7],[1,-1],[2,-1],[1,-1],[5,0],[2,1],[1,3],[0,3],[0,3],[0,4],[0,3],[1,2],[2,2],[7,4],[5,4],[7,-1],[8,-4],[12,-8],[6,-3],[7,-2],[7,0],[4,0],[7,2],[3,0],[44,-16],[1,-1],[2,-2],[-9,-2],[-7,-4],[-2,-3],[3,-3],[2,-3],[-14,-9],[-5,-3],[-5,-1],[-11,3],[-7,-1],[-6,2],[-7,6],[-3,3],[-2,4],[-1,7],[1,5],[4,2],[3,3],[0,2],[-1,3],[-11,0],[-7,-1],[-6,-2],[2,-12],[1,-4],[2,-2],[10,-13],[2,-1],[6,-3],[6,-5],[-10,-6],[-4,-2],[-4,-1],[-3,1],[-2,1],[-3,3],[-3,3],[-3,2],[-6,0],[-6,-2],[-7,-2],[-18,-2],[-5,-2],[-6,0],[-7,3],[-7,4],[-2,0],[-2,-1],[-2,-3],[-1,-4],[-2,-5],[-3,-3],[-3,-2],[-3,0],[-3,1],[-4,1],[-21,6],[-3,2],[-2,2],[-6,8],[-4,2],[-3,1],[-6,4],[-6,6],[-1,2],[-1,3],[1,3],[5,-1],[4,0],[-2,12],[1,11],[3,2],[9,-2],[-3,4],[-2,5],[1,3],[2,2],[4,1],[6,1],[2,1],[1,2],[3,2],[6,1],[11,4],[3,0],[3,-2],[2,-3],[3,-2],[9,-4],[6,-3],[8,-8]],[[7681,9577],[2,-1],[-1,-2],[-3,1],[-3,-2],[0,-1],[-2,-4],[-5,2],[-7,1],[-5,1],[-10,2],[0,2],[2,2],[6,-2],[5,2],[10,-1],[3,2],[8,-2]],[[7690,9573],[-2,-1],[-1,1],[-1,0],[0,3],[3,4],[0,1],[1,1],[3,-1],[2,-2],[-2,-4],[-3,-2]],[[8124,9597],[4,-4],[1,-2],[-2,-1],[0,-1],[-1,-2],[-1,0],[-4,2],[-2,3],[-4,1],[-5,3],[-1,1],[2,1],[7,-1],[3,1],[3,-1]],[[7710,9596],[-1,-1],[-3,0],[-3,3],[-1,3],[2,1],[6,-6]],[[9142,9599],[-21,0],[2,1],[7,4],[19,2],[-4,-2],[-1,-4],[-2,-1]],[[6882,9575],[-11,-4],[-7,-3],[-7,-3],[-6,-1],[-11,-4],[-18,-4],[-12,-4],[-12,-3],[-14,-4],[-13,-3],[-3,0],[-10,-4],[-7,-1],[-28,-9],[-12,-6],[-4,0],[-3,0],[-3,-2],[-3,-3],[-6,-4],[-3,-3],[-3,-2],[-2,-1],[-3,0],[-2,0],[-5,-3],[-1,-2],[6,-1],[1,-3],[-2,-1],[-4,-3],[-2,-2],[-4,-2],[-2,-1],[-7,0],[0,-3],[1,-2],[-1,-1],[-2,-2],[-2,0],[-10,5],[-2,-2],[0,-3],[-1,-3],[-1,-3],[-2,-1],[-3,-1],[-11,2],[-1,-2],[2,-3],[2,-5],[1,-2],[-1,-4],[-5,-5],[-19,-7],[0,-2],[2,-5],[1,-3],[-1,-2],[-2,-2],[-3,0],[-2,0],[-4,3],[-4,1],[0,-2],[5,-4],[2,-5],[-3,-2],[-9,-6],[-4,-8],[-9,-4],[-6,0],[-6,1],[-5,1],[-14,1],[-7,2],[-8,4],[-6,-1],[-6,-1],[-7,-4],[-5,7],[2,4],[-10,9],[-2,4],[2,2],[3,1],[6,4],[6,2],[6,1],[1,1],[3,4],[2,4],[3,2],[3,3],[9,13],[2,1],[18,3],[2,1],[-6,2],[-5,0],[-2,1],[-2,2],[-1,2],[2,2],[8,8],[8,6],[8,3],[-2,1],[-3,2],[-9,0],[-4,3],[-1,2],[0,2],[3,2],[3,2],[3,-1],[4,-1],[3,-1],[2,-3],[3,0],[8,9],[-1,2],[-1,3],[1,1],[4,1],[3,1],[6,-1],[9,-2],[0,1],[2,6],[2,3],[9,5],[-1,1],[0,3],[10,3],[7,3],[6,5],[3,1],[3,0],[7,2],[12,2],[7,2],[2,5],[5,2],[9,1],[3,-1],[2,-2],[4,0],[2,1],[1,2],[0,3],[0,4],[3,2],[1,1],[11,0],[6,0],[12,-3],[7,0],[8,0],[6,0],[15,4],[26,4],[7,3],[6,3],[4,1],[3,0],[3,1],[7,3],[3,1],[3,0],[3,2],[3,4],[2,3],[8,5],[14,5],[12,3],[7,2],[4,1],[10,-2],[13,-3],[6,-4],[4,-4],[2,-2],[0,-3],[-1,-3],[-1,-3],[1,-2],[-9,-7],[-10,-8],[-1,-1],[-11,-3]],[[7674,9620],[-1,-1],[-1,-1],[-4,1],[-6,-2],[-3,1],[-2,2],[-9,0],[-2,0],[4,2],[12,2],[19,7],[1,-3],[-1,-2],[-3,-3],[-4,-3]],[[7486,9630],[-6,-1],[-4,2],[-1,1],[2,3],[2,1],[10,1],[1,-2],[0,-1],[-4,-4]],[[7983,9633],[-3,0],[-1,3],[3,3],[3,0],[3,-1],[1,-1],[1,-1],[0,-2],[-7,-1]],[[6367,7853],[0,-3],[-3,0],[0,-4],[-1,-2],[-8,-5],[-2,0],[-1,-1],[0,-3],[0,-3],[2,-3],[-1,-2],[-1,0],[-2,1],[-1,2],[-1,0],[-2,0],[-6,-9],[-3,-3],[-3,-1],[-6,-3],[-2,0],[-2,1],[-1,-1],[0,-5],[-2,3],[-2,3],[-1,0],[1,-5],[1,-4],[-1,-2],[0,-2],[-1,-1],[-2,-1],[0,-7],[-1,-5],[-2,-4],[-2,-7],[-2,-3],[-1,-4],[-1,-5],[-1,1],[-1,3],[-1,-3],[0,-3],[-3,-3],[-3,-4],[-1,-6],[0,-3],[0,-3],[1,-2],[5,-2],[3,-2],[2,-5],[3,-4],[2,-5],[2,-6],[2,-13],[1,-12],[3,16],[2,2],[-1,-4],[-1,-7],[-2,-10],[0,-7],[0,-7],[0,-3],[-1,-10],[1,-2],[1,-2],[3,-4],[2,-5],[0,-8],[1,-2],[2,-2],[7,-15],[4,-10],[2,-5],[2,-8],[2,-1],[1,-2],[3,-3]],[[6110,7685],[-3,3],[-10,14],[-5,10],[-17,23],[-2,1],[-9,4],[-4,2],[-9,16],[-4,-2],[-4,1],[-2,1],[-2,2],[-2,4],[-2,6],[-2,4],[-7,6],[-9,3],[0,1],[0,2],[7,4],[2,2],[-4,3],[-1,1],[-2,1],[2,2],[2,1],[4,-2],[3,-5],[3,-2],[2,3],[10,3],[1,3],[0,4],[-1,0],[-1,0],[0,4],[2,5],[5,9],[2,11],[2,3],[2,-2],[0,-2],[0,-2],[2,3],[1,6],[4,0],[2,-1],[3,1],[-5,8],[-7,9],[-3,-1],[-1,2],[-3,7],[-2,6],[3,0],[3,-1],[5,4],[2,1],[3,-2],[5,0],[0,3],[-2,5],[5,4],[5,2],[9,6],[4,1],[1,2],[0,2],[-1,5],[-2,4],[-5,1],[-2,-6],[-7,-2],[-4,1],[3,3],[2,2],[1,1],[-5,-1],[-3,-4],[-7,-5]],[[6061,7896],[0,3],[0,2],[0,2],[1,2],[1,1],[0,1],[-1,0],[-1,1],[0,1],[0,2],[1,1],[0,2],[0,5],[1,4],[2,3],[4,1],[4,2],[2,3],[3,7],[2,1],[4,0],[3,-1],[7,0],[7,0],[2,1],[1,2],[0,4],[1,5],[2,7],[2,4],[0,2],[-1,1],[-1,0],[-1,1],[0,2],[1,1],[0,4],[0,3],[-1,4],[-2,1],[-3,2],[0,4],[1,4],[2,3],[1,1],[3,-1],[2,1],[1,1],[-1,2],[-3,1],[-3,2],[-2,3],[0,3],[2,1],[3,2],[3,4],[2,4],[2,3],[0,3],[0,3],[-2,4],[0,4],[1,2],[0,2],[-2,1],[-2,0],[-2,-1],[-3,0],[-4,5],[-4,4],[-3,0],[-2,1],[-1,2],[-1,3],[-1,1],[-2,0],[-2,-2],[-4,1],[-3,3],[-4,4],[-3,0],[-3,1],[-5,5],[-1,0],[-1,-2],[-1,-4],[0,-1],[-1,0],[-2,-1],[-2,3],[-7,8],[-3,6],[-1,5],[-2,2],[-2,4],[-2,1],[-3,-2],[-2,-1],[-1,-1],[-4,-1],[-7,-2],[-1,-3],[-2,-2],[-2,1],[-2,3],[-3,1],[-2,-1],[-2,2],[-1,3],[-2,2],[-3,1],[-4,1],[-2,-2],[-4,-3],[-2,1],[-1,4],[-2,1],[-2,5],[0,4],[0,2],[1,2],[0,3],[-1,2],[-1,2],[-1,6],[-1,2],[0,3],[1,2],[-1,1],[-1,0],[-2,0],[-1,1],[-1,3],[-1,4],[-1,1],[-2,0],[-3,-1],[-3,-1],[-1,0],[-3,2],[-4,2],[-7,0],[0,1],[0,1],[2,2],[-1,2],[-1,1],[0,4],[0,3],[-1,4],[-1,3],[-1,2],[0,2],[3,1],[4,2],[1,1],[0,2],[-8,12],[-3,10],[-2,5],[-3,4],[-2,2],[-4,-1],[-4,0],[-5,1],[-4,0],[-7,-5],[-2,-1],[-5,2],[-4,2],[-2,0],[-1,-1],[-1,-1],[-2,-10],[-2,-1],[-2,-2],[-3,0],[-1,0],[-3,1],[-3,2]],[[5778,8610],[1,4],[-1,5],[0,5],[1,3],[2,0],[2,-3],[3,-2],[3,2],[1,5],[2,2],[2,-2],[4,0],[3,0],[3,1],[0,1],[1,3],[2,3],[2,3],[15,-3],[12,-5],[1,2],[1,3],[-4,3],[-2,1],[-3,6],[-4,4],[-4,0],[-6,-1],[-8,1],[-7,8],[-5,2],[-3,7],[-1,3],[3,-3],[1,3],[0,4],[-2,2],[-2,2],[-9,-6],[-10,-2]],[[5857,9203],[5,-1],[11,-4],[3,0],[3,2],[3,5],[3,1],[3,-1],[1,1],[-2,5],[1,2],[11,-5],[5,-3],[10,-4],[2,-1],[0,-3],[0,-3],[-2,-1],[-5,0],[-16,4],[-2,-2],[2,-3],[4,-2],[2,-4],[7,0],[7,-1],[3,0],[1,-1],[-3,-4],[1,-1],[8,4],[4,1],[2,-1],[0,-3],[-1,-4],[0,-3],[-3,-6],[-3,-2],[-2,-3],[5,2],[3,2],[5,9],[2,1],[15,0],[4,0],[14,-5],[4,0],[5,0],[1,2],[2,1],[15,-5],[22,-11],[30,-18],[18,-16],[2,-3],[6,-2],[2,1],[3,-1],[21,-14],[7,-1],[-1,3],[-2,3],[2,-1],[3,-2],[3,-6],[5,-4],[5,-6],[4,-3],[4,-1],[3,-1],[5,-2],[3,-16],[2,-3],[0,-7],[4,-3],[2,0],[0,-5],[-2,-12],[-2,-5],[-19,-22],[-12,-8],[-22,-10],[-18,-4],[-7,0],[-14,2],[-7,2],[-10,5],[-8,3],[-6,1],[-11,1],[-24,5],[-4,2],[-15,10],[-6,-2],[-4,-1],[-2,4],[1,1],[0,1],[-8,3],[-7,0],[-4,3],[-4,1],[-2,-1],[-2,0],[-9,5],[-4,4],[-4,6],[1,2],[1,2],[-15,4],[-14,0],[3,-2],[6,-1],[4,-2],[4,-4],[-1,-5],[6,-5],[5,-5],[0,-1],[2,-1],[7,-2],[1,-4],[-1,-2],[1,-2],[5,-3],[3,-1],[4,-1],[-1,-4],[-4,-2],[-3,-1],[2,-1],[4,1],[15,-6],[8,-5],[8,-10],[3,-6],[0,-2],[-1,-3],[-1,-3],[0,-3],[-3,-9],[-2,-3],[-4,-4],[4,-6],[3,-7],[4,-10],[1,-4],[0,-7],[3,-2],[-1,-1],[-1,-2],[0,-9],[5,-7],[7,-4],[4,-1],[6,2],[4,-3],[9,-8],[5,-9],[2,-2],[9,-3],[7,-2],[12,-5],[1,-1],[6,5],[9,3],[3,5],[0,3],[-3,7],[0,7],[-3,2],[-3,2],[-9,-1],[-4,0],[-3,2],[-4,4],[-7,12],[-4,3],[-2,3],[-1,3],[0,5],[4,0],[3,3],[3,11],[5,1],[2,0],[11,-5],[13,-13],[3,-2],[3,0],[5,0],[1,-1],[3,-2],[2,-1],[12,-4],[14,-8],[6,0],[2,5],[0,2],[6,4],[4,1],[6,-1],[1,1],[-2,7],[-3,6],[-4,3],[-6,11],[-3,6],[-1,5],[0,5],[1,4],[15,9],[5,5],[5,7],[2,2],[8,2],[11,5],[9,8],[8,12],[4,3],[3,0],[4,-2],[4,-3],[5,-1],[6,1],[6,-1],[9,-5],[2,-2],[1,-2],[-3,-5],[0,-3],[2,2],[3,0],[3,-1],[3,-2],[2,-3],[3,-2],[0,3],[1,3],[-2,7],[4,10],[2,4],[5,11],[-1,7],[0,8],[-1,4],[-3,6],[-6,4],[-6,1],[-2,4],[0,4],[2,6],[5,14],[5,18],[0,5],[0,2],[0,2],[-1,6],[-1,4],[-21,17],[-1,1],[-1,2],[2,1],[2,0],[16,-8],[3,0],[26,2],[12,-2],[10,-4],[8,-11],[7,-10],[7,-8],[0,-7],[-7,-2],[-7,0],[-18,-3],[-4,-4],[-12,-13],[-1,-3],[1,-4],[5,-4],[12,-5],[5,-12],[4,-5],[3,-3],[2,0],[6,0],[5,-2],[1,-1],[1,1],[4,1],[23,6],[4,3],[2,3],[1,14],[2,4],[2,6],[-1,4],[0,4],[11,3],[11,3],[5,-1],[1,3],[-3,6],[-2,2],[2,1],[2,-1],[3,-1],[6,1],[21,11],[9,7],[5,2],[8,6],[4,2],[6,0],[7,3],[8,4],[11,4],[1,0],[2,-1],[5,-4],[-2,-2],[-1,-3],[2,-1],[2,-1],[2,1],[2,2],[5,2],[2,3],[-2,2],[-3,5],[-3,1],[-3,0],[10,7],[20,10],[11,5],[11,0],[8,0],[-3,-2],[-14,-2],[-2,-1],[0,-2],[3,0],[2,-2],[-2,-2],[-1,0],[-1,-6],[-2,-4],[4,-6],[0,-5],[-2,-3],[-4,1],[-4,-2],[-6,-2],[-1,-2],[-1,-2],[4,-1],[3,0],[11,-1],[1,0],[4,1],[4,1],[4,0],[3,1],[2,-1],[4,-5],[4,1],[2,10],[6,6],[8,5],[7,1],[7,3],[3,1],[7,-2],[9,0],[8,-3],[6,-1],[9,5],[20,15],[2,-3],[3,4],[16,5],[4,0],[0,-1],[1,-5],[3,-3],[5,-6],[-2,-2],[-3,-1],[-3,-4],[0,-10],[6,-2],[8,-3],[3,0],[3,1],[1,1],[1,2],[1,3],[0,2],[-2,5],[1,6],[7,0],[10,1],[4,4],[5,6],[3,5],[-2,9],[-6,-2],[-9,20],[-4,8],[3,4],[8,2],[7,7],[2,2],[3,0],[21,-5],[24,-1],[20,-4],[23,-8],[12,-6],[9,-6],[-1,-5],[4,2],[8,-4],[6,-2],[5,-2],[2,-3],[8,-3],[8,-4],[1,-1],[10,-3],[6,-1],[5,-7],[13,-10],[3,-4],[12,-6],[6,-5],[3,2],[9,12],[6,15],[3,7],[-6,1],[-5,-3],[-2,1],[-4,2],[-5,6],[-7,10],[-1,10],[-2,4],[-6,3],[-4,3],[-16,6],[-3,-2],[0,-4],[-1,-2],[-2,3],[-1,3],[0,5],[1,6],[2,10],[4,-1],[2,1],[3,5],[-1,4],[-2,2],[1,5],[2,11],[1,14],[-2,4],[-2,2],[-9,-2],[-3,1],[-1,2],[0,3],[3,3],[2,6],[-4,-1],[-2,2],[4,3],[4,9],[10,3],[7,4],[12,8],[9,8],[5,9],[4,10],[6,21],[6,16],[10,17],[6,1],[2,0],[1,-1],[-2,-1],[0,-2],[2,-1],[5,0],[8,1],[13,-1],[23,2],[4,-1],[8,-5],[5,1],[10,-3],[5,-2],[5,-3],[-1,-12],[-1,-8],[-3,-16],[-2,-3],[-5,-11],[-3,-8],[-4,-5],[-6,-3],[-1,-2],[0,-3],[6,-9],[13,-9],[4,-11],[1,-8],[-1,-21],[-2,-3],[-2,-3],[-3,-4],[2,-6],[2,-22],[0,-18],[-1,-6],[-1,-13],[0,-4],[1,-7],[3,-5],[4,-4],[10,-6],[10,-7],[1,-3],[1,-3],[-4,-3],[-6,-8],[-3,-6],[0,-5],[1,-7],[-1,-6],[-2,-6],[-3,-4],[-10,-6],[-21,-34],[-5,-4],[-8,2],[2,-5],[3,-7],[0,-4],[-6,0],[-8,-5],[-3,-3],[-6,-2],[-5,2],[-5,3],[1,3],[1,1],[4,2],[3,2],[-2,1],[-1,0],[-4,-4],[-4,0],[-6,4],[-4,4],[-2,1],[-3,-2],[-15,1],[-4,-1],[-2,-1],[1,-2],[2,-2],[1,-5],[1,-3],[6,-4],[8,-2],[8,-5],[10,-3],[23,1],[5,0],[6,-1],[10,-5],[4,0],[7,4],[2,10],[1,4],[26,14],[4,3],[8,8],[3,5],[2,14],[3,5],[17,16],[2,4],[1,8],[-1,5],[-1,5],[-3,8],[-3,5],[-3,7],[2,13],[3,6],[15,6],[13,2],[14,5],[6,1],[4,-1],[4,-5],[4,-7],[10,-10],[4,-7],[0,-9],[0,-22],[-2,-9],[4,-3],[2,-2],[5,-3],[3,-3],[3,-1],[6,-1],[16,1],[10,1],[-1,1],[-2,1],[-8,1],[-11,2],[-15,4],[-2,9],[0,6],[4,10],[2,2],[3,1],[4,1],[-1,7],[-2,6],[-3,9],[-4,16],[-5,0],[-4,3],[-19,9],[-18,7],[-12,1],[-4,-1],[-10,-7],[-7,-2],[-12,3],[-11,-1],[-4,1],[-1,4],[3,12],[-2,5],[-4,7],[-3,5],[0,5],[7,22],[3,5],[8,10],[3,8],[-1,4],[-16,24],[-4,9],[-2,2],[-4,4],[-6,3],[-2,4],[17,23],[7,4],[10,2],[5,3],[9,4],[5,4],[2,3],[1,4],[0,9],[-1,7],[-1,5],[-3,5],[-3,6],[2,1],[2,1],[6,0],[6,-3],[3,-7],[3,-6],[0,-4],[0,-3],[2,-4],[1,-2],[1,-3],[-1,-3],[-1,-1],[-3,-3],[-4,-11],[-4,-1],[0,-9],[7,-9],[-1,-7],[-2,-2],[-4,-4],[1,-3],[1,-2],[11,-4],[10,-3],[18,-1],[5,-4],[2,3],[17,-1],[13,-10],[7,-4],[6,-1],[11,1],[2,1],[2,3],[-5,0],[-3,-1],[-2,0],[-4,1],[-2,2],[-3,3],[-5,11],[-9,3],[-5,-1],[-6,0],[-11,6],[-6,2],[-13,6],[-3,3],[-3,5],[-3,8],[-2,5],[3,1],[8,4],[13,2],[5,-2],[13,-9],[7,-1],[11,5],[1,2],[-2,5],[-4,3],[-6,1],[-8,-2],[-2,2],[0,3],[1,2],[5,0],[3,2],[6,6],[7,3],[7,1],[26,-1],[15,-9],[15,-4],[6,-3],[2,-1],[1,-2],[1,-5],[18,-13],[5,-1],[11,-1],[13,3],[6,0],[6,-1],[4,-1],[3,-3],[-2,-4],[-1,-2],[-4,-7],[-1,-2],[-12,-7],[-5,-2],[-1,-9],[-1,-2],[0,-4],[2,-7],[0,-4],[-1,-6],[-3,-6],[0,-5],[1,-7],[1,2],[-1,4],[1,3],[6,8],[4,12],[4,3],[3,1],[4,-4],[1,-4],[0,-7],[0,-7],[-3,-10],[-5,-7],[-2,-4],[2,-3],[3,-3],[3,-1],[3,0],[1,1],[0,3],[-1,3],[0,4],[6,2],[6,2],[4,4],[1,3],[1,4],[-2,7],[-2,6],[-7,13],[-5,6],[3,10],[6,11],[2,3],[0,2],[1,3],[-1,3],[0,2],[-6,8],[-4,3],[-12,1],[-3,2],[-9,8],[-1,2],[-2,6],[-1,2],[-2,1],[-9,4],[-5,1],[-9,1],[-5,1],[-8,6],[0,2],[-3,7],[-1,4],[0,3],[3,5],[2,6],[-2,4],[-4,1],[-3,2],[-2,4],[-1,5],[0,3],[0,4],[1,3],[4,4],[-1,2],[1,3],[24,4],[10,1],[48,1],[3,1],[21,2],[9,2],[10,-2],[3,0],[7,1],[4,5],[11,2],[17,2],[8,0],[2,-2],[2,-2],[-9,-6],[-10,-6],[-7,-2],[-8,-5],[0,-2],[-1,-1],[1,-4],[0,-3],[8,-3],[6,-4],[5,-3],[5,-2],[1,1],[-16,10],[-5,2],[-1,3],[0,4],[2,1],[3,2],[1,1],[7,2],[20,3],[5,5],[2,3],[6,3],[-2,1],[-5,1],[-3,2],[-14,18],[-4,3],[-11,2],[-5,2],[5,6],[6,2],[4,0],[4,-2],[6,-5],[9,2],[-3,2],[-6,3],[-5,4],[-8,4],[-9,2],[-9,1],[3,6],[5,-1],[1,2],[3,3],[12,-8],[6,2],[5,4],[11,9],[1,4],[-5,3],[-4,1],[-6,0],[0,2],[2,3],[5,2],[14,-4],[23,9],[6,5],[16,6],[8,-1],[16,8],[23,3],[13,0],[11,4],[15,2],[6,2],[26,4],[14,3],[3,3],[-13,-2],[-3,2],[-3,-2],[-2,-1],[-6,3],[-2,-1],[-2,-2],[-2,0],[-2,0],[-1,4],[3,6],[3,-3],[5,4],[3,0],[8,-3],[5,3],[7,1],[8,-1],[3,0],[2,3],[13,-2],[9,1],[6,0],[10,-1],[4,-2],[-2,-4],[-10,-7],[3,-1],[5,3],[16,5],[3,-1],[-2,-4],[-1,-2],[10,2],[9,5],[4,1],[5,-3],[3,3],[1,3],[7,0],[3,3],[5,2],[4,1],[9,3],[3,-1],[6,-1],[5,-1],[11,-4],[1,-2],[2,0],[3,-3],[-3,-4],[-2,-6],[-4,-3],[2,0],[2,0],[4,4],[3,3],[-1,12],[-6,6],[-4,2],[-10,6],[-4,3],[-4,3],[2,2],[19,-3],[10,1],[11,0],[14,3],[6,-3],[7,0],[8,-2],[3,2],[-13,3],[-6,0],[-2,1],[2,4],[3,5],[-3,4],[-2,3],[-1,4],[3,5],[5,3],[3,4],[6,5],[31,18],[14,7],[6,1],[6,-1],[13,6],[4,0],[18,-5],[4,-3],[9,-2],[12,-2],[5,-2],[2,-2],[2,-4],[-9,-2],[-9,-6],[-14,-4],[-16,-2],[-3,-2],[31,-1],[9,1],[2,-6],[3,0],[9,2],[5,1],[10,-2],[2,1],[5,0],[9,-3],[4,-3],[-6,-6],[-7,-6],[-9,-9],[-2,1],[-5,0],[1,-4],[8,0],[4,-2],[9,2],[13,0],[2,0],[5,3],[2,5],[2,4],[4,1],[5,-1],[8,0],[20,1],[17,-2],[14,3],[18,-2],[7,-2],[6,-4],[5,-1],[5,-3],[4,-4],[-2,-3],[-2,-3],[5,3],[5,0],[3,-1],[6,-2],[1,-9],[2,-2],[1,-3],[-2,-3],[-1,-2],[4,1],[6,3],[2,1],[1,2],[-2,3],[-2,1],[2,1],[6,0],[2,-4],[2,-4],[4,-13],[8,2],[0,-4],[-3,-9],[-4,-6],[-1,-2],[-2,0],[0,4],[-1,2],[-2,1],[-7,1],[-14,8],[-4,1],[-1,-1],[0,-1],[8,-5],[6,-9],[6,2],[2,0],[3,-5],[6,-1],[4,-3],[-3,-9],[-19,-16],[-20,-10],[-9,-6],[-16,-5],[-11,-6],[-15,-5],[-4,-5],[-11,-3],[1,-2],[1,-2],[-1,-3],[-2,-2],[-8,-5],[-12,-3],[-24,-20],[-12,-4],[-14,0],[-3,-2],[-10,-12],[-3,-2],[-14,-2],[-14,-20],[-8,-7],[-7,-3],[7,0],[9,3],[10,7],[2,3],[1,3],[3,3],[5,2],[17,2],[8,-1],[10,0],[7,4],[4,1],[4,1],[2,2],[6,1],[14,3],[3,2],[4,5],[9,-2],[6,1],[16,9],[9,3],[3,3],[-2,1],[-2,1],[-9,-3],[-9,-1],[-9,1],[-1,1],[-2,4],[3,4],[3,3],[6,4],[5,1],[18,-4],[4,0],[2,6],[6,0],[6,-1],[-3,-2],[-6,-2],[2,-5],[3,-3],[11,-5],[9,-2],[7,0],[11,2],[2,2],[2,4],[-2,7],[2,-1],[3,-2],[4,-4],[4,-8],[3,-3],[-2,-4],[-6,-7],[4,-4],[6,-3],[0,-11],[-1,-6],[-3,-6],[-3,-2],[-3,-4],[0,-4],[1,-2],[4,-4],[10,-2],[1,2],[-2,1],[-7,2],[-3,1],[-2,4],[3,4],[3,4],[3,7],[1,5],[0,5],[2,2],[3,3],[2,0],[2,1],[-3,2],[-2,0],[-5,3],[-1,5],[10,1],[6,3],[21,1],[14,6],[32,-2],[23,-4],[31,-1],[12,-3],[1,-1],[1,-2],[-5,-1],[-8,0],[-3,-5],[2,-7],[15,-8],[13,-3],[9,-5],[4,0],[19,0],[11,-2],[10,2],[11,0],[4,-1],[4,-3],[6,-1],[8,-1],[4,1],[2,1],[-1,2],[-6,2],[1,2],[2,1],[11,-4],[4,0],[4,3],[3,4],[2,4],[1,1],[2,1],[1,1],[-3,4],[-4,4],[0,4],[-1,1],[-1,6],[3,6],[2,2],[9,-2],[4,3],[2,2],[10,2],[5,0],[7,-3],[23,-11],[-1,-4],[5,1],[3,2],[6,1],[4,2],[1,-1],[2,-1],[-1,-3],[-2,-2],[1,-2],[1,0],[7,-3],[7,5],[4,6],[2,1],[19,-4],[6,-2],[2,-1],[0,-2],[4,-2],[4,-1],[-1,-2],[0,-2],[9,0],[4,-2],[4,-3],[0,-2],[1,-2],[4,0],[1,0],[-1,-4],[-6,-4],[-3,-2],[-4,-3],[2,0],[10,-1],[6,-5],[0,-4],[-3,-2],[-9,-5],[-5,-2],[-3,-1],[-3,0],[4,-3],[16,0],[4,-3],[4,-7],[0,-9],[-4,-4],[-9,-1],[-13,10],[-8,4],[-11,7],[-2,-1],[3,-6],[5,-4],[10,-9],[15,-19],[4,1],[2,3],[1,3],[-1,4],[2,-2],[3,-4],[4,-6],[-6,0],[-8,-2],[-3,-2],[2,-4],[6,-1],[3,-4],[4,-6],[11,-17],[7,-3],[7,-7],[7,-3],[4,0],[2,4],[2,-1],[2,-8],[4,-3],[3,-1],[3,2],[5,3],[4,5],[5,11],[4,6],[4,2],[-1,3],[0,3],[3,8],[3,9],[3,5],[6,10],[3,2],[2,-4],[1,-4],[1,-2],[1,0],[8,-9],[8,-6],[8,-4],[11,-3],[17,1],[3,4],[6,3],[9,2],[6,3],[9,2],[5,-1],[9,-3],[20,-9],[5,-3],[3,-3],[7,-6],[4,-2],[4,-2],[1,1],[0,1],[-2,1],[-2,2],[5,2],[0,2],[2,1],[6,1],[-6,2],[-2,0],[-3,1],[0,3],[2,2],[2,4],[2,2],[3,2],[2,0],[6,-2],[4,4],[3,0],[6,-5],[6,-6],[3,0],[9,2],[10,1],[-2,3],[-6,9],[0,10],[-4,3],[-6,1],[8,3],[6,8],[4,1],[5,2],[-1,1],[-15,1],[-3,-1],[-2,-3],[-7,0],[-1,6],[0,4],[9,8],[4,1],[24,0],[7,2],[10,4],[-3,2],[0,5],[-9,7],[1,2],[1,1],[2,0],[14,-2],[6,-4],[15,-4],[41,-1],[4,-1],[18,-2],[7,-2],[17,-2],[8,-2],[7,-2],[10,-2],[5,-2],[-1,-5],[-21,1],[-7,2],[-9,0],[-3,-1],[-6,-5],[-6,-2],[-5,0],[3,-4],[5,-1],[16,5],[43,2],[7,0],[-1,-3],[-6,-7],[-5,-5],[-8,-5],[-3,0],[6,11],[-3,0],[-2,0],[-7,5],[-1,0],[-1,-1],[0,-2],[-2,-6],[3,-3],[0,-4],[-10,-3],[-4,0],[-4,2],[-1,0],[-1,-2],[1,-2],[0,-2],[-2,-2],[0,-2],[2,-3],[3,-1],[17,3],[8,4],[8,6],[15,16],[6,6],[4,2],[4,1],[27,-2],[16,-4],[15,-5],[7,-4],[6,-6],[1,-2],[0,-3],[-4,-3],[-16,-1],[-7,-2],[-2,-2],[0,-1],[-1,-2],[1,-1],[8,0],[7,-1],[10,-4],[1,-1],[3,-4],[1,0],[15,0],[1,-1],[1,-2],[-4,-4],[-4,-3],[-8,-7],[5,3],[16,5],[4,1],[5,0],[12,-5],[5,-4],[9,-11],[-3,-2],[-6,-1],[20,-8],[8,0],[19,2],[9,0],[17,6],[17,3],[16,1],[8,3],[22,0],[22,-1],[16,-2],[18,-6],[18,-9],[11,-8],[2,-2],[3,-6],[1,-5],[2,-6],[-1,-6],[-3,-3],[-1,-5],[0,-5],[-3,-7],[3,-5],[8,-3],[17,-4],[5,-3],[0,-8],[2,-8],[1,-13],[3,-4],[5,-3],[1,-4],[-6,-15],[-4,-3],[-4,-4],[7,2],[4,5],[3,10],[4,1],[2,4],[0,9],[-2,8],[0,5],[1,5],[12,9],[6,4],[5,2],[16,2],[7,2],[9,-1],[5,1],[7,1],[6,0],[10,-7],[35,-1],[6,-2],[23,-3],[2,0],[5,3],[15,11],[7,-1],[2,-2],[3,-4],[3,-3],[2,-7],[2,-10],[3,-2],[5,-1],[10,-4],[10,-4],[3,-10],[5,-7],[13,0],[13,2],[13,13],[0,5],[-3,7],[-5,7],[-4,12],[-11,2],[1,3],[4,4],[4,6],[1,5],[-1,10],[10,-1],[11,-1],[20,-4],[16,-2],[9,-3],[5,-3],[6,-2],[2,5],[3,2],[8,-4],[6,-1],[10,1],[13,-2],[14,1],[13,2],[5,0],[5,-2],[8,-6],[15,-7],[13,-2],[15,-6],[14,-3],[11,-4],[2,-1],[0,-2],[1,-2],[9,-2],[16,-14],[-9995,-2],[6,-2],[5,-2],[2,0],[2,0],[3,-3],[2,-2],[11,-4],[5,-5],[5,-5],[-2,1],[-4,4],[0,-4],[1,-3],[6,-3],[7,-2],[4,-2],[1,-2],[1,-4],[-1,-3],[4,1],[3,3],[-2,2],[-11,8],[-3,3],[4,-1],[15,-11],[5,-4],[-2,0],[-1,-3],[1,-1],[2,1],[3,1],[3,-2],[4,-2],[7,-4],[43,-25],[1,-4],[1,-2],[1,-3],[0,-4],[-4,-6],[7,1],[0,1],[2,2],[2,1],[2,-2],[2,-3],[-1,-5],[-1,-3],[0,-7],[1,-5],[2,-2],[1,-3],[0,-8],[-3,-3],[-1,-6],[2,0],[5,-1],[2,-1],[3,-3],[0,-2],[1,-4],[1,-3],[1,-2],[4,5],[1,1],[3,2],[2,-6],[-1,-8],[1,0],[1,0],[1,3],[1,1],[2,3],[2,4],[-2,3],[-2,2],[-5,1],[-3,3],[-1,3],[3,1],[2,2],[2,5],[-1,3],[0,3],[-2,4],[-2,2],[-3,1],[-2,2],[-2,0],[-3,1],[-1,1],[0,1],[3,1],[16,0],[6,2],[2,0],[3,-2],[9,-2],[0,-1],[-2,-1],[-3,-5],[0,-2],[0,-4],[2,0],[3,1],[-2,3],[0,3],[1,2],[1,0],[3,-3],[2,0],[9,-1],[3,0],[1,1],[-2,2],[-12,3],[0,2],[11,-3],[5,-2],[5,-1],[6,0],[7,-2],[6,-7],[6,-8],[6,-5],[6,-3],[10,-10],[2,-1],[1,-1],[-2,-2],[-2,-2],[3,1],[4,1],[1,0],[2,-1],[1,-2],[0,-2],[-1,-2],[10,0],[3,-1],[1,-5],[-3,-4],[-1,1],[-2,1],[-1,0],[-5,-1],[-6,-5],[-4,-3],[-1,-3],[1,-6],[-1,-4],[-3,-2],[-6,2],[-3,1],[-3,2],[-3,2],[-4,4],[-2,0],[-1,-1],[2,-2],[3,-3],[4,-4],[2,-5],[-1,-2],[-2,0],[-1,0],[-4,1],[-3,0],[-9,-1],[-3,-1],[-1,1],[-1,2],[-4,1],[-3,1],[-2,0],[-1,2],[-3,3],[-5,1],[-3,1],[-2,-1],[7,-4],[5,-7],[-1,-1],[0,-1],[3,-1],[2,1],[0,-2],[-1,-7],[-1,-1],[-10,-2],[2,-1],[3,-1],[3,1],[2,-1],[2,-5],[0,-5],[-2,-2],[-3,-2],[-5,-4],[-6,-1],[-3,0],[-3,0],[-1,-2],[-1,-2],[2,1],[3,0],[3,-2],[0,-2],[-3,-2],[0,-1],[1,-3],[-1,-2],[1,-1],[3,0],[4,-2],[4,-2],[1,-1],[1,-3],[1,-2],[-1,-1],[-8,0],[-1,0],[-1,3],[-1,2],[-3,1],[-1,-1],[1,-8],[-1,-2],[-2,-2],[-4,-1],[-3,1],[-3,4],[0,3],[2,2],[0,2],[-1,3],[-2,-3],[-2,-3],[-3,-4],[-2,0],[-2,0],[-5,3],[-2,2],[-6,7],[-3,4],[-7,4],[-7,4],[-6,2],[-3,0],[-3,-1],[-4,0],[-1,1],[-2,2],[-1,1],[-5,5],[-4,3],[0,3],[1,3],[-1,7],[-2,7],[-4,7],[-13,4],[-11,3],[-3,1],[-4,-1],[-8,-5],[-6,-1],[-17,0],[-3,0],[-2,3],[-1,3],[1,6],[0,2],[-1,1],[-1,0],[-3,3],[-3,4],[-3,4],[-2,5],[3,0],[3,-1],[0,1],[1,5],[2,3],[1,2],[2,7],[0,4],[-3,-2],[-3,-7],[-2,-2],[-2,-1],[-1,0],[-3,1],[-2,2],[0,6],[-1,2],[-1,-1],[-1,-3],[-2,0],[-2,-1],[1,-4],[0,-3],[-3,-2],[-5,0],[-2,3],[-2,-5],[-1,-5],[0,-6],[2,-6],[2,-3],[5,-4],[3,-3],[0,-3],[0,-4],[-3,-4],[-2,-3],[-3,-8],[-2,-4],[-8,-6],[9994,-2],[-5,-7],[-5,-6],[-9,-2],[-12,-9],[-5,-1],[-7,4],[-15,2],[-4,4],[-7,9],[-2,1],[-2,4],[-9,3],[-7,-2],[-6,2],[-2,-2],[3,-1],[6,-1],[8,1],[3,-1],[2,-3],[3,-5],[-2,-4],[-2,-1],[-7,4],[-8,-1],[-3,1],[-10,6],[-8,-6],[-11,-4],[-8,0],[-15,-6],[4,0],[11,4],[6,0],[10,2],[5,3],[2,2],[3,2],[4,-1],[2,-2],[1,-4],[2,-4],[-2,-3],[-2,-1],[-2,-3],[10,5],[6,-3],[3,1],[6,5],[9,3],[2,-1],[1,-1],[-2,-10],[1,-7],[7,-8],[7,-5],[3,0],[2,1],[1,4],[2,3],[2,-3],[2,-3],[3,-8],[0,-2],[-1,-4],[2,-2],[4,-1],[1,-7],[1,-10],[-2,-1],[-1,0],[-5,-3],[0,-1],[6,-1],[1,-2],[-1,-5],[0,-2],[2,-1],[1,3],[0,4],[0,2],[4,-8],[0,-4],[3,-3],[8,-6],[2,-2],[0,-4],[-2,-1],[-2,-3],[2,-4],[2,-3],[3,-1],[2,-6],[0,-4],[-3,-5],[-5,-6],[-3,-2],[-1,-4],[0,-5],[-3,1],[-2,1],[-26,11],[-10,2],[-9,1],[-1,0],[0,3],[0,2],[2,3],[-1,3],[-1,0],[-1,-2],[-3,0],[-2,2],[-2,0],[-1,-3],[0,-2],[0,-2],[1,-2],[5,-2],[-1,-2],[-7,-1],[-6,-2],[-7,-5],[-3,-4],[-20,-9],[-5,-4],[-2,0],[-2,-1],[-3,-4],[-10,-6],[-3,1],[-3,-5],[-2,-2],[-7,-1],[-4,-1],[-9,-7],[-5,3],[-7,-10],[-7,-8],[-2,0],[-5,3],[-2,-2],[1,-3],[2,-4],[-1,-1],[-2,1],[-2,0],[-1,-1],[0,-2],[-3,-4],[-2,0],[-3,-1],[-1,-3],[1,-3],[-5,-4],[-4,-5],[-2,0],[-2,-3],[-3,-1],[-3,0],[-6,-6],[-15,-12],[-5,-2],[-5,-3],[0,-3],[0,-3],[-3,-4],[-2,-13],[-1,-2],[-1,-2],[-5,1],[-5,5],[-2,2],[-1,2],[0,4],[-1,2],[-1,1],[-5,10],[-10,7],[-1,2],[-12,-2],[-4,0],[-5,2],[-9,-1],[-11,-4],[-4,-2],[-11,-4],[-7,-6],[-14,-20],[-4,-5],[-1,-1],[-3,0],[-1,4],[0,4],[1,6],[2,5],[1,10],[1,4],[1,4],[-5,-1],[-6,-7],[-10,-7],[-5,-1],[-4,-5],[-2,0],[-3,-2],[-1,-8],[-1,-5],[-2,-1],[-3,0],[-2,1],[-3,8],[-4,3],[-2,1],[-2,-1],[-3,-5],[-4,-4],[0,5],[-3,2],[-3,1],[-4,0],[-1,-1],[-1,-3],[-3,-3],[-2,-2],[-3,-3],[-1,-3],[-1,-4],[-2,-11],[0,-12],[-5,-10],[-2,1],[-1,-1],[-1,-1],[2,-6],[-1,-2],[-1,-1],[-2,-1],[-6,-8],[-5,-6],[-9,-15],[-3,-10],[-2,-11],[1,-6],[1,-3],[2,-3],[3,-2],[5,-3],[0,-2],[0,-2],[2,3],[2,8],[3,3],[2,-1],[12,-6],[2,-3],[0,-6],[-1,-2],[-2,-5],[-4,-5],[-5,-6],[-1,-5],[0,-2],[2,-8],[0,-5],[-1,-8],[0,-4],[2,-3],[2,-2],[3,1],[3,-1],[3,-2],[0,-7],[1,-7],[1,-12],[-2,-4],[-2,-2],[-4,-5],[-2,-1],[-4,2],[-5,10],[2,5],[5,4],[2,3],[2,4],[-3,0],[-2,-2],[-5,1],[-3,-2],[-2,-4],[1,-8],[-2,-1],[-4,-3],[-5,-3],[-2,-3],[-4,-14],[-4,-11],[-2,-9],[1,-8],[1,-8],[1,-4],[5,-8],[2,-7],[1,-8],[-4,-3],[-7,-9],[-2,-1],[-10,0],[-4,5],[-6,-2],[-4,-2],[-7,-6],[-6,-8],[-6,-6],[-2,-3],[-3,-7],[-2,-13],[1,-7],[1,-3],[1,-4],[-1,-6],[0,-4],[3,-6],[0,-8],[-2,0],[-5,6],[-5,0],[-12,-7],[-6,-4],[-5,-8],[-2,2],[-1,4],[-2,2],[-3,-1],[-1,-4],[4,-2],[1,-3],[-2,-10],[-2,-4],[1,-10],[0,-4],[-1,-5],[-4,-12],[-6,-16],[-8,-12],[-5,-4],[-3,-3],[-1,-4],[-8,-11],[-10,-12],[-3,-2],[0,4],[-1,4],[-1,6],[-4,5],[0,4],[-1,6],[0,25],[-3,26],[0,8],[-4,7],[-2,7],[-2,7],[0,8],[-4,42],[-1,11],[-6,34],[-2,20],[-2,19],[0,9],[3,25],[2,16],[7,36],[1,4],[1,1],[13,14],[6,8],[3,8],[4,10],[-1,5],[0,3],[-2,4],[-3,4],[1,2],[2,1],[3,2],[6,-3],[7,1],[6,13],[8,-2],[7,2],[2,-1],[1,4],[3,5],[7,7],[10,8],[5,5],[2,6],[4,5],[4,6],[7,18],[14,16],[6,9],[4,3],[4,1],[10,13],[7,10],[8,7],[3,5],[4,11],[2,3],[5,4],[13,7],[7,7],[11,1],[3,3],[3,1],[4,3],[-5,6],[1,3],[1,2],[8,7],[3,6],[-1,3],[0,1],[-5,3],[1,5],[1,5],[4,4],[1,10],[1,9],[3,15],[3,3],[8,7],[2,0],[6,-2],[7,-1],[2,-3],[1,2],[-1,3],[2,1],[4,-1],[-1,2],[-9,2],[-7,3],[-7,6],[-4,1],[-4,0],[-26,-8],[-1,-3],[-1,-3],[1,-5],[-1,-2],[-1,-1],[-2,-3],[-1,-6],[0,-6],[-3,-9],[0,-6],[6,-3],[1,-2],[-2,-4],[-1,-1],[-2,-3],[-1,-1],[-1,0],[-2,3],[-2,6],[-3,0],[-1,-1],[-1,-2],[-2,0],[-3,1],[-3,-1],[-6,-7],[-32,-33],[-3,-4],[-4,-8],[-8,-1],[-3,-1],[-3,-3],[-3,-2],[0,3],[1,3],[1,6],[4,11],[-3,1],[-2,0],[-5,-2],[-4,-4],[-2,1],[1,3],[3,7],[-1,6],[-1,3],[2,2],[6,12],[2,7],[2,8],[0,3],[0,3],[-2,0],[-1,0],[-13,-8],[-5,-2],[-1,3],[-3,2],[-3,6],[-3,1],[-3,-1],[-7,-4],[-8,-2],[-6,1],[-5,-4],[-2,0],[-8,2],[-9,0],[-3,-3],[-7,-4],[-6,-6],[-3,-2],[-3,-3],[-1,-12],[-4,-4],[-4,-3],[-8,-9],[-6,-13],[-3,-5],[-8,-8],[-13,-10],[-11,-16],[-4,-12],[-1,0],[-3,-3],[-1,-6],[0,-4],[-1,-3],[-2,-4],[2,-3],[1,-1],[3,1],[6,3],[11,-5],[5,-5],[0,-5],[0,-5],[-4,0],[-5,0],[-4,-3],[-6,5],[-3,-2],[-3,-5],[-7,-2],[-3,3],[-6,6],[-9,-1],[-2,-7],[-2,1],[-4,-1],[-5,-8],[-2,-1],[-7,1],[-5,5],[-2,0],[-4,-2],[-2,-5],[-11,-3],[-10,1],[-6,12],[11,5],[6,-1],[7,0],[8,4],[-3,3],[-2,1],[-4,-1],[-4,3],[-9,11],[-4,2],[-5,2],[-4,0],[-1,-1],[-2,-3],[-1,-3],[-1,0],[-3,0],[-3,2],[-4,0],[2,1],[3,2],[-6,2],[-3,3],[-4,1],[-15,6],[-6,0],[-4,-2],[-6,-6],[2,-4],[1,-2],[1,-2],[-2,0],[-6,-1],[-4,4],[-2,-5],[1,-4],[4,1],[2,-2],[-1,-5],[-6,-1],[-6,0],[-7,9],[-10,-2],[-5,-5],[-5,-1],[-13,5],[-7,1],[-7,4],[-3,-1],[-5,-12],[-6,-3],[-3,2],[-3,7],[-2,3],[-6,2],[-29,-2],[-10,2],[-8,0],[-9,-4],[-9,1],[-17,-7],[-7,-5],[-9,-9],[-7,-15],[-4,-5],[-8,-7],[-10,-6],[-5,-7],[-3,-5],[-5,-20],[-2,-3],[-12,-7],[-4,-8],[-1,-2],[-6,-4],[-3,-5],[-1,-2],[-8,-4],[-6,-10],[-8,-7],[-12,-19],[-2,-3],[-1,-5],[-1,-4],[-11,-17],[-3,-1],[-6,-8],[-5,-5],[-5,-5],[-6,-6],[-9,-7],[-3,-4],[-5,-9],[-12,-11],[-6,-3],[-8,-10],[0,-2],[-1,-3],[1,-7],[2,-1],[3,-1],[12,-6],[11,1],[9,0],[4,1],[2,0],[1,-4],[0,-6],[-2,-6],[-1,-16],[-1,-8],[1,-7],[2,-1],[3,3],[3,0],[4,-1],[3,12],[-3,1],[-2,5],[2,3],[6,5],[4,1],[4,-1],[-4,-7],[-2,-1],[-1,-1],[-2,-1],[4,-4],[4,-4],[6,-1],[-1,-2],[-4,-3],[-4,-9],[-6,-4],[-2,-3],[1,-2],[2,0],[11,1],[6,2],[8,7],[4,11],[3,3],[1,0],[1,-1],[0,-7],[-4,-9],[-3,-4],[-2,-4],[2,0],[4,0],[2,2],[4,10],[1,8],[0,10],[0,6],[0,4],[-1,4],[1,2],[11,-6],[6,-2],[11,5],[2,-1],[2,-3],[9,-9],[2,-3],[3,-11],[9,-12],[9,-6],[0,-2],[6,-7],[4,-3],[1,-6],[-2,-5],[-4,-5],[-8,5],[-2,0],[1,-3],[6,-8],[5,-4],[0,-10],[0,-6],[-4,-7],[1,-4],[5,-5],[2,-3],[2,-3],[-3,-7],[0,-8],[-3,-3],[-4,-8],[-5,-6],[-3,-12],[-4,-10],[0,-11],[-1,-3],[-4,-11],[-1,-15],[2,-24],[1,-1],[1,-2],[0,-1],[-1,-1],[-3,-7],[0,-5],[1,-4],[0,-10],[-2,-15],[-1,-2],[-1,-4],[0,-4],[-1,-2],[0,-4],[0,-3],[2,-2],[-5,-11],[-1,-14],[-2,-6],[-3,-6],[-7,-8],[-2,-5],[-4,-7],[-4,-5],[-6,-15],[-5,-14],[-11,-19],[-2,-4],[-1,-5],[-3,-9],[-1,-11],[-4,-5],[-3,-12],[-9,-19],[-2,-6],[-8,-10],[-7,-15],[-10,-12],[-2,-6],[-3,-6],[-4,-9],[-6,-8],[-1,-6],[-2,-5],[-4,-3],[-4,-3],[-9,-24],[-1,-4],[0,-3],[-7,-9],[-3,-9],[-6,-6],[-6,-8],[-15,-14],[-4,-5],[-9,-7],[-3,0],[-7,-4],[-5,-4],[-3,2],[-2,4],[-2,0],[-1,0],[-5,4],[-3,0],[-3,2],[-5,-1],[1,20],[-1,5],[-2,-4],[-5,-8],[-3,-1],[-2,0],[1,4],[3,7],[-1,1],[-1,0],[-4,-3],[-2,-3],[-6,-12],[-3,-10],[-3,-3],[-1,-4],[-3,-4],[-3,1],[-2,-1],[-6,3],[-1,-1],[3,-8],[-2,-11],[-2,-2]],[[7991,9684],[-3,-3],[-3,-1],[-4,2],[-10,0],[-16,3],[5,1],[26,1],[1,0],[4,-3]],[[7951,9688],[-3,0],[-4,1],[1,3],[8,0],[3,4],[5,0],[2,-1],[1,-2],[0,-1],[-1,0],[-5,0],[-1,-1],[-6,-3]],[[7857,9749],[-3,-5],[-1,-4],[-8,-13],[-1,-2],[5,2],[4,4],[3,4],[3,2],[3,0],[4,1],[6,3],[7,2],[4,0],[3,-2],[2,-3],[3,-3],[8,-2],[2,-1],[0,-2],[0,-3],[5,-2],[7,1],[3,-1],[4,-1],[2,-3],[1,-2],[1,-4],[1,-4],[0,-6],[-14,-8],[-2,-1],[-6,1],[-7,-1],[-16,-5],[-20,0],[-5,-4],[-2,0],[-2,1],[-1,1],[-12,-1],[-14,0],[-14,0],[-4,-3],[-14,-6],[-13,-4],[-6,-1],[-10,1],[-3,2],[-3,2],[4,2],[3,6],[4,3],[10,6],[1,2],[1,6],[2,2],[1,1],[1,3],[0,3],[1,3],[4,4],[2,2],[3,0],[7,0],[3,0],[-2,1],[-1,5],[0,2],[1,3],[2,1],[2,1],[1,5],[-1,1],[3,2],[1,3],[3,1],[7,2],[0,3],[1,2],[2,1],[3,0],[2,0],[2,-3],[3,-3],[3,0],[4,0],[-3,3],[1,4],[1,2],[1,1],[4,0],[10,-2],[7,-4],[2,-2],[-1,-1],[-3,0],[-2,-1]],[[7117,9772],[4,-2],[2,1],[25,-5],[5,-2],[2,-1],[-22,-1],[-5,0],[0,3],[-5,0],[-8,2],[-3,3],[0,1],[3,1],[2,0]],[[7781,9769],[-6,0],[0,4],[1,1],[3,0],[2,-1],[4,0],[-4,-4]],[[7574,9774],[-7,-1],[-8,1],[-13,6],[-9,2],[-6,4],[-2,5],[4,2],[6,2],[9,0],[12,-1],[11,-3],[25,-3],[9,-2],[-6,-5],[-6,-2],[-6,-2],[-6,-2],[-7,-1]],[[6427,9788],[1,0],[0,-1],[-10,1],[-17,-1],[-10,4],[10,3],[6,0],[7,3],[9,-3],[0,-2],[0,-1],[2,-1],[2,-2]],[[6657,9789],[-10,-2],[-3,1],[-1,1],[-2,1],[-5,1],[1,3],[1,1],[15,4],[7,-3],[4,-5],[-7,-2]],[[7712,9801],[7,-4],[3,-4],[-3,-1],[-3,-3],[-1,-3],[-4,-3],[-1,-4],[2,-1],[2,1],[4,4],[5,3],[6,-2],[2,1],[4,4],[0,3],[1,2],[2,1],[8,-1],[11,-1],[3,-2],[2,-1],[2,-2],[5,-1],[3,-1],[4,-3],[3,-4],[-4,-2],[-2,-4],[-1,-1],[-1,-2],[0,-3],[-1,-3],[-1,-2],[0,-1],[0,-5],[-1,-3],[-4,-3],[-4,0],[-6,2],[-2,0],[-2,-1],[8,-4],[6,-5],[6,-2],[2,0],[2,-6],[1,-2],[-11,-6],[-3,-1],[-17,-1],[-11,-2],[-4,0],[-6,2],[-4,-1],[-6,1],[-4,0],[-8,2],[-9,4],[-2,2],[-2,1],[-10,1],[-2,1],[-16,-1],[-2,1],[-5,5],[-3,0],[-8,-3],[-3,0],[-7,2],[-4,2],[0,1],[0,3],[-4,2],[-5,5],[-3,5],[-12,3],[-8,1],[-6,-1],[-5,3],[9,7],[12,4],[5,4],[6,4],[3,6],[10,4],[3,2],[4,3],[1,0],[8,-4],[2,1],[1,2],[3,2],[10,0],[8,-1],[4,1],[3,0],[20,2],[13,1],[2,0]],[[6390,9796],[-3,-1],[-10,5],[-1,1],[9,4],[10,-1],[2,-2],[-7,-4],[0,-2]],[[6540,9807],[-7,-2],[-5,0],[-1,1],[3,3],[4,1],[3,0],[2,-1],[1,-2]],[[6585,9812],[1,-2],[0,-7],[-1,-3],[0,-3],[-3,-1],[-22,0],[-10,1],[-3,1],[6,3],[2,2],[0,7],[1,1],[17,0],[2,2],[6,0],[4,-1]],[[6486,9802],[-18,0],[-7,0],[0,1],[-2,0],[-6,1],[-3,3],[1,1],[9,1],[3,1],[1,2],[4,3],[9,0],[4,0],[0,-2],[4,-3],[10,-3],[-2,-2],[-3,-1],[-4,-2]],[[6609,9799],[-4,-1],[-11,2],[-2,1],[-2,2],[-1,8],[0,2],[-1,1],[-3,3],[-2,2],[2,1],[12,-1],[27,-1],[13,-2],[4,-2],[4,-3],[-23,-1],[-4,-1],[0,-3],[0,-3],[-3,0],[-6,-4]],[[6511,9819],[-4,-3],[-13,3],[1,2],[2,0],[0,2],[-2,1],[1,3],[8,-2],[1,-1],[6,-1],[1,-3],[-1,-1]],[[6317,9841],[13,-3],[9,1],[3,0],[3,-1],[3,-1],[4,-4],[0,-5],[-2,0],[-16,2],[-7,5],[-2,1],[-3,-2],[-3,-3],[-3,0],[-3,-4],[-3,0],[-1,0],[-4,-3],[-9,0],[-2,-1],[-3,-4],[-3,-1],[-7,-1],[-2,3],[-1,3],[-2,1],[-9,-1],[-7,1],[-6,2],[-7,1],[6,2],[33,5],[13,1],[7,4],[9,2],[2,0]],[[6726,9840],[2,-3],[-1,-3],[-2,-3],[-1,-4],[-9,-1],[-2,-1],[-3,-3],[-8,-1],[-7,-5],[-9,1],[-12,3],[-11,-3],[-7,0],[-8,4],[-1,1],[-1,3],[1,2],[2,6],[3,3],[1,1],[2,2],[3,1],[11,1],[4,-1],[1,-2],[5,0],[10,1],[13,2],[8,2],[7,0],[7,-1],[2,-2]],[[6396,9845],[4,-1],[11,0],[3,-1],[15,-8],[3,-1],[4,-3],[-16,-5],[-5,-3],[-19,-1],[-12,-2],[-3,-1],[2,-3],[-6,-3],[-19,0],[-3,-1],[-3,-3],[0,-1],[6,0],[1,-1],[1,-1],[1,-2],[-1,-3],[-3,0],[-2,0],[-6,2],[-1,-1],[-1,-1],[-1,-3],[-3,-1],[-6,2],[-2,0],[-2,-2],[-2,0],[-6,-1],[-3,2],[3,2],[7,4],[-2,1],[-7,1],[-6,-1],[-3,-2],[-2,-1],[-7,0],[-4,3],[-3,2],[-3,2],[21,8],[7,4],[7,1],[8,1],[3,1],[3,0],[2,0],[4,-3],[13,0],[3,3],[0,5],[-1,4],[2,6],[8,3],[17,3],[4,0]],[[7222,9841],[-26,-3],[-2,2],[-1,1],[4,4],[3,2],[16,1],[13,-2],[4,-1],[-1,-2],[-1,-1],[-9,-1]],[[6698,9846],[-9,-1],[-14,2],[-7,1],[0,1],[2,1],[12,4],[24,1],[4,-3],[-3,-2],[-9,-4]],[[6519,9856],[21,-6],[20,1],[8,-2],[12,-5],[18,-5],[4,-2],[-3,-2],[-21,-5],[-14,-2],[-12,0],[-5,0],[-5,4],[-12,3],[-12,-1],[-1,2],[-3,1],[-4,0],[-9,2],[0,3],[5,2],[4,0],[1,4],[6,8],[2,0]],[[6628,9852],[4,-3],[1,-4],[3,-2],[0,-3],[-2,-3],[-6,-1],[-10,0],[-9,1],[-5,6],[-10,1],[-5,6],[5,2],[7,-1],[11,5],[1,0],[3,-1],[9,-2],[3,-1]],[[6409,9852],[-4,0],[-2,0],[-3,2],[-1,1],[-1,1],[3,1],[1,1],[1,0],[2,1],[3,0],[5,-1],[2,-2],[-5,-3],[-1,-1]],[[6760,9832],[-5,0],[-6,1],[-6,3],[-7,3],[2,2],[6,2],[9,4],[13,1],[7,0],[7,1],[2,2],[1,4],[1,3],[2,1],[7,2],[6,0],[7,-2],[4,-1],[3,-3],[2,-2],[0,-3],[0,-3],[2,-2],[-12,-6],[-13,-4],[-32,-3]],[[7543,9857],[-10,-4],[-34,3],[-2,2],[0,1],[4,3],[29,-1],[10,-1],[3,-3]],[[7681,9854],[1,-3],[3,-2],[2,-2],[18,-7],[8,-1],[4,-1],[1,-2],[-1,-4],[-3,0],[-2,-1],[-12,-2],[-3,-2],[-3,-4],[2,-1],[1,-2],[4,-7],[1,-2],[3,-1],[-3,-3],[-3,-1],[-37,-4],[-25,-2],[-8,-1],[-3,0],[-7,-3],[-12,-4],[-6,0],[-18,6],[-23,4],[-3,3],[-5,1],[-7,1],[-3,5],[4,4],[6,3],[10,1],[9,2],[7,5],[4,5],[8,5],[-14,-1],[-5,1],[1,1],[3,4],[1,1],[5,2],[3,4],[9,2],[3,1],[4,-1],[7,2],[7,1],[7,1],[6,1],[7,1],[6,3],[3,5],[17,0],[3,-1],[2,-3],[3,-1],[3,0],[8,-5],[2,-1]],[[6647,9867],[-6,-1],[-11,1],[-3,2],[1,1],[7,2],[5,0],[6,-2],[3,-2],[-2,-1]],[[6605,9881],[2,-3],[4,-1],[12,-1],[3,-3],[-5,-1],[-14,-2],[1,-3],[3,-3],[-3,-3],[-4,-2],[-9,-2],[-8,3],[-9,3],[-5,-2],[-4,-2],[-4,1],[-5,2],[-13,-2],[-4,2],[-3,5],[9,1],[10,-1],[7,5],[9,2],[7,5],[3,1],[8,0],[2,1],[8,1],[2,-1]],[[6767,9884],[-3,0],[-18,0],[-9,2],[-1,1],[-11,1],[4,2],[15,1],[25,-2],[2,-1],[0,-1],[-4,-3]],[[6619,9890],[-10,-1],[-1,1],[0,1],[1,1],[1,3],[4,2],[32,1],[4,-1],[-2,-3],[0,-1],[-29,-3]],[[5847,5122],[-1,-1],[0,-2],[1,-5],[3,-9],[2,-2],[2,-3],[1,-6],[1,-8],[-1,-9],[1,-7],[1,-4],[0,-6],[0,-7],[-1,-4],[-1,-1],[-1,-1],[-1,1],[-2,-1],[-2,-1],[-1,0]],[[5821,5104],[1,0],[6,3],[1,-1],[0,-6],[1,-1],[1,0],[1,1],[4,5],[1,3],[2,4],[2,4],[1,4],[1,2],[1,1],[2,-1],[1,0]],[[4526,6382],[-1,3],[2,30],[0,3]],[[6166,6147],[2,-1],[-1,2],[0,1],[1,3],[3,-6],[0,-6],[-1,-2],[0,2],[-1,1],[0,1],[-1,2],[-3,-1],[-2,2],[-2,5],[-1,4],[1,1],[1,2],[1,3],[-1,3],[2,0],[1,-4],[0,-7],[0,-2],[0,-1],[1,-2]],[[6024,6646],[-2,4],[-1,3],[-2,2],[-5,3],[-1,3],[1,2],[1,-2],[1,-2],[4,-3],[5,-8],[1,0],[-2,-2]],[[6016,6665],[0,-1],[-1,2],[0,5],[1,2],[0,-3],[0,-4],[0,-1]],[[6345,6828],[2,-6],[0,-5],[3,-13],[4,-10],[1,-3],[1,-6],[-1,-2],[0,-2],[3,-6],[5,-4],[2,-2],[2,-2],[-2,-3],[3,-7],[4,-8],[3,-1],[5,-12],[8,-7],[4,-9],[0,-1],[-1,1],[-2,2],[-1,-2],[1,-4],[0,-4],[2,-4],[2,-3],[1,-6],[-1,-12],[-1,0],[-1,1],[-1,0],[-1,0],[2,-9],[1,-6],[2,-6],[1,-7],[1,-4],[5,-8],[1,-7],[2,-12],[3,-7],[1,-6],[3,-4]],[[6423,6601],[2,-2],[2,0],[1,-2],[-2,-3],[-1,-8],[2,-1],[2,-1],[2,-1],[1,0]],[[6443,6278],[-6,-2],[-7,-2],[-7,-2],[-8,-2],[-7,-2],[-10,-3],[-9,-2],[-8,-2],[-8,-3],[-7,-2],[-4,-2],[-5,-5],[-8,-8],[-8,-7],[-4,-4],[-4,-11],[-2,-5],[-4,-9],[-3,-8],[-3,-8],[-1,-8],[-3,-12],[-2,-3],[-3,-3],[-3,-3],[-5,0],[-2,8],[-3,7],[-2,3],[-1,0],[-5,-1],[-5,-1],[-7,2],[-8,1],[-7,1],[-3,1],[-5,5],[-1,1],[-2,1],[-5,0],[-6,0],[-5,-2],[-6,1],[-5,-1],[-2,-2],[-2,0],[-2,-2],[-1,0],[-1,1],[-2,0],[-2,1],[-2,3],[-2,3],[-1,2],[-2,1],[-2,0],[-2,-2],[-1,-2],[-3,-5],[0,-2],[1,-4],[0,-1],[-2,-2],[0,-6],[-1,-2],[0,-7],[1,-6],[1,-2],[0,-2],[-1,-5],[-1,-1],[-1,-5],[-1,-2],[-2,-2],[-5,-8]],[[6188,6127],[0,4],[-2,7],[0,5],[-1,5],[-1,4],[-3,3],[0,6],[-2,5],[-2,4],[-2,8],[-1,10],[-6,14],[-9,12],[-2,7],[-5,14],[-2,12],[-5,13],[-1,5],[0,6],[-2,7],[0,5],[-6,23],[-2,4],[-2,5],[0,4],[0,3],[-4,4],[-4,9],[-11,16],[-6,2],[-4,5],[-3,8],[-4,12],[-6,14],[-5,19],[2,7],[0,5],[-2,9],[-1,6],[-2,6],[1,9],[1,10],[1,5],[0,6],[-1,11],[-1,6],[0,4],[-2,2],[-2,5],[2,0],[-3,6],[-1,3],[-1,9],[-1,6],[-5,15],[-2,9],[-5,11],[-5,9],[-4,3],[-1,4],[-3,0],[-3,5],[-2,0],[-3,1],[-3,10],[-2,9],[-5,11],[1,3],[2,5],[-1,7],[-1,4],[-2,9],[-6,20],[-2,3],[-2,3],[-2,9],[-1,8],[-4,3],[-8,29],[-4,9],[-2,7],[-5,11],[-2,11],[-5,10],[-5,17],[-6,18],[-3,3],[-7,1],[-3,1],[-3,-4],[0,5],[2,7],[3,14],[0,12],[4,37]],[[6024,6451],[0,-13],[1,-11],[4,-15],[4,-8],[1,-4],[0,-2],[0,-2],[-1,2],[-2,1],[0,-7],[1,-5],[0,-9],[1,-10],[-1,-9],[1,-16],[1,-19],[0,-12],[3,-29],[3,-15],[2,-4],[2,-2],[3,-1],[6,-8],[4,-9],[2,-4],[2,-5],[1,1],[1,1],[1,-4],[7,-8],[1,-4]],[[5946,5729],[-5,0],[-1,1],[0,1],[0,3],[0,4],[1,6],[2,7],[0,1],[0,2],[-1,1],[0,1],[1,4],[0,1],[0,2],[0,1],[-2,6],[0,1],[-12,21],[-2,5],[-1,0],[0,1],[-6,4],[0,1],[0,1],[1,3],[0,1],[0,1],[-3,42],[0,1],[0,1],[1,1],[0,1],[0,2],[1,8],[0,7],[1,11],[1,4],[-14,1],[0,-1],[0,-1],[0,-2],[0,-1],[0,-3],[1,-2],[0,-1],[0,-1],[-19,-1],[8,-16],[0,-1],[0,-1],[0,-6],[0,-10],[0,-6],[0,-3],[2,-8],[0,-1],[0,-2],[-14,-23],[0,-1],[-2,-10],[-1,-5],[-1,-2],[-3,-7],[-12,-25],[-2,-1],[-6,-1],[-3,0],[-1,0],[0,-1],[-1,-1],[-1,1],[-7,14],[-13,17],[-1,-2],[-8,-7],[-1,-2],[-1,-1],[0,-9],[-2,-4],[-2,-5],[-6,-2],[-4,-3],[-3,-4],[-1,-1],[-1,-2],[-2,-5],[-1,-4],[1,-4],[-22,0],[-2,3],[-3,13],[-2,-1],[-21,2],[-2,-2],[-6,-5],[-3,-1],[-3,2],[-11,26],[-2,3],[-1,1],[-1,5],[-3,3],[0,1],[-1,3],[0,6],[0,3],[-2,1],[-14,-6],[-2,1],[-3,-1],[-1,-1],[-1,-4],[-1,-3],[0,-4],[0,-3],[-1,-4],[-4,-8],[-1,-4],[0,-10],[0,-4],[-1,-3],[-2,-3],[0,-2],[0,-3],[-1,-7],[0,-2],[-2,-8],[-1,-2],[0,-6],[0,-1],[-7,-5],[-2,-2],[-1,-4],[-1,-2]],[[5634,5813],[1,6],[2,9],[0,5],[-1,4],[-2,4],[-2,0],[-1,2],[-1,2],[-2,2],[-1,4],[-1,5],[1,18],[-1,3],[-2,1],[0,1],[0,3],[-1,11],[-2,9],[1,4],[-2,7],[-3,3],[-3,-1],[-3,-1],[-2,0],[-2,1],[-1,3],[0,3],[0,4],[2,8],[2,6],[5,6],[1,3],[1,4],[0,4],[0,4],[-1,4],[-1,5],[-1,6],[0,4],[0,3],[1,3],[3,4],[0,1],[2,2],[1,1],[4,5],[1,2],[-1,2],[-1,2],[-1,3],[0,3],[-1,6],[0,3],[-1,3],[1,2],[2,3],[1,1],[3,2],[1,2],[1,4],[-1,3],[1,3],[2,6],[1,2],[2,3],[1,4],[1,4],[0,5],[-1,12],[3,6],[2,4],[4,0],[6,1],[4,2],[3,0],[7,-3],[0,1],[1,4],[0,8],[0,26],[0,26],[0,25],[0,26],[0,26],[0,25],[0,26],[0,26]],[[5943,5427],[-6,-14],[-5,-10],[-1,-1],[-1,-2],[-5,0],[-5,1],[-4,6],[-4,-4],[-3,-2],[-2,0],[-4,-1],[-5,-3],[-3,-3],[-1,-2],[-1,-5],[-1,0],[-1,0],[-1,2],[-3,3],[-2,5],[-1,4],[-1,2],[-5,-6],[-2,-1],[-2,0],[-4,3],[-3,3],[-2,0],[-3,-4],[-3,-5],[-2,-5],[-1,-3]],[[4535,5895],[-1,3],[-1,4],[1,3],[2,2],[4,3],[2,-2],[1,0],[0,2],[-1,1],[-2,2],[-1,3],[-2,-2],[-1,-3],[0,-1],[-2,-1],[0,2],[-1,3],[1,1],[0,11],[0,5],[0,5]],[[4539,5966],[0,6],[-2,5],[-3,4],[0,4],[1,3],[2,3],[1,2],[-1,-1],[-3,-1],[-1,-1],[0,6],[-2,6],[-3,11],[-3,5],[-2,9],[-3,4],[-2,1],[-2,0],[-1,-4],[-3,6],[4,2],[7,7],[9,22],[7,25],[1,6]],[[7887,5260],[-4,-3],[-5,3],[2,6],[3,1],[3,-2],[1,-1],[1,-2],[-1,-2]],[[4270,1818],[0,-3],[-4,3],[-1,1],[1,2],[3,0],[1,-1],[0,-2]],[[3969,2070],[3,-3],[2,2],[2,0],[1,-1],[1,-1],[2,0],[3,-4],[-1,-5],[3,1],[2,-3],[1,0],[1,1],[2,2],[1,-2],[1,-4],[2,-2],[1,-4],[2,-5],[1,-1],[2,0],[2,1],[-1,-5],[0,-4],[3,-3],[-2,-2],[-2,-3],[-4,-1],[-1,0],[-3,5],[-2,5],[-4,7],[-1,2],[0,1],[-4,1],[-3,2],[-2,3],[-1,2],[-1,2],[-3,0],[-2,2],[-3,2],[-9,7],[-4,-1],[-1,2],[0,3],[2,2],[-9,1],[-2,1],[2,1],[11,0],[4,0],[1,-1],[3,-3],[4,0]],[[4841,4262],[-2,0],[0,3],[2,3],[1,-1],[0,-3],[-1,-2]],[[4601,4724],[-1,0],[-1,1],[0,1],[1,2],[0,2],[1,0],[1,-2],[0,-1],[0,-1],[-1,-2]],[[9636,4512],[-2,-1],[-1,0],[-2,5],[1,1],[2,0],[0,-3],[2,-2]],[[9460,4504],[-2,-2],[-2,1],[-2,2],[-1,4],[-2,3],[-3,1],[-2,2],[0,1],[-2,1],[-1,2],[0,3],[1,1],[2,-1],[10,-12],[2,-3],[2,-3]],[[9614,4564],[-2,-1],[-1,0],[-2,0],[-2,-4],[-1,0],[-1,0],[-1,4],[0,1],[2,0],[0,3],[2,2],[3,1],[3,-1],[1,-1],[-1,-3],[0,-1]],[[9491,4586],[4,-4],[2,1],[3,-3],[2,2],[1,-3],[4,-12],[0,-4],[2,-3],[-2,0],[-2,1],[-3,-1],[-2,3],[-4,1],[-3,3],[-7,8],[0,5],[-1,2],[0,5],[-3,2],[-3,0],[0,3],[1,4],[2,0],[2,-2],[5,-6],[2,-2]],[[9486,4629],[1,-6],[0,-2],[-2,5],[-1,-2],[-1,2],[0,5],[0,5],[-1,4],[-1,5],[2,-1],[3,-15]],[[9437,4650],[6,-10],[2,1],[8,0],[5,-6],[3,-4],[1,-5],[2,-2],[2,-3],[0,-5],[0,-1],[-3,-2],[-1,-1],[-5,2],[-5,4],[-8,1],[-5,1],[-1,1],[-1,3],[-2,5],[-2,6],[0,3],[0,7],[0,2],[2,3],[2,0]],[[9448,4666],[2,-1],[1,0],[1,-3],[3,-5],[-1,-2],[-2,1],[-1,0],[0,2],[-3,3],[-2,0],[0,2],[2,3]],[[9421,4658],[-2,1],[-1,0],[-1,2],[1,3],[1,2],[1,-1],[1,-1],[1,0],[0,-4],[-1,-2]],[[9378,4679],[0,-2],[-2,1],[-3,3],[0,1],[2,1],[1,-1],[1,-1],[1,-2]],[[9394,4676],[-1,-1],[-1,3],[2,6],[1,-5],[0,-2],[-1,-1]],[[9391,4684],[-3,-5],[-2,2],[-1,3],[0,5],[0,1],[1,1],[1,1],[1,2],[3,-2],[1,-1],[-2,-3],[0,-1],[1,-1],[0,-2]],[[9371,4682],[0,-1],[-2,2],[-3,7],[1,3],[3,5],[1,1],[1,-3],[-1,-5],[-1,-1],[-1,-4],[2,-4]],[[9435,4694],[-1,-1],[-2,2],[-1,2],[0,3],[1,1],[2,-2],[0,-2],[1,-3]],[[9464,4705],[7,-17],[0,-3],[-1,-2],[0,-6],[1,-2],[1,-1],[4,-6],[1,-8],[0,-2],[1,-4],[0,-7],[4,-10],[0,-5],[-1,-2],[-1,1],[-3,12],[-5,5],[0,2],[-4,6],[-3,11],[-3,20],[1,5],[-3,10],[0,2],[2,0],[1,0],[0,1],[1,0]],[[9381,4709],[2,-5],[2,-10],[0,-4],[-2,0],[0,-2],[-2,5],[-3,1],[-1,3],[-1,7],[0,3],[-2,1],[-4,-1],[-1,-3],[-2,1],[-1,3],[1,3],[2,3],[1,3],[2,7],[2,1],[3,-2],[0,-9],[1,-3],[3,-2]],[[9349,4713],[0,-1],[-2,7],[0,3],[1,3],[1,-8],[0,-4]],[[9365,4717],[-1,-1],[-3,0],[-2,6],[0,5],[2,4],[2,0],[1,-1],[1,-4],[1,-4],[-1,-4],[0,-1]],[[9352,4727],[-1,0],[-1,3],[-1,1],[0,3],[-2,6],[-1,4],[2,4],[2,-3],[2,-4],[3,-2],[-1,-3],[-2,-6],[0,-3]],[[9440,4692],[0,-1],[-4,5],[-2,6],[-8,6],[-2,3],[-2,1],[-4,5],[-4,4],[-2,4],[-1,2],[-1,1],[-3,5],[-2,4],[-1,6],[-3,4],[0,2],[7,-3],[4,-7],[3,-4],[1,-3],[3,-3],[2,-1],[3,-4],[2,-1],[2,-2],[11,-17],[-1,-4],[1,-4],[1,-4]],[[9328,4775],[-3,-1],[-2,1],[1,5],[1,2],[4,-4],[-1,-3]],[[9374,4762],[1,-2],[-3,-4],[-2,2],[-1,2],[0,1],[-2,-1],[-4,2],[-5,8],[-6,16],[-6,8],[-1,3],[0,4],[1,2],[3,-2],[5,-7],[7,-7],[2,-4],[1,-9],[2,-3],[4,-7],[2,-1],[1,0],[1,-1]],[[4652,5612],[-1,-1],[-2,3],[-9,6],[2,3],[7,1],[2,-2],[1,-1],[0,-3],[0,-6]],[[4680,5582],[-1,2],[-5,8],[-6,6],[-11,9],[-4,2],[0,3],[1,6],[-2,7],[1,5],[-1,0],[-2,-3],[-3,1],[-3,5],[-1,1],[-1,2],[-1,12],[-1,5],[-2,3],[-4,1],[-1,7],[-2,5],[0,4],[2,-1],[1,-2],[2,-1],[3,6],[2,3],[0,3],[0,1],[-1,-2],[-4,1],[-1,-3],[-2,0],[-1,7],[0,4],[1,4],[3,1],[1,1],[-3,1],[-3,5],[-1,4]],[[2560,5956],[0,-1],[0,-6],[-1,-3],[-2,-3],[-2,-1],[-5,0],[-6,3],[-5,4],[-3,0],[1,-1],[2,-1],[3,-3],[-1,-1],[-10,6],[-11,11],[-7,2],[-8,3],[-4,7],[-4,3]],[[6359,5832],[0,-16],[0,-15],[0,-16],[0,-27],[0,-9],[0,-14],[0,-7],[-4,-12],[-5,-16],[-5,-16],[-5,-14],[-4,-13],[-4,-13]],[[6201,5846],[5,-9],[5,-18],[7,-14],[8,-13],[3,-5],[3,-2],[16,0],[11,12],[10,9],[3,2],[6,-2],[6,-1],[6,-3],[3,1],[11,10],[7,10],[5,4],[2,0],[7,-3],[8,1],[12,9],[4,2],[2,0],[7,-4],[1,0]],[[6359,5832],[3,1],[9,4],[7,6],[13,5],[10,11],[2,6],[3,7],[4,2],[11,-8],[2,-1],[-1,-5],[0,-5],[-2,-9],[-2,-9],[1,-15],[1,-24],[0,-4],[-1,-3],[0,-3],[-2,-1],[0,-2],[1,0],[3,2],[0,3],[0,2],[3,-3],[2,-2],[1,-3],[0,-2],[-4,1],[-1,2],[-5,-3],[-3,-3],[-1,-5],[0,-19],[-2,-12],[0,-16],[-4,-11],[-1,-8],[-6,-15],[-3,-13],[-1,-6],[-5,-18],[-7,-14],[-2,-17],[-3,-11],[-3,-10],[-6,-18],[-3,-12],[-4,-21],[-1,-14],[-11,-39],[-12,-31],[-7,-26],[-13,-31],[-17,-39],[-23,-47],[-7,-9],[-25,-29],[-16,-24],[-8,-17],[-9,-14],[-7,-13],[-21,-46],[-2,-5],[-2,-4],[-3,-7],[-2,-4],[-5,-13],[-3,-7],[-4,-6],[-1,-5],[-1,-5],[-1,-4],[-3,-13],[-3,-8],[-3,-7]],[[3440,7877],[-1,0],[-2,1],[1,1],[1,1],[1,0],[0,-1],[0,-1],[0,-1]],[[3437,7882],[-3,-3],[-1,2],[1,1],[1,4],[0,1],[-2,8],[1,1],[0,1],[2,-2],[0,-2],[-1,-5],[1,-3],[1,-2],[0,-1]],[[5184,5191],[-2,-4],[-1,1],[-1,3],[-1,6],[0,3],[2,3],[3,4],[1,0],[2,-4],[0,-5],[-3,-7]],[[5206,5274],[-1,-1],[-2,1],[0,2],[2,5],[0,1],[1,-1],[0,-1],[0,-2],[0,-4]],[[3411,5503],[0,-1],[1,7],[1,5],[0,6],[2,6],[2,3],[14,-3],[7,-3],[8,-5],[1,-6],[0,6],[0,5],[2,4],[5,2],[7,-2],[7,2],[8,0],[14,-5],[6,-3],[2,-3],[1,-5],[-1,-6],[-1,-6],[-2,-9]],[[5626,8010],[-1,-2],[-1,-3],[-1,-3],[-2,-3],[-1,-8],[-1,-3],[-4,-7],[-1,-9]],[[5377,7806],[1,1],[3,3]],[[5459,8426],[-2,-3],[-1,0],[-1,4],[0,10],[0,5],[6,18],[3,1],[4,11],[1,5],[2,4],[1,4],[0,2],[2,-1],[1,-1],[-2,-2],[0,-3],[0,-1],[-5,-13],[-1,-8],[-1,-2],[-7,-30]],[[5529,8515],[-2,-1],[-1,-4],[-2,-1],[-2,-1],[-1,-13],[4,-5],[-2,-1],[-2,-1],[-1,-2],[-1,-5],[-5,-3],[-1,-2],[-3,-4],[-1,-6],[-3,-3],[-2,-1],[1,5],[2,5],[-2,3],[-1,4],[-2,4],[2,3],[-1,7],[0,6],[2,3],[2,3],[4,6],[3,4],[6,2],[2,-2],[1,4],[1,1],[2,-1],[3,-4]],[[5532,8520],[-1,-4],[-1,1],[-2,2],[3,4],[4,0],[1,-1],[-4,-2]],[[5511,8584],[-1,-1],[-1,0],[1,3],[0,1],[2,1],[1,0],[-2,-4]],[[5516,8609],[-1,-2],[0,3],[0,2],[2,2],[2,-1],[0,-1],[-2,-2],[-1,-1]],[[5670,8974],[-7,-1],[-5,2],[-3,-1],[-5,0],[-6,-1],[-1,-2],[-2,-1],[-5,3],[-5,5],[-3,-4],[-2,-1],[-3,4],[-1,0],[-1,-1],[-1,-3],[-1,-2],[-1,-2],[0,-6],[0,-1],[-5,1],[0,-2],[1,0],[1,-1],[-2,-2],[-5,0],[0,-1],[1,-2],[-1,-2],[-1,-1],[-5,-1],[-4,0],[0,-1],[-1,-2],[1,-1],[1,-1],[1,-1],[0,-2],[-1,-1],[-4,4],[-1,0],[1,-2],[2,-2],[1,-2],[1,-3],[0,-2],[-4,-7],[-4,-4],[-3,-3],[-1,-4],[1,-2],[3,-3],[1,-6],[2,-5],[3,-4],[0,-3],[-1,-2],[-6,-5],[-7,-7],[-7,-18],[-2,-2],[-6,-3],[-3,-3],[-4,-3],[-8,-3],[-4,-5],[-2,-4],[-2,0],[-1,2],[-3,1],[0,-3],[0,-2],[-4,3],[-2,-3],[-1,-4],[-6,-7],[-6,1],[-1,-1],[2,-1],[0,-1],[-1,0],[-1,0],[-3,-1],[-2,0],[-1,-3],[-1,-4],[-3,-1],[-2,-1],[-1,-2],[5,0],[0,-2],[0,-2],[-1,-1],[-6,-3],[-1,-2],[-1,-2],[-2,0],[0,2],[0,1],[-4,0],[-1,3],[-1,-1],[1,-2],[1,-3],[1,-4],[-1,-2],[-1,-1],[1,-1],[2,-1],[0,-2],[-2,-1],[-3,-4],[-3,0],[-2,-3],[-2,0],[-2,2],[-3,1],[-1,-2],[0,-3],[2,-5],[3,-4],[2,-2],[-2,-1],[-1,-3],[-2,-8],[-1,-3],[-1,-6],[1,-5],[0,-2],[2,-3],[-4,0],[-4,2],[1,-4],[-3,-5],[1,-4],[0,-2],[0,-5],[1,-1],[0,-3],[-1,-2],[1,-1],[0,-6],[1,-10],[-1,-1],[2,-9],[0,-2],[0,-4],[3,-3],[2,0],[3,0],[1,-1],[1,-3],[1,-2],[2,0],[4,2],[2,1],[2,-5],[4,-6],[2,-2],[5,-2],[4,-5],[-1,-5],[2,-2],[5,-3],[2,-3],[1,-2],[1,-3],[2,-6],[-1,-4],[-2,-2],[-5,-4],[-2,-3],[-1,-2],[-5,-5],[-2,0],[-2,-3],[-2,-1],[-1,1],[-6,-4],[1,-2],[4,-1],[2,1],[2,2],[2,1],[1,-1],[2,2],[2,1],[1,-1],[2,-4],[-4,-2],[-2,0],[-1,-7],[-2,-2],[-1,-2],[-5,-2],[-3,-4],[-4,-3],[-2,1],[-3,-3],[-6,-3],[-3,-5],[-6,-4],[-4,-3],[-9,0],[-9,1],[-3,-2],[3,0],[2,-2],[2,1],[6,-1],[3,-1],[4,-5],[-3,-2],[-5,-1],[2,-8],[1,-5],[-2,-3],[0,-14],[-3,-1],[-1,-5],[1,-3],[0,-7],[1,-4],[1,-4],[-1,-4],[-4,-10],[0,-4],[1,-3],[1,-4],[-2,-8],[-2,-7],[-1,-6],[-4,-7],[-2,-5],[-4,-16],[-2,-3],[-3,-2],[-3,2],[-2,1],[-4,0],[-5,-2],[-7,1],[-8,0],[-2,-2],[1,-6],[-2,-1],[-3,2],[-3,-2],[-1,-2],[-4,-5],[-2,-3],[0,-6],[2,-6],[2,-6],[-5,-7],[-2,-1],[-8,2],[-13,-4],[-13,3],[2,4],[0,3],[1,5],[0,5],[0,3],[-1,3],[-3,5],[-7,14],[-2,6],[-1,3],[1,0],[5,-3],[2,0],[1,2],[-2,4],[-1,2],[-1,4],[3,1],[3,-1],[1,4],[-1,6],[-2,2],[-2,0],[-4,10],[-4,5],[-8,18],[-3,13],[-2,-2],[-2,6],[0,5],[-1,4],[-4,2],[0,3],[0,12],[-5,2],[-2,6],[-1,13],[-3,2],[-2,0],[0,3],[1,3],[-2,12],[0,10],[-1,4],[-1,3],[1,4],[0,2],[3,0],[3,-3]],[[5891,3638],[0,1],[-2,1],[-1,-1],[-1,-8],[0,-12],[0,-8],[-6,0],[-7,1],[-6,3],[-6,7],[-3,11],[-2,8],[-2,0],[0,1],[0,9],[0,9],[0,2],[4,12],[2,7],[2,6],[3,8],[4,5],[1,1],[1,0],[6,-7],[7,-7],[1,1],[1,1]],[[3249,6225],[0,-2],[0,-1],[-2,1],[-1,1],[0,1]],[[6542,4913],[0,-5],[-1,2],[-1,3],[-1,3],[-1,2],[2,3],[2,-8]],[[5999,7178],[-2,13],[-1,6],[0,6],[2,10],[-1,4],[0,3],[0,4],[-4,9],[2,16],[1,4]],[[5996,7253],[3,-1],[4,-4],[1,0],[1,6],[1,2],[3,2],[1,9],[1,2],[2,1],[2,0],[2,1],[0,2],[-3,11],[1,3],[1,11],[1,4],[1,2],[3,-1],[5,-2],[1,-3],[2,-3],[3,0],[4,0],[3,-1],[3,2],[5,4],[3,1],[2,2],[8,6],[3,0],[3,-1],[1,-1],[4,-4],[3,-4],[2,-2],[4,0],[6,0],[7,0],[4,1],[5,2],[9,5],[12,10],[7,6],[3,0],[4,0],[4,-1],[5,-1],[2,0],[5,1],[6,2],[4,2],[5,3],[3,5],[1,0],[1,-1],[1,0],[1,-3],[1,-7]],[[2990,6442],[4,-3],[2,1],[0,-1],[-1,-1],[-1,0],[-3,-1],[-1,0],[0,2],[0,3]],[[3009,6437],[-2,2],[-3,0],[0,3],[1,0],[4,-1],[1,-2],[-1,-2]],[[3003,6442],[0,-1],[-2,2],[0,2],[-1,0],[-1,1],[0,2],[3,0],[0,-5],[1,-1]],[[5045,5542],[-9,-4],[-4,-3]],[[7768,5559],[-1,0],[-1,5],[1,7],[2,-9],[-1,-3]],[[7751,5621],[1,-7],[-1,2],[-1,3],[0,4],[0,1],[1,-3]],[[7738,5641],[0,-1],[-2,11],[2,-3],[0,-7]],[[7733,5639],[0,-4],[-2,0],[-1,-3],[-1,8],[1,12],[0,2],[1,-3],[3,-1],[-1,-7],[0,-4]],[[7730,5705],[-2,0],[1,3],[0,2],[1,0],[0,-3],[0,-2]],[[7779,5736],[0,-3],[-1,-4],[-2,-3],[-1,4],[0,4],[1,2],[2,-1],[1,1]],[[7779,5742],[0,-1],[-1,2],[-1,2],[0,3],[1,0],[1,-3],[0,-3]],[[7849,5856],[0,-6],[-2,3],[1,3],[0,1],[1,-1]],[[7844,5874],[0,-1],[-1,1],[-2,0],[-1,8],[0,2],[1,-1],[2,-4],[1,-3],[0,-2]],[[7858,5858],[-1,4],[-2,7],[-1,7],[-3,8],[-2,3],[0,-3],[-1,-3],[-3,4],[-3,5],[-2,8],[-1,-2],[0,-2],[-3,6],[-2,6],[-3,1],[-2,2],[-1,3],[-3,3],[-8,-4],[-10,3],[-4,-3],[-1,2],[-1,3],[1,6],[0,13],[1,8],[0,7],[0,3],[1,4],[-2,2],[-7,4],[-1,2],[-2,-3],[-8,-2],[-4,-2],[-3,-5],[0,-6],[1,-5],[2,-7],[-3,-16],[-1,-4],[1,-20],[0,-10],[-2,-7],[-3,-7],[-1,-10],[-2,-6],[-2,-11],[-2,-14],[-1,-7],[-1,-12],[-6,-18],[-1,-11],[-2,-4],[1,-3],[0,-5],[-1,-14],[0,-12],[1,-6],[2,-12],[0,-3],[-1,-6],[3,-2],[1,-1],[9,6],[3,-1],[2,-6],[0,-4],[2,-26],[1,-4],[2,-5],[2,-5],[0,1],[0,2],[1,2],[1,-5],[2,-9],[5,-48],[1,-6],[1,-6],[-3,3],[-1,11],[0,4],[-1,1],[-2,0],[0,2],[1,3],[0,4],[-2,4],[-3,-3],[0,-7],[2,-6],[4,-13],[2,-5],[2,-2],[2,1],[3,-5],[3,-5],[6,-8],[4,1],[4,2],[3,-1],[3,-2],[3,-6],[5,-16],[8,-14]],[[7780,5555],[-7,18],[-4,7],[0,13],[-1,3],[-2,0],[-1,4],[1,7],[-2,-1],[-3,0],[-2,2],[-1,11],[-1,4],[-3,5],[-3,0],[-1,3],[1,7],[-2,4],[-3,4],[-3,2],[-2,11],[-2,3],[-1,2],[-3,-1],[0,-4],[-2,-4],[-2,0],[-1,3],[-2,11],[0,7],[0,13],[3,11],[1,19],[2,12],[1,4],[2,15],[4,21]],[[6962,7542],[-1,0],[-1,2],[-1,2],[1,1],[1,-2],[1,-2],[0,-1]],[[6882,7325],[1,4],[0,14],[1,5],[5,8],[2,7],[2,5],[2,2],[1,4],[2,5],[0,3],[0,3],[-1,1],[-2,4],[-3,5],[-1,5],[-1,6],[0,5],[2,13],[0,2],[-1,2],[-2,1],[-2,1],[-2,-1],[-3,0],[-2,1],[-1,1],[0,5],[-1,2],[0,1],[-6,2],[-2,2],[0,1],[2,13],[1,1],[1,2],[1,2],[5,4],[6,-2],[4,-1],[5,-1],[2,-1],[2,0],[2,0],[1,2],[2,4],[1,6],[1,5],[1,1],[2,-1],[0,1],[1,2],[0,1],[0,1],[1,-2],[1,0],[0,1],[0,2],[-1,1],[-1,4],[0,1],[1,1],[2,1],[2,0],[0,1],[0,2],[-1,1],[-4,-1],[-4,0],[-1,1],[1,1],[0,1],[9,3],[4,-1],[3,-1],[2,0],[-2,5],[2,1],[0,2],[-2,13],[1,2],[2,2],[0,5],[1,3],[1,2],[3,-2],[3,-5],[2,-1],[1,0],[1,1],[7,5],[4,3],[4,4],[1,2],[1,6],[1,0],[1,0],[4,-7],[2,-4],[0,-1],[-1,-1],[1,-1],[3,-3],[0,-1],[-1,-2],[0,-1],[-1,0],[-4,-6],[-5,-6],[0,-1],[0,-2],[0,-1],[1,-1],[2,-1],[2,-2],[0,-3],[1,-3],[2,-1],[7,2],[1,0]],[[6475,7419],[-1,-3],[-1,8],[-1,9],[1,3],[1,0],[-1,-4],[2,-13]],[[6497,7335],[0,4],[-2,15],[-1,14],[0,7],[1,14],[0,7],[0,6],[0,6],[1,7],[0,7],[0,5],[-2,4],[-2,5],[-1,3],[0,3],[-2,1],[-2,3],[-2,2],[-4,2],[-2,0],[-2,-2],[-1,-3],[-1,5],[0,5],[3,10],[2,-3],[2,-1],[3,0],[3,1],[0,3],[-2,2],[-1,2],[-1,4],[0,5],[1,5],[-1,1],[-1,1],[-3,0],[-5,2],[-4,0],[-1,-5],[3,-7],[-2,3],[-2,5],[-3,8],[-2,9],[0,11],[2,8],[1,8],[2,10],[1,11],[2,-5],[1,-4],[3,-4],[1,-1],[4,-1],[2,0],[3,3],[3,-1],[2,-4],[2,-5],[3,-1],[6,3],[3,1],[2,-1],[2,-1],[1,1],[-1,4],[-1,4],[2,2],[5,-2],[3,1],[0,1],[1,1],[0,4],[0,3],[0,3],[-1,3],[-2,4],[-9,10],[-3,4],[-2,5],[-2,7],[-1,8],[-1,5],[-3,13],[-1,2],[-2,0],[-3,1],[-4,-1],[-6,-2],[-3,0],[-1,-1],[-4,-5],[-2,-5],[-3,-11],[2,-3],[0,-2],[-1,-16],[1,-8],[-1,0],[0,2],[-2,7],[-4,10],[-3,14]],[[6554,7564],[8,-1],[6,0],[8,-1],[3,-1],[3,0],[1,0],[1,2],[1,1],[1,2],[0,1],[-1,1],[-2,3],[-1,13],[0,11],[2,3],[2,2],[3,8],[2,2],[2,2],[9,0],[3,2],[1,2],[2,6],[1,5],[1,2],[1,2],[2,0],[2,-1],[2,-1],[1,-1],[2,-2],[1,-3],[0,-2],[0,-1],[1,0],[1,0],[1,0],[0,1],[0,2],[-2,3],[-4,7],[-2,3],[-1,2],[0,1],[1,2],[2,2],[2,-1],[4,-1],[1,1],[2,6],[4,-6],[4,-7],[1,-1],[3,-1],[3,0],[1,-1],[1,-1],[2,-8],[2,-1],[3,-2],[8,0],[3,0],[2,-3],[2,-2],[0,-1],[0,-2],[-1,-1],[0,-4],[0,-3],[0,-1],[-1,-2],[1,-1],[4,-2],[1,-3],[1,-2],[1,-1],[-1,-2],[-2,1],[-1,-2],[0,-3],[1,-4],[1,-2],[-1,-3],[-1,-4],[0,-3],[0,-2],[4,-3],[7,-7],[1,0],[7,1],[3,1],[2,-1],[5,-2],[2,-1],[2,0],[2,1],[2,3],[0,1],[1,0],[2,0],[4,-2],[4,-4],[3,-4],[1,-4],[2,-8],[2,-12],[3,-8],[3,-4],[2,-8],[2,-17],[1,-4],[1,-1],[4,-5],[7,-9],[4,-4],[6,-8],[6,-7],[6,-11],[2,-2],[5,-6],[6,-6],[4,2],[6,-9],[2,-4],[1,-1],[5,-4],[7,-7],[9,-11],[6,-7],[2,0],[1,0],[2,1],[2,1],[3,-1],[3,-3],[2,-2],[3,-3],[2,-2],[1,-2],[6,-2],[0,-1],[1,-2],[0,-1],[-3,-9],[0,-11],[0,-8],[0,-6]],[[8445,4646],[4,5],[7,3]],[[8469,4669],[3,5],[3,8],[1,4],[4,3],[2,1],[12,5],[3,0],[7,0],[10,1],[2,1],[4,2],[3,2],[1,2],[2,2],[3,-2],[4,-1],[1,-2],[1,-1],[-5,-10],[-5,-7],[-4,-2],[-3,-2],[-3,-3],[-2,-5],[-3,-2],[-3,-1],[-3,-1],[-3,-3],[-3,-5],[-2,0],[-1,0],[-3,-2],[-9,-6],[-6,-8],[-4,-6]],[[8489,4715],[-2,-10],[-2,2],[3,6],[1,1],[0,1]],[[141,3957],[0,-9],[-1,4],[0,2],[1,3]],[[134,3964],[1,0],[0,2],[2,1],[0,-2],[-2,-6],[-2,2],[-3,4],[-1,3],[1,2],[0,-1],[1,-1],[2,-1],[1,-1],[-1,-1],[1,-1]],[[168,4110],[-1,-3],[-1,0],[-1,2],[0,1],[2,4],[1,0],[1,-1],[0,-1],[-1,-2]],[[3305,5768],[-5,-4],[-11,0],[-5,1],[-4,-1],[7,7],[1,3],[3,0],[0,1],[1,16],[0,4],[-1,2],[-1,1],[-2,2],[-1,1],[2,2],[3,1],[3,2],[5,0],[3,2],[5,0],[-3,-7],[-1,-3],[1,-6],[-1,-4],[1,-6],[1,-4],[-1,-3],[0,-6],[0,-1]],[[3312,5828],[-2,-1],[1,2],[2,4],[4,3],[1,0],[0,-3],[-6,-5]],[[5304,7126],[-1,0],[-1,-2],[-1,0],[-2,2],[-1,0],[-1,1],[1,7],[0,2],[5,0],[3,-4],[0,-1],[0,-1],[-1,-2],[-1,-2]],[[5313,7186],[-5,-5],[1,4],[3,4],[1,-1],[0,-2]],[[5238,7311],[7,4],[6,9],[2,2],[16,9],[2,-1],[2,-1],[-1,-3],[-1,-3],[2,-4],[1,2],[0,2],[0,3],[3,0],[3,-1],[3,-2],[-1,-10],[5,-10],[-2,-5],[4,-3],[3,4],[1,5],[6,3],[5,7],[3,1],[0,-6],[2,-5],[-2,-2],[-3,-6],[-5,-14],[-4,-4],[-3,-6],[-1,-4],[-1,-5],[1,-8],[3,-8],[2,-5],[3,-2],[6,-8],[0,-4],[1,-6],[0,-7],[2,-5],[-4,-12],[-3,-9],[-5,-12],[-4,-7],[-9,-12],[-2,-4],[-2,-4],[-1,-4],[1,-5],[3,-11],[4,-8],[4,-3],[7,1],[0,-4],[0,-6],[3,0],[2,1],[2,6],[3,-4],[2,-11],[3,-4],[1,-1],[-2,-1],[0,-1],[1,-1],[2,-1],[2,1],[3,-3]],[[5721,7496],[-7,-2],[-2,2],[2,3],[4,2],[1,0],[2,-3],[0,-2]],[[5996,7253],[2,4],[-2,10],[-2,8],[2,6],[4,6],[5,8],[0,5],[-1,4],[-1,2],[-2,4],[-4,-4],[-3,-4],[-2,-1],[-2,-2],[-1,-4],[-2,-3],[-4,-2],[-6,4],[-7,5],[-4,4],[-3,1],[-2,-1],[-9,-11],[-7,-15],[-2,-3],[-8,-6],[-4,-2],[-3,0],[-9,-3],[-5,0],[-4,-4],[-7,4],[-4,5],[-3,5],[-4,10],[-3,5],[-7,5],[-12,10],[-3,2],[-8,1],[-8,1],[-2,-4],[-1,-15],[-1,-5],[-1,-8],[-1,-2],[-1,-2],[-3,3],[-2,1],[-4,-3],[-8,-5],[-3,-1],[-9,6],[-4,4],[-2,4],[-1,7],[-1,4],[0,3],[-1,3],[-2,2],[-2,-3],[-2,0],[-3,2],[-6,6],[-5,0],[-3,-7],[-3,-2],[-2,-1],[0,2],[2,5],[-8,-1],[-4,-4],[-4,1],[-2,1],[0,2],[3,1],[2,2],[8,1],[2,1],[3,5],[3,5],[1,2],[-3,0],[-13,-2],[-9,1],[-1,-2],[-1,0],[-1,6],[2,2],[2,0],[4,2],[0,5],[-3,4],[-1,2],[-3,0],[-1,2],[-1,6],[-1,7],[-3,3],[1,2],[4,2],[1,9],[-1,5],[-2,1],[-6,4],[-2,0],[-2,5],[-3,3],[-2,-1],[-1,-2],[-2,1],[-2,3],[-3,2],[-1,2],[1,5],[2,0],[1,4],[-2,7],[0,3],[2,1],[2,0],[2,-4],[1,-4],[-1,-4],[1,-4],[1,-1],[1,4],[1,1],[1,-2],[3,-1],[6,2],[1,3],[-4,-1],[-2,2],[-2,5],[-1,4],[0,2],[-1,2],[1,2],[3,2],[3,7],[-1,1],[-2,1],[-1,0],[-2,2],[0,3],[1,2],[0,4],[-3,8],[-1,2],[0,3],[3,4],[3,6],[0,2],[-2,1],[-10,-3],[-4,-2],[-6,-1],[-1,3],[0,3],[2,5],[0,12],[1,7],[3,2],[5,10],[7,12],[8,0],[3,3],[4,0],[1,-2],[1,-3],[4,-3],[7,1],[1,1],[2,2],[-3,5],[1,2],[3,0],[3,-1],[0,-1],[-1,-2],[-1,-3],[1,-1],[9,2],[10,-2],[3,1],[7,0],[2,2],[-3,3],[-2,1],[-1,1],[-2,1],[5,6],[2,1],[13,4],[9,1],[1,2],[-2,0],[-12,2],[-3,3],[-4,5],[-1,1],[-1,3],[1,5],[1,5],[1,2],[5,0],[17,-4],[11,3],[13,-7],[13,2],[2,2],[3,10],[18,15],[6,8],[6,5],[12,5],[9,6],[3,1],[22,-3],[16,-1],[7,7],[4,-2],[0,-3],[-1,-2],[0,-3],[2,-6],[3,-4],[7,-5],[10,4],[2,0],[2,-1],[3,-15],[3,-5],[4,-4],[3,-1],[2,4],[1,2],[4,0],[6,-5],[2,-5],[10,-4],[9,-2],[4,-5],[14,-4],[4,1],[9,4],[16,5],[10,-7],[3,-1],[3,1],[3,-2],[4,1],[12,9],[3,4],[4,2],[4,2],[9,10],[2,5]],[[5778,7601],[-1,-6],[2,-8],[4,-10],[4,-5],[17,-12],[3,-1],[-1,-6],[-1,-4],[-1,-3],[-5,-2],[-14,5],[-3,1],[-2,-1],[-5,-4],[-5,1],[-7,-2],[-2,-8],[-4,-9],[-8,-7],[-6,-4],[-8,-13],[-4,-8],[-2,-2],[-2,-1],[1,4],[1,3],[0,3],[0,4],[3,4],[2,3],[8,6],[2,5],[-6,0],[-6,-1],[-4,0],[-3,0],[-1,4],[-1,3]],[[8288,6596],[1,-4],[0,-2],[-4,1],[0,3],[1,-1],[2,3]],[[8361,6487],[-2,-7],[-2,-7],[0,-7],[0,-7],[0,-6],[-1,-6],[-3,1],[-1,5],[-1,7],[-2,9],[0,2],[-3,5],[-3,3],[-2,4],[1,-1],[-2,5],[-1,5],[-2,15],[-1,4],[-1,3],[0,3],[0,4],[1,5],[0,6],[0,7],[0,7],[1,3],[13,45],[4,9],[2,5],[2,5],[1,7],[2,6],[2,2],[7,5],[3,5],[2,2],[2,0],[1,-3],[1,-3],[2,-1],[3,-3],[1,-3],[1,-5],[-2,-4],[-1,-4],[0,-5],[0,-6],[0,-6],[-2,-14],[-3,-9],[-1,-5],[-1,-11],[-1,-11],[-1,-14],[-3,-14],[-1,-7],[-2,-5],[-3,-11],[-4,-9]],[[6102,4724],[-1,0],[-1,0],[-1,3],[2,2],[2,4],[3,6],[1,3],[1,1],[0,-4],[-2,-10],[-2,-1],[-2,-4]],[[6097,4828],[2,-12],[-1,-2],[-1,-2],[-1,0],[-1,2],[-1,4],[-1,-1],[-2,5],[-2,0],[-1,6],[0,5],[0,9],[2,5],[1,7],[2,-5],[0,-8],[2,-9],[1,-3],[1,-1]],[[6107,4901],[0,-3],[-1,-2],[1,-9],[-1,-6],[-1,-8],[-1,-3],[-2,1],[-1,1],[0,3],[1,14],[-1,11],[3,-1],[3,2]],[[6089,4914],[-1,-5],[-2,-12],[0,-5],[-1,-6],[-1,-4],[-2,-16],[-2,-6],[-2,-15],[-1,-11],[2,-8],[0,-7],[3,-7],[3,-3],[1,-3],[3,-7],[2,-8],[5,-3],[2,-9],[-1,-6],[-2,-4],[-2,-8],[-2,-10],[0,-16],[1,3],[3,-4],[0,-12],[-3,-13],[-1,-6],[0,-6],[2,-16],[3,-8],[0,-2],[-1,-2],[6,-15],[-1,-12],[2,-10],[1,-8],[1,-7],[0,-4],[-1,-5],[4,-1],[2,-4],[1,-4],[3,0],[1,-3],[3,-2],[4,-7],[2,-3],[0,-2],[0,-1]],[[5914,4642],[-2,1],[-3,4],[-4,3],[-3,3],[-2,3],[-3,2],[-3,0],[-2,3],[-3,1],[-2,0],[-1,2],[0,5],[-1,1],[-2,1],[-2,0],[-1,-1],[-1,1],[-1,2],[-2,4],[-1,5],[-2,3],[-3,3],[-7,0],[-2,1],[-1,2],[-2,5],[-2,5],[-2,7],[0,4]],[[5847,5122],[0,1],[2,-1],[2,1],[2,3],[2,0],[1,0],[3,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[5,0],[4,0],[5,0],[5,0],[5,0],[5,0],[5,0],[3,0]],[[5889,7845],[3,-3],[-3,1],[-9,3],[-4,2],[-1,3],[0,4],[2,-4],[1,-2],[11,-4]],[[6061,7896],[-1,0],[-10,0],[-8,-1],[-5,-9],[-4,0],[-4,-2],[-4,-3],[-4,-7],[-2,3],[-4,0],[-4,-1],[-4,-5],[-2,0],[-5,1],[-5,-3],[-12,-14],[-4,-10],[-2,-2],[-2,-2],[-2,-2],[-1,0],[6,8],[1,2],[1,2],[0,4],[-2,4],[-5,-10],[-2,-2],[-4,-3],[0,-6],[1,-5],[1,-7],[3,-10],[7,-15],[3,-5],[2,-2],[3,0],[5,4],[3,1],[5,-2],[2,3],[2,2],[3,0],[4,-1],[4,-3],[-1,-5],[-2,-4],[-1,-4],[-1,-6],[-4,-2],[-5,1],[-5,-2],[-2,2],[-1,2],[-3,2],[-3,1],[-2,-2],[-3,-7],[-6,-4],[-2,-6],[-5,2],[-5,-1],[-7,-5],[-5,-11],[-6,-6],[-5,-3],[-4,1],[-3,2],[-5,7],[0,3],[1,1],[1,3],[2,13],[0,5],[-1,6],[-5,6],[-4,-1],[-2,1],[-7,9],[-4,0],[-5,-1],[-1,1],[-2,3],[9,11],[9,9],[4,1],[5,4],[6,6],[-1,5],[-1,4],[-3,-1],[-2,-1],[-5,4],[-1,2],[-8,-3],[-4,1],[-8,-3],[-5,3],[-8,7],[-3,2],[-2,0],[-2,2],[2,1],[2,0],[2,1],[1,2],[0,2],[-5,2],[-4,1],[-2,2],[-2,2],[4,0],[5,-2],[7,0],[6,-2],[2,2],[4,4],[0,2],[-6,-3],[-6,2],[-2,2],[-2,4],[-1,5],[0,4],[0,7],[-2,6],[-1,4],[-2,3],[2,-7],[1,-5],[1,-4],[0,-12],[-1,-4],[-3,-1],[-3,0],[-4,2],[1,6],[-2,-2],[-2,-6],[-3,-1],[-5,0],[-9,-4],[-1,-4],[-1,-7],[-2,-3],[0,-2],[-4,-10],[-1,0],[-7,-13],[-1,-1],[-5,-3],[-3,-3],[-2,-1],[-4,1],[-2,-2],[0,-2],[0,-5],[2,-3],[1,-11],[0,-5]],[[3517,3240],[-1,-2],[-2,-4],[-1,-10],[-6,-13],[-1,-7],[-7,-8],[-4,-9],[-3,0],[-2,-4],[-15,-11],[-6,2],[-4,0],[-3,5],[-9,2],[-5,-2],[-7,-6],[-2,0],[-2,1],[-4,2],[-2,5],[-11,5],[-8,13],[-11,1],[-8,-2],[-1,2],[-1,3],[-1,5],[-7,11],[-6,11],[-1,12],[1,12],[2,14],[-1,5],[2,2],[2,1],[2,3],[2,6],[0,4],[-1,8],[-1,11],[-1,5]],[[678,6279],[-1,-3],[-2,0],[-5,6],[-1,3],[1,15],[-2,12],[-3,9],[2,5],[2,4],[3,7],[-2,8],[0,6],[1,1],[6,-7],[12,-10],[3,-6],[1,-8],[2,-1],[1,-5],[3,-4],[1,-3],[-1,-4],[-6,-7],[-7,-4],[-6,-9],[-2,-5]],[[643,6380],[-2,-1],[-1,0],[-1,4],[-2,5],[3,1],[2,-1],[1,-2],[1,-2],[-1,-4]],[[653,6389],[1,-1],[3,2],[2,1],[3,-4],[2,-3],[2,-3],[1,-2],[-1,-2],[-2,-4],[-4,-1],[-2,-2],[-3,1],[-1,0],[0,5],[-1,6],[-2,-1],[-1,2],[-3,5],[0,2],[1,5],[2,0],[2,-2],[1,-4]],[[633,6406],[6,-2],[1,1],[1,-1],[5,-1],[1,-1],[-1,-3],[-3,-2],[-5,2],[-7,1],[0,2],[1,2],[0,3],[1,-1]],[[617,6420],[1,-1],[1,1],[0,-5],[2,-2],[0,-2],[-1,-2],[-3,0],[-2,1],[-1,3],[-2,-1],[0,2],[0,1],[-1,0],[1,-3],[-3,-1],[-1,1],[-1,3],[-3,7],[0,2],[-1,3],[5,1],[2,5],[2,1],[3,-9],[0,-2],[1,-2],[1,-1]],[[551,6442],[-1,-3],[-1,1],[0,2],[0,3],[2,3],[2,4],[1,-1],[-1,-2],[0,-3],[-2,-2],[0,-2]],[[573,6447],[-3,-3],[-1,1],[-3,1],[-1,2],[-2,2],[-2,3],[2,6],[4,5],[7,0],[1,-4],[0,-3],[-1,-3],[0,-5],[-1,-2]],[[2728,6598],[-1,-1],[0,1],[1,1],[1,0],[0,-1],[-1,0]],[[2734,6601],[-2,-1],[2,2],[0,4],[1,-3],[0,-1],[-1,-1]],[[2740,6604],[0,-2],[-1,1],[0,2],[-1,3],[0,1],[3,-3],[0,-1],[-1,-1]],[[2749,6607],[-2,-1],[-1,1],[1,1],[5,2],[-2,-2],[-1,-1]],[[2754,6612],[0,1],[1,2],[1,-1],[0,-1],[-2,-1]],[[2760,6618],[-1,0],[1,2],[0,-2]],[[2767,6632],[-6,-11],[1,3],[2,6],[1,2],[1,2],[2,3],[0,4],[2,2],[0,1],[-3,-12]],[[2721,6707],[-1,-1],[-2,1],[-1,2],[-1,4],[2,-4],[1,-1],[2,-1]],[[2720,6713],[0,-3],[-2,5],[-1,7],[2,-2],[1,-7]],[[2301,6691],[-1,-3],[-2,12],[-4,29],[0,16],[1,5],[1,-22],[4,-29],[1,-8]],[[2296,6756],[-1,-3],[0,5],[2,11],[5,15],[2,2],[-6,-16],[-2,-14]],[[2772,6755],[1,-4],[-3,10],[-3,15],[-2,12],[2,-3],[1,-7],[4,-23]],[[2305,6791],[-1,0],[2,4],[0,2],[2,6],[1,1],[1,-2],[-2,-5],[-3,-6]],[[2312,6805],[-1,0],[1,3],[2,2],[5,6],[2,0],[0,2],[1,1],[0,-3],[-4,-4],[-6,-7]],[[2360,6863],[-2,-1],[6,9],[2,3],[1,0],[-2,-5],[-5,-6]],[[2450,6883],[-1,-1],[-5,5],[0,2],[2,2],[2,0],[2,-2],[1,-1],[0,-1],[0,-2],[-1,-2]],[[2641,6891],[-3,-2],[-3,2],[2,0],[2,-1],[3,3],[2,2],[2,1],[-5,-5]],[[2531,6895],[-2,-3],[0,1],[1,3],[1,2],[0,-3]],[[2532,6901],[0,-2],[0,9],[-1,7],[1,-3],[1,-4],[-1,-7]],[[2521,6917],[0,-3],[-1,1],[-2,0],[1,1],[1,1],[0,1],[2,3],[0,-2],[-1,-2]],[[2540,6924],[-1,0],[-2,1],[-2,1],[0,1],[4,-2],[1,-1]],[[2553,6926],[-2,-1],[-4,0],[0,1],[1,0],[4,2],[1,-2]],[[2738,6968],[-1,-14],[-1,5],[0,4],[1,3],[1,2]],[[1712,7075],[-1,-1],[-2,1],[-2,6],[-1,4],[1,1],[1,-4],[3,-6],[1,-1]],[[1682,7097],[-1,0],[-2,0],[-1,4],[2,0],[1,-1],[1,-2],[0,-1]],[[1712,7107],[2,-4],[-2,0],[-2,0],[-1,2],[-1,3],[0,1],[-1,0],[-1,1],[0,1],[1,1],[4,-4],[1,-1]],[[1665,7137],[-2,0],[-1,0],[-2,6],[5,1],[2,-3],[-2,-4]],[[1658,7144],[-1,-1],[-3,1],[1,1],[1,1],[1,0],[1,-2]],[[1670,7147],[5,-3],[3,1],[1,-1],[0,-1],[-7,-3],[-2,2],[-1,2],[0,2],[1,1]],[[2873,7180],[-1,0],[-2,2],[1,0],[2,-2]],[[2875,7179],[-1,0],[2,7],[5,9],[2,1],[-4,-8],[-4,-9]],[[2895,7211],[-5,-4],[-1,0],[3,3],[3,1]],[[2901,7214],[-3,-2],[-1,1],[4,3],[2,11],[0,6],[-1,9],[0,2],[1,-3],[1,-9],[-1,-6],[-1,-10],[-1,-2]],[[2899,7249],[-1,-1],[-2,6],[2,-2],[1,-2],[0,-1]],[[2907,7366],[-1,-1],[4,12],[3,9],[1,4],[-1,-7],[-2,-6],[-4,-11]],[[2940,7469],[-3,-8],[0,1],[4,11],[-1,-4]],[[2939,7518],[-1,0],[1,5],[2,3],[1,-1],[0,-2],[0,-1],[-2,-3],[-1,-1]],[[2986,7545],[-2,-4],[1,-1],[2,2],[1,2],[4,3],[3,1],[1,0],[1,-2],[3,2],[2,1],[-12,-10],[-2,-1],[-4,-3],[-3,-2],[-2,0],[-12,-8],[-1,0],[-1,1],[-10,-4],[-4,0],[-4,-1],[3,3],[0,1],[-1,1],[-1,-1],[-2,-3],[-2,-1],[-1,4],[1,2],[1,3],[3,3],[3,3],[2,2],[1,-2],[0,2],[1,2],[1,1],[2,0],[2,0],[1,1],[1,0],[2,-1],[3,0],[2,2],[2,0],[6,1],[5,1],[3,2],[4,6],[3,1],[-4,-6],[-2,-3]],[[3056,7561],[-2,-1],[-5,2],[4,2],[1,0],[0,3],[0,1],[2,-5],[0,-2]],[[3041,7567],[-8,-3],[-1,2],[2,1],[3,4],[1,1],[3,-3],[0,-2]],[[3017,7573],[0,-1],[-1,3],[1,3],[1,-1],[-1,-4]],[[3021,7574],[-2,-2],[-1,0],[1,2],[0,4],[1,3],[0,1],[1,1],[0,-9]],[[3093,7729],[-1,-1],[-1,1],[0,2],[1,1],[0,1],[1,-1],[0,-3]],[[3106,7737],[-2,-1],[-2,1],[0,-3],[0,-1],[-2,1],[-1,1],[0,4],[2,4],[1,1],[2,-1],[2,-4],[0,-2]],[[1587,7903],[0,-1],[-1,2],[0,2],[0,1],[1,-4]],[[1600,7914],[0,-2],[-1,-1],[-1,1],[0,1],[-1,-1],[0,3],[0,4],[1,0],[1,-2],[1,-3]],[[1597,7925],[0,-1],[-2,1],[0,2],[0,2],[0,2],[1,0],[1,0],[0,-1],[0,-5]],[[1595,7958],[1,-8],[1,3],[4,-5],[0,-3],[-1,-1],[-1,1],[-1,1],[-1,1],[-2,1],[0,2],[-1,2],[0,4],[0,1],[-1,1],[-1,1],[-2,3],[1,3],[1,4],[1,2],[1,-1],[1,-1],[1,-2],[0,-2],[-4,-3],[2,-1],[0,-1],[1,-2]],[[1588,7973],[-2,1],[-1,1],[0,1],[1,4],[1,0],[0,-3],[1,-2],[0,-2]],[[1583,7977],[1,-2],[-3,2],[-2,1],[0,1],[-1,3],[1,1],[1,1],[3,-4],[0,-3]],[[1589,7987],[1,-1],[-2,-1],[-2,2],[0,-3],[0,-1],[-2,2],[-1,1],[1,2],[1,1],[1,0],[3,-2]],[[3135,7785],[0,-1],[1,-3],[0,-6],[-1,-2],[1,-4],[2,-1],[1,-1],[0,-1],[-6,-9],[-5,1],[-2,-2],[-3,-1],[-1,-4],[-2,0],[-2,0],[-1,1],[-2,-1],[-2,-7],[-1,1],[-1,-3],[-1,-1],[-1,-1],[-1,3],[0,3],[-1,1],[-2,1],[-1,0],[-1,-1],[-1,-2],[-2,-1],[-1,1],[-1,2],[-1,-3],[-1,-4],[1,-4],[-1,-3],[-1,1],[-1,2],[-3,2],[-3,0],[1,2],[2,4],[-1,0],[-1,0],[1,3],[0,4],[-1,-1],[-2,-4],[-3,-3],[0,-5],[-3,-10],[0,-4],[-2,-4],[-2,-3],[-4,1],[-2,-2],[-1,-3],[-1,-1],[-1,4],[0,1],[-1,-5],[-1,-1],[-1,4],[0,3],[-1,-2],[-1,-6],[-1,0],[0,2],[-1,1],[0,-3],[0,-3],[0,-2],[-1,1],[-1,2],[-2,-2],[-1,0],[0,2],[0,2],[-2,-1],[-4,-4],[-2,-6],[1,-1],[1,-1],[-5,-9],[-4,-7],[-4,-13],[-1,-1],[-1,-2],[-1,-8],[-2,-7],[1,-2],[1,-4],[1,-3],[1,0],[1,1],[1,0],[0,-2],[0,-1],[-1,-1],[-3,-2],[-2,-1],[-1,-3],[-2,-4],[-3,-6],[2,-2],[5,-2],[2,-2],[3,-11],[-1,-1],[0,-2],[3,-3],[1,-7],[2,-3],[4,-2],[5,3],[3,3],[0,3],[-2,6],[-1,3],[-2,2],[0,-2],[-1,2],[0,1],[1,1],[1,0],[1,-2],[4,-6],[1,-9],[0,-6],[0,-2],[-1,1],[-2,-1],[-10,-3],[-2,-2],[-5,-3],[0,1],[0,3],[0,6],[-1,1],[-8,-10],[-3,-1],[-2,-2],[-1,1],[0,7],[1,6],[-3,-3],[-1,2],[-1,2],[0,2],[-1,0],[0,-5],[-1,-4],[-1,-11],[-2,-4],[-7,-3],[-4,1],[-4,-1],[-6,-2],[-3,1],[-3,-2],[-10,0],[-2,1],[-3,-4],[-4,-3],[-11,-8],[-3,-4],[-3,-5],[-2,-2],[-1,-1],[-1,-3],[-1,-1],[1,5],[1,4],[1,9],[-1,6],[-1,3],[-1,2],[1,-7],[1,-8],[-1,-5],[-3,-9],[-1,-2],[-1,-2],[-1,0],[-1,-2],[-1,-2],[-1,-5],[0,-4],[6,-2],[1,2],[1,-3],[0,-4],[0,-5],[-1,-4],[-1,-6],[0,-9],[-1,-7],[0,2],[0,9],[-1,-1],[0,-2],[-2,-12],[-2,-7],[-2,-4],[-2,1],[0,-4],[0,-2],[-1,-4],[-1,-2],[-1,0],[-2,-2],[-1,-1],[0,-3],[-1,-2],[-4,-12],[-3,-3],[-1,0],[1,6],[0,6],[-2,2],[-2,1],[-2,0],[-3,5],[-3,3],[-5,8],[0,3],[0,4],[1,6],[2,5],[2,2],[5,2],[1,4],[1,3],[-2,-5],[-5,-2],[-2,-2],[-2,-3],[-1,-4],[-2,-4],[0,-3],[1,-2],[-1,-4],[2,-5],[3,-7],[0,-11],[3,-7],[3,-8],[3,-3],[0,-3],[-1,-5],[-2,-2],[2,0],[1,-1],[1,-4],[0,-5],[0,-2],[-1,-1],[0,2],[0,1],[-1,-1],[0,-1],[-1,-5],[0,-3],[-2,-1],[-2,-6],[-1,-4],[-7,-25],[0,-4],[-1,-1],[-2,-1],[-2,-3],[-1,-3],[-1,-7],[-3,-8],[-1,3],[0,3],[0,8],[3,13],[2,8],[2,3],[2,8],[-2,1],[-3,0],[0,3],[1,4],[-1,3],[-1,0],[-1,1],[1,3],[0,3],[0,3],[1,2],[-1,0],[-2,-3],[0,-1],[-1,3],[-1,-1],[0,-1],[-1,-1],[-2,2],[-2,2],[-2,5],[-1,3],[1,6],[2,1],[2,-1],[4,0],[-1,2],[-1,-1],[-3,5],[-1,3],[-2,1],[-1,-3],[-1,-1],[1,7],[2,0],[2,2],[-1,3],[-1,2],[-3,-2],[0,2],[1,4],[2,0],[1,-1],[2,5],[0,2],[-2,-3],[-1,7],[2,7],[3,3],[2,0],[3,1],[-2,1],[-1,1],[1,3],[1,0],[1,3],[-3,-1],[1,5],[-2,-1],[-1,-1],[-1,-2],[0,-3],[0,-2],[-1,-2],[-2,-1],[-1,2],[0,1],[-1,-5],[0,-1],[-2,4],[0,-1],[0,-1],[0,-2],[-2,-1],[0,-3],[0,-2],[-4,3],[0,-1],[2,-6],[2,-2],[0,-3],[-2,-2],[-2,2],[1,-4],[1,-3],[-1,-3],[0,-3],[0,-3],[0,-3],[1,-12],[1,-3],[1,-3],[1,-3],[-2,-1],[-2,3],[-1,2],[-2,6],[-1,2],[0,2],[0,-5],[1,-4],[6,-11],[1,-4],[1,-3],[0,-3],[-2,2],[-1,3],[-4,3],[-5,2],[-3,7],[1,-3],[-1,-3],[-2,4],[-1,2],[0,3],[-2,0],[-3,-3],[-2,1],[0,5],[1,3],[2,6],[2,3],[1,4],[0,7],[0,-7],[-2,-3],[-2,-2],[-2,-5],[-1,-4],[-1,-8],[1,-2],[1,-1],[4,2],[2,-1],[3,-9],[8,-4],[2,-2],[3,-5],[3,-3],[2,-4],[0,-2],[-1,-3],[0,-4],[-1,-3],[-3,0],[-1,0],[-8,15],[-1,1],[-4,8],[-3,4],[-1,0],[5,-8],[2,-5],[4,-7],[2,-4],[2,-5],[2,-2],[5,-3],[-2,-3],[3,-2],[1,-3],[-1,-4],[-4,1],[0,-3],[1,-2],[-2,-1],[-2,2],[-6,11],[0,-1],[0,-2],[4,-7],[3,-5],[2,-2],[3,-3],[0,-3],[1,-3],[-2,-2],[-2,-2],[-1,3],[-1,2],[-3,4],[-1,5],[-2,-1],[-8,6],[-7,1],[1,-1],[0,-1],[6,-1],[2,-3],[4,-2],[3,-1],[1,-7],[4,-5],[0,-4],[3,0],[4,3],[3,-1],[4,-1],[1,-3],[0,-6],[2,-6],[3,-24],[6,-21],[1,-3],[-2,3],[-4,13],[-2,10],[-2,17],[-1,4],[-1,1],[0,-1],[-1,-2],[1,-2],[-1,-5],[0,-3],[2,-3],[1,-6],[2,-9],[-2,3],[-2,2],[-3,2],[-3,2],[1,-3],[-1,-4],[-2,1],[-1,1],[1,-4],[-2,1],[-2,0],[-1,-4],[-2,-2],[-2,-1],[-3,4],[-1,4],[-1,5],[0,-6],[1,-6],[-1,-4],[4,-1],[3,1],[4,0],[2,0],[2,2],[4,-1],[0,-6],[0,-5],[-1,-5],[1,0],[2,1],[0,10],[4,4],[1,0],[1,-3],[0,-4],[1,-4],[-1,-7],[-5,-8],[-4,-7],[-2,-2],[-3,1],[-3,2],[-2,0],[-1,0],[-1,2],[0,4],[-1,1],[-1,0],[-1,-4],[-3,-1],[-4,1],[-4,4],[2,-4],[10,-7],[1,-2],[1,-2],[-1,-3],[-1,-3],[0,-3],[-1,-2],[-4,-5],[-2,1],[-6,9],[3,-8],[2,-3],[4,-2],[8,3],[3,-3],[-3,-5],[-2,-4],[-3,-1],[-2,-1],[-1,-2],[-2,0],[-2,0],[-5,-1],[-2,1],[-3,-5],[-1,-1],[-2,1],[-1,4],[-1,2],[0,-8],[1,-2],[0,-2],[-4,-4],[-3,-5],[-2,-2],[-1,-2],[-3,-8],[-1,-6],[-1,-6],[0,3],[0,4],[-1,6],[0,-10],[-1,-5],[-11,0],[-5,-2],[-7,-9],[-3,-4],[-6,-14],[-1,-9],[-1,4],[0,2],[0,3],[-2,-5],[2,-8],[-1,-3],[-4,-5],[-3,-1],[-2,-1],[-1,-6],[-3,-5],[-2,-2],[-4,2],[1,-5],[-1,-4],[-2,-2],[-3,-2],[-2,0],[-1,-1],[-1,-2],[-3,-2],[-2,1],[-3,1],[-2,-2],[3,-2],[1,-3],[0,-4],[-1,-1],[-2,-3],[0,1],[-1,2],[0,4],[-1,-1],[0,-2],[-1,-1],[-3,7],[0,-5],[1,-4],[1,-2],[1,-1],[0,-2],[-2,-4],[0,-1],[-2,0],[-1,-3],[0,-2],[-1,-5],[-4,-3],[-1,0],[0,-1],[0,-2],[1,-2],[0,-1],[-1,-2],[-2,-1],[-1,-2],[1,-2],[0,-1],[0,-2],[-2,-3],[0,-2],[1,0],[1,0],[-1,-3],[-1,-3],[-1,-3],[-3,-1],[0,-2],[2,-1],[1,-2],[-2,-6],[-2,1],[-1,1],[0,-4],[0,-3],[0,-4],[-1,-6],[-1,-2],[0,-4],[1,-4],[1,-5],[2,-22],[1,-7],[3,-20],[4,-20],[6,-23],[9,-28],[1,-4],[-1,-4],[-1,-3],[0,-6],[1,-5],[1,-6],[2,-10],[-1,2],[-3,14],[-1,8],[1,12],[-1,-1],[-1,-3],[0,-5],[-1,-2],[-1,7],[0,3],[1,4],[0,1],[-2,2],[0,3],[0,3],[-1,1],[-1,0],[1,-7],[1,-4],[1,-10],[1,-7],[1,-5],[12,-56],[3,-7],[1,-5],[1,-11],[0,-14],[-2,-25],[0,-17],[0,2],[-1,0],[-2,-8],[-2,-7],[-1,-11],[-1,-5],[-3,-6],[-2,0],[-5,-4],[-3,1],[-5,-3],[-2,1],[-2,5],[0,2],[1,3],[1,0],[4,-5],[0,2],[-1,3],[-2,1],[-1,2],[-4,12],[-3,9],[0,6],[-6,3],[-4,5],[-3,10],[-1,16],[-2,2],[-1,2],[2,6],[2,5],[-2,-1],[-1,-2],[-1,-5],[-1,-1],[-1,1],[-1,9],[0,11],[2,4],[-3,0],[-2,-2],[0,-3],[0,-2],[-2,0],[-1,2],[-2,3],[-2,7],[-5,20],[-1,3],[-2,3],[1,1],[1,0],[3,9],[3,5],[1,4],[0,2],[-1,2],[-2,-2],[-1,1],[-1,4],[-2,1],[-1,-1],[1,-3],[1,-2],[0,-5],[0,-2],[-1,-2],[-2,1],[-1,-1],[-1,1],[0,3],[-1,4],[2,22],[3,15],[0,16],[0,2],[0,5],[-3,9],[-15,23],[-11,27],[-10,11],[-7,-3],[-1,-2],[-1,-2],[0,-3],[0,-2],[-2,1],[-3,-1],[-7,-7],[-2,0],[-3,-2],[-1,-1],[-5,-1],[-3,-2],[-2,1],[-1,4],[0,5],[1,-4],[1,-2],[1,1],[0,2],[-1,5],[-4,5],[-5,9],[1,-1],[1,2],[-2,3],[1,2],[1,3],[-2,0],[-2,-2],[0,-3],[0,-2],[-1,1],[-2,2],[-9,7],[-8,4],[6,1],[3,-1],[0,2],[-1,1],[-2,2],[-4,0],[-2,0],[-2,-1],[-2,-3],[-2,-1],[-8,-2],[-7,-2],[2,2],[1,2],[3,2],[1,4],[-1,4],[-1,-1],[-1,-3],[-1,2],[-2,0],[0,-5],[-2,-3],[-1,-4],[-5,-2],[-1,1],[2,3],[0,1],[-2,-1],[-3,-6],[-11,-2],[1,1],[2,1],[3,2],[-1,3],[-1,3],[-1,1],[-1,2],[0,6],[0,4],[-2,4],[-1,-1],[-1,-7],[-1,-8],[0,-3],[-4,0],[-2,0],[-10,-1],[-3,3],[-2,1],[-1,0],[-4,-3],[-5,-2],[-1,1],[-1,0],[-4,-7],[-4,-4],[-10,6],[-3,5],[-2,1],[-3,1],[-2,-6],[-3,-8],[4,-4],[3,-3],[5,2],[3,4],[2,0],[1,1],[1,2],[2,-2],[0,-2],[-1,-2],[-2,-2],[-1,-2],[2,-4],[3,-2],[1,1],[1,5],[2,3],[2,-1],[0,-2],[0,-2],[2,-3],[-1,-4],[1,-2],[-3,-2],[-2,0],[-2,-3],[1,-2],[-2,-1],[-1,1],[0,-1],[-1,-2],[0,-1],[1,-5],[2,-3],[2,-4],[8,-5],[2,0],[1,-5],[2,-1],[1,-1],[0,-4],[-3,-2],[0,-3],[-1,-2],[-1,2],[-1,2],[-3,-5],[-1,-1],[1,5],[-1,2],[-2,5],[-2,4],[-2,1],[-1,2],[-1,0],[-1,0],[-2,1],[-1,3],[0,2],[-2,3],[-8,4],[0,-2],[1,-1],[1,-1],[1,-2],[0,-5],[0,-3],[-1,-3],[0,-3],[-1,-3],[-2,-2],[-1,2],[-2,7],[-2,2],[-3,0],[-3,-1],[-2,-7],[-2,-1],[-7,3],[-8,6],[0,2],[1,0],[3,-1],[0,2],[-3,6],[0,3],[0,4],[-1,0],[-1,-3],[-5,2],[-2,3],[-3,8],[-4,0],[-2,5],[-3,-2],[-2,-2],[-2,-4],[1,-1],[2,-3],[-1,-2],[-5,-2],[-11,3],[-4,2],[-4,4],[-6,4],[-3,1],[-3,-1],[-9,0],[-2,-1],[-2,-2],[-1,2],[0,3],[1,0],[1,2],[1,4],[0,2],[-1,1],[-1,1],[-3,-10],[2,-5],[0,-2],[-6,-1],[-13,-11],[-5,-6],[0,2],[6,8],[-2,1],[-4,-2],[-1,1],[2,6],[-1,5],[-2,1],[-2,-5],[-1,0],[-2,2],[-1,0],[1,-10],[2,-4],[1,-6],[-4,-6],[-3,-5],[0,-5],[-4,-7],[-3,-4],[-7,-9],[-2,-1],[-4,-5],[-4,-3],[-5,-5],[-1,0],[2,4],[4,4],[-3,-1],[-5,2],[-2,0],[0,-1],[-2,-2],[-3,3],[0,2],[-1,2],[-1,0],[-1,-1],[4,-12],[1,-1],[1,-1],[-1,-3],[-2,-2],[-4,-2],[-2,5],[-1,-6],[0,-6],[-1,-1],[-2,-2],[0,1],[-1,2],[-1,-2],[-1,-1],[-2,0],[-2,-1],[0,-3],[0,-2],[3,2],[-1,-6],[-2,-6],[-3,-2],[-3,1],[-1,-1],[-1,-1],[4,-9],[-2,-15],[-2,-5],[-1,-1],[-1,0],[-5,5],[-2,3],[2,-10],[6,-2],[0,-4],[0,-3],[-1,-4],[-1,-5],[1,-3],[1,-9],[0,-4],[1,-12],[1,-5],[5,-19],[2,0],[0,-2],[0,-4]],[[1746,7058],[0,6],[-1,3],[-2,-2],[-1,8],[1,4],[0,4],[-2,9],[-4,12],[-9,14],[-5,4],[-3,6],[-2,2],[-3,0],[-1,-2],[-3,1],[0,7],[-3,9],[-3,1],[-6,0],[-9,5],[-2,3],[-1,5],[-4,5],[-6,4],[-3,-1],[-3,1],[-6,3],[-3,1],[-7,-1],[-2,0],[-2,4],[-2,3],[0,5],[0,4],[0,4],[-1,8],[1,7],[-1,3],[-1,2],[-4,3],[-1,4],[1,5],[-1,3],[-4,3],[-3,8],[-4,4],[-2,6],[-2,5],[-1,3],[-6,13],[-6,10],[-1,6],[0,8],[3,5],[1,5],[0,3],[-1,3],[-2,5],[-8,3],[-6,13],[0,9],[-3,10],[0,7],[0,6],[2,2],[1,-1],[0,-2],[1,-5],[2,-4],[2,-2],[1,-3],[2,-1],[1,-1],[-1,3],[0,1],[-1,5],[-2,6],[-2,3],[-1,7],[-1,1],[-1,2],[2,3],[3,2],[4,0],[10,0],[2,1],[2,0],[1,0],[-3,1],[-1,0],[-2,0],[-4,0],[-1,1],[-2,1],[-1,1],[-3,-4],[-2,1],[-3,3],[-2,1],[-2,-2],[-1,-9],[1,-7],[-2,0],[-1,2],[-3,2],[-2,2],[-3,5],[-2,2],[-2,-4],[0,2],[1,4],[0,8],[3,-6],[-1,4],[-2,5],[-2,1],[-2,8],[-5,5],[-4,8],[-7,14],[-1,12],[-3,14],[2,9],[-1,6],[-1,9],[-1,5],[-7,13],[-6,9],[0,7],[-1,7],[1,6],[2,7],[0,1],[1,0],[-1,-2],[1,0],[1,3],[0,1],[-1,0],[0,1],[1,2],[2,9],[0,10],[2,13],[-1,5],[-1,9],[-1,6],[-2,4],[1,6],[0,5],[-4,8],[-2,10],[0,5],[0,12],[-1,5],[-3,8],[2,7],[1,4],[3,19],[1,2],[1,0],[2,3],[-1,1],[-2,-2],[2,8],[1,6],[1,2],[1,21],[1,16],[1,6],[0,5],[0,7],[0,8],[3,36],[-1,4],[1,6],[-1,15],[1,17],[-1,3],[0,2],[2,-2],[6,0],[5,2],[1,-1],[2,-3],[2,0],[3,0],[-1,1],[-1,0],[-3,3],[-2,3],[-5,0],[-1,2],[-6,-2],[-1,2],[-4,-2],[1,6],[0,7],[0,6],[1,-5],[2,-5],[1,6],[0,7],[-1,3],[-4,2],[-1,7],[8,6],[-4,1],[-2,3],[-2,0],[0,-2],[0,-3],[-1,4],[0,4],[-1,7],[-3,11],[-2,15],[-2,7],[-5,7],[-1,4],[-1,10],[1,8],[-1,5],[2,0],[5,-4],[8,-4],[2,-2],[3,-2],[19,-3],[1,1],[3,1],[1,0],[3,-4],[1,0],[2,0],[1,1],[2,2],[1,-1],[0,-2],[0,-4],[2,-4],[1,-3],[-4,-9],[0,3],[-1,1],[-6,-14],[-2,-7],[-1,-3],[0,-2],[1,0],[2,1],[3,2],[0,1],[-2,-1],[-2,0],[1,3],[0,2],[2,4],[2,3],[2,3],[2,2],[1,4],[3,4],[1,1],[-1,4],[1,0],[1,0],[1,-6],[-1,-3],[-2,-3],[-1,-1],[1,-5],[-1,0],[-1,0],[3,-5],[0,-3],[1,-4],[-1,-6],[-1,-1],[-1,0],[-2,2],[-1,-5],[-1,0],[-1,6],[-3,-2],[-1,-3],[0,-4],[-2,-2],[4,-1],[2,1],[3,-2],[3,2],[0,2],[2,6],[1,1],[1,0],[1,1],[2,3],[0,2],[0,7],[0,5],[-1,1],[0,2],[0,1],[0,2],[0,2],[0,2],[0,2],[2,5],[0,2],[2,4],[0,2],[-2,2],[-1,2],[-1,3],[-1,1],[1,-5],[0,-1],[-3,3],[0,2],[-1,2],[1,2],[1,1],[2,1],[0,1],[-3,5],[-1,2],[-1,1],[-2,0],[0,1],[-1,1],[1,2],[1,0],[2,0],[1,1],[0,1],[0,2],[0,6],[-1,5],[-1,1],[-1,0],[-1,0],[-1,1],[-1,4],[-2,8]],[[9984,8143],[-5,0],[-10,9],[-5,3],[-3,3],[2,1],[6,-2],[5,-5],[2,-4],[3,-2],[4,-2],[1,-1]],[[103,8167],[-2,-3],[-1,1],[0,5],[1,1],[2,-3],[0,-1]],[[111,8168],[-2,-1],[-4,2],[1,3],[3,-2],[2,-2]],[[59,8159],[-1,-2],[-4,3],[-1,1],[3,2],[0,1],[0,1],[-2,2],[-3,3],[-1,2],[1,1],[1,1],[5,0],[2,-3],[2,-1],[4,-1],[-2,-2],[-1,-1],[-2,-5],[-1,-2]],[[79,8163],[-1,-1],[-1,-1],[-4,1],[-3,0],[-3,-1],[-2,-1],[0,2],[0,1],[9,3],[2,2],[2,2],[1,4],[1,1],[2,-2],[-1,-2],[-1,-2],[0,-1],[-1,-5]],[[95,8171],[0,-2],[3,1],[1,-1],[0,-4],[0,-1],[-1,-1],[-1,1],[-1,-2],[-6,-4],[-2,2],[-4,-4],[3,11],[3,1],[1,2],[-1,3],[2,5],[3,0],[1,-2],[0,-2],[-1,-3]],[[9959,8174],[-1,-1],[-1,3],[0,1],[1,2],[1,-1],[1,-2],[-1,-2]],[[9991,8173],[-2,-1],[-3,1],[-1,2],[0,3],[4,3],[4,-4],[-2,-4]],[[111,8179],[-1,-2],[-3,2],[-1,2],[0,1],[1,3],[2,0],[1,-1],[1,-2],[1,-1],[-1,-2]],[[9927,8172],[-2,-2],[-2,2],[0,1],[3,5],[3,0],[1,2],[1,5],[2,0],[1,0],[0,-3],[-2,-3],[0,-3],[-5,-4]],[[179,8187],[6,-3],[6,1],[3,-1],[0,-1],[-5,0],[-1,0],[-4,-1],[-2,-1],[-6,2],[-5,-1],[-1,0],[-1,1],[-2,2],[0,1],[1,0],[4,-1],[1,1],[3,1],[3,0]],[[209,8195],[-2,-1],[-2,1],[1,3],[1,1],[2,2],[3,-1],[1,-2],[-4,-3]],[[148,8181],[-15,-2],[-2,1],[2,1],[3,1],[5,2],[7,3],[5,3],[5,1],[1,3],[-4,2],[0,1],[2,2],[1,2],[4,2],[3,-3],[1,-2],[0,-2],[-1,-3],[-3,-1],[0,-2],[1,-3],[-6,-4],[-9,-2]],[[9825,8200],[-2,-1],[-1,2],[-6,1],[0,2],[3,1],[4,3],[3,-1],[-1,-2],[0,-5]],[[257,8212],[-1,-1],[-1,0],[0,3],[1,1],[3,4],[2,-1],[1,-1],[-1,-1],[0,-2],[-1,-1],[-1,0],[-2,-1]],[[286,8228],[0,-3],[-1,0],[-4,1],[-3,-1],[0,2],[0,1],[5,2],[2,0],[1,-1],[0,-1]],[[9799,8237],[5,-2],[3,1],[5,-3],[5,-5],[-1,-1],[-2,-1],[-1,0],[-4,0],[-2,0],[-4,-4],[-5,3],[-1,5],[-4,1],[-2,2],[5,4],[3,0]],[[334,8256],[-8,-6],[-3,-4],[-2,-5],[-2,-2],[-1,0],[-1,-2],[-3,-3],[-1,0],[-9,-7],[-1,0],[0,2],[3,2],[2,3],[2,4],[1,1],[1,2],[0,4],[0,2],[2,3],[2,1],[1,1],[4,-1],[2,2],[0,1],[-1,1],[0,2],[0,3],[1,3],[2,2],[3,2],[3,2],[3,0],[4,-3],[1,-2],[-1,-2],[-1,-3],[-3,-3]],[[383,8278],[-1,1],[0,2],[0,1],[2,2],[1,1],[1,0],[0,-1],[-1,-2],[-1,-2],[-1,-2]],[[372,8288],[1,-2],[2,1],[2,3],[1,3],[1,1],[1,-2],[2,-2],[-2,-3],[-5,-5],[-1,-4],[0,-1],[4,1],[1,0],[1,-1],[-1,-2],[-2,-1],[-3,-2],[-5,-5],[-2,-3],[-2,-1],[-3,-1],[-5,-2],[-3,-2],[-1,-1],[-1,-1],[-2,0],[-1,-1],[-1,-2],[-1,-1],[-2,0],[-1,-1],[-2,0],[-3,3],[0,1],[2,3],[2,1],[3,0],[3,3],[6,3],[2,2],[2,6],[1,1],[1,3],[3,0],[2,-3],[0,-1],[0,1],[1,2],[1,2],[-1,1],[-3,1],[-2,1],[-2,0],[-1,1],[-1,1],[0,2],[0,2],[1,2],[1,2],[2,1],[3,1],[3,1],[2,0],[1,0],[1,-6]],[[393,8298],[-1,-1],[-1,0],[0,1],[-3,-1],[-1,0],[-1,4],[0,1],[0,2],[2,1],[2,1],[2,0],[3,-3],[2,-2],[0,-1],[-1,-1],[-3,-1]],[[401,8302],[-1,0],[-1,3],[-1,4],[2,1],[1,1],[1,-1],[1,-3],[1,-1],[1,-1],[-1,0],[-3,-3]],[[485,8317],[-3,-1],[-2,1],[-3,3],[0,3],[5,-2],[1,-1],[2,-3]],[[492,8343],[-1,0],[-2,1],[-1,2],[0,2],[4,3],[1,0],[0,-2],[0,-1],[-1,-4],[0,-1]],[[459,8351],[3,-10],[1,-2],[2,-1],[2,-1],[1,-1],[2,-2],[0,-1],[-8,3],[-5,-5],[-1,-1],[-14,0],[-2,-1],[-2,-2],[-3,-5],[-2,-2],[-1,-1],[-4,-2],[-4,1],[-2,0],[-2,3],[-1,4],[0,2],[1,2],[4,3],[1,2],[5,11],[1,1],[2,1],[4,-1],[3,3],[8,5],[2,1],[5,0],[2,-1],[1,-1],[1,-2]],[[573,8350],[-1,0],[-1,4],[-1,1],[2,-1],[1,-2],[0,-2]],[[569,8360],[0,-4],[-1,-1],[0,1],[-2,-1],[-1,1],[1,2],[0,1],[1,0],[0,2],[0,1],[0,2],[1,1],[1,-5]],[[1352,8356],[2,-7],[1,-3],[-3,-1],[-2,1],[-1,0],[-1,2],[1,4],[-1,2],[-2,1],[-1,-2],[-1,4],[2,3],[-1,3],[0,3],[0,1],[2,0],[3,-3],[2,-8]],[[559,8359],[-2,-1],[0,-2],[-1,0],[-2,-2],[-3,-6],[-2,-1],[2,5],[0,2],[0,1],[0,4],[1,0],[1,0],[1,4],[2,0],[2,4],[1,0],[-1,-3],[2,-2],[0,-2],[-1,-1]],[[1309,8346],[1,-1],[1,0],[1,2],[2,0],[1,-1],[1,0],[0,-3],[-1,-5],[-1,-2],[0,-2],[-3,1],[-3,3],[-3,5],[-2,4],[0,2],[-1,1],[-2,7],[-2,5],[-2,0],[-2,2],[-1,3],[1,2],[3,1],[6,-6],[1,-3],[2,-3],[0,-4],[1,-2],[2,-6]],[[546,8371],[0,-4],[-4,3],[-1,1],[1,1],[3,0],[1,-1]],[[536,8370],[1,0],[1,0],[2,4],[0,-1],[-1,-4],[2,-4],[1,-2],[0,-1],[-3,-1],[-3,1],[-1,0],[-2,-2],[0,2],[-1,8],[0,1],[2,3],[1,1],[1,0],[1,-1],[0,-2],[-1,-2]],[[1297,8383],[1,-2],[0,-1],[-4,-3],[0,-1],[-1,-3],[-1,0],[-2,-3],[-3,-3],[1,9],[-3,4],[3,3],[2,-1],[3,0],[3,2],[1,-1]],[[679,8399],[-1,-2],[-3,0],[-1,1],[0,2],[3,4],[1,1],[1,-2],[0,-4]],[[1362,8380],[-1,-6],[-2,-7],[-3,-3],[-2,0],[-2,3],[-1,0],[-2,1],[-1,2],[1,3],[0,2],[-1,-2],[-2,-2],[-3,-2],[-2,-5],[-1,-3],[-2,4],[0,7],[-1,4],[3,5],[3,4],[1,15],[10,7],[0,-1],[4,-5],[3,-7],[1,-4],[0,-6],[0,-4]],[[1290,8429],[5,-1],[5,0],[1,-3],[2,-2],[0,-3],[0,-2],[0,-1],[0,-2],[0,-1],[9,-5],[5,-6],[1,-3],[1,-2],[2,-7],[4,-7],[2,-2],[1,-3],[-3,2],[-6,5],[-1,-3],[-1,-2],[-1,-2],[1,-1],[5,2],[4,-5],[1,-1],[2,-4],[0,-1],[-1,-3],[-1,-1],[2,-1],[4,1],[1,-1],[-1,-10],[1,-4],[0,-2],[-1,-2],[0,-2],[1,-2],[0,-2],[-1,-4],[-2,-1],[-2,0],[-1,1],[-2,4],[-2,6],[-1,1],[-3,1],[0,1],[-2,0],[-1,2],[0,4],[-1,3],[0,2],[-1,0],[-1,-1],[0,-3],[0,-3],[-3,2],[-3,8],[-4,6],[-2,2],[1,1],[2,1],[1,0],[1,1],[-4,7],[0,2],[2,3],[-2,1],[-4,-1],[-2,1],[-1,2],[-1,2],[-4,1],[-1,0],[-2,3],[-1,2],[0,1],[2,2],[2,0],[2,-2],[1,0],[2,2],[1,3],[2,2],[-1,2],[-1,3],[-2,1],[-5,-2],[-4,-3],[-1,1],[-1,2],[5,6],[2,3],[-1,1],[-1,3],[0,6],[1,1]],[[1312,8424],[-2,-1],[-2,1],[-4,5],[0,1],[1,2],[2,3],[1,0],[6,0],[1,-1],[1,-1],[0,-1],[-1,-2],[0,-1],[0,-2],[0,-1],[-3,-2]],[[1330,8416],[0,-10],[-2,1],[-1,0],[-2,-2],[-2,1],[-1,1],[0,1],[0,3],[-1,2],[-5,0],[-1,1],[-1,3],[0,4],[0,1],[3,1],[1,5],[1,1],[4,9],[1,-1],[3,-5],[4,-9],[-1,-7]],[[703,8434],[-2,-1],[0,1],[0,1],[0,1],[1,2],[3,4],[3,2],[1,0],[1,-2],[-2,-3],[-5,-5]],[[716,8439],[-1,0],[-2,1],[0,2],[3,2],[3,0],[0,-1],[0,-2],[-1,-1],[-2,-1]],[[285,8446],[3,-1],[2,0],[2,0],[0,-1],[-3,-3],[-1,0],[-4,3],[1,2]],[[1312,8440],[0,-1],[-3,0],[-2,1],[0,2],[0,2],[1,2],[1,3],[1,6],[5,-6],[2,-3],[0,-4],[-1,-1],[-3,0],[-1,-1]],[[1278,8458],[2,-4],[2,0],[2,-3],[1,-4],[-1,-3],[-1,1],[-1,-2],[-1,-6],[0,-5],[0,-6],[-2,-6],[0,-3],[-1,-1],[0,-1],[-1,1],[-1,1],[-2,-3],[-2,0],[-1,7],[1,12],[3,3],[-2,3],[-3,4],[0,2],[-3,6],[0,1],[0,6],[3,4],[4,1],[2,-2],[2,-2],[0,-1]],[[1295,8467],[2,-2],[1,2],[2,0],[3,-2],[3,-2],[1,-3],[0,-2],[-1,-4],[1,-4],[0,-2],[-1,-1],[-1,-2],[-1,0],[-2,4],[-3,6],[-3,2],[0,-1],[1,-1],[2,-4],[0,-2],[1,-3],[1,-1],[0,-3],[0,-2],[0,-2],[-1,-1],[0,-1],[-5,1],[-3,-2],[-3,1],[-1,1],[-1,2],[0,5],[-1,6],[1,5],[-3,5],[-1,3],[-3,2],[-2,2],[1,2],[2,2],[5,0],[9,-4]],[[750,8474],[-4,-2],[-3,-3],[-1,-2],[-2,3],[0,5],[2,3],[10,-1],[0,-1],[0,-1],[0,-1],[-2,0]],[[273,8478],[-3,-3],[-2,1],[-1,2],[0,1],[8,2],[-2,-3]],[[1251,8487],[2,-6],[2,-5],[1,-6],[3,-12],[1,-5],[0,-2],[1,-7],[-1,-1],[0,-2],[-1,-2],[1,-5],[0,-7],[-1,-5],[-2,1],[-2,3],[-1,2],[-3,8],[-1,3],[0,3],[1,2],[1,1],[1,3],[-1,0],[-3,-1],[-2,3],[-2,1],[1,5],[-1,1],[-3,-2],[-1,2],[-1,1],[0,3],[1,2],[3,5],[0,1],[-2,1],[-2,2],[-1,6],[-2,3],[-1,0],[-3,-10],[-2,-2],[-4,-2],[1,3],[1,3],[-2,7],[0,3],[1,2],[3,1],[2,1],[1,2],[0,2],[2,6],[1,1],[3,0],[6,-6],[2,-1],[3,-4]],[[743,8516],[-1,-2],[0,1],[-2,2],[-3,2],[-1,2],[-1,1],[2,1],[3,-2],[2,-2],[1,-3]],[[753,8514],[0,-3],[1,1],[4,3],[3,1],[2,0],[3,-2],[0,-1],[0,-1],[-2,-3],[0,-2],[2,-3],[5,-2],[1,-1],[0,-1],[-4,-5],[-1,-2],[-1,0],[-6,1],[-5,2],[-3,0],[-2,-2],[1,-1],[5,0],[2,-2],[0,-2],[1,-2],[-1,-1],[-2,-1],[-3,0],[-3,-2],[-2,-2],[-6,-1],[-4,-3],[-2,-2],[-1,-2],[-1,-2],[-4,-1],[2,-1],[0,-1],[0,-2],[0,-1],[-3,-6],[-6,-5],[-2,0],[0,1],[-1,1],[0,1],[8,9],[0,1],[-3,0],[-3,3],[-2,-2],[-1,0],[1,2],[1,3],[0,1],[-1,1],[-2,0],[-3,0],[-2,0],[-1,-2],[0,-1],[3,1],[1,-1],[0,-1],[1,-2],[0,-2],[-1,-2],[-1,-3],[-2,0],[-5,7],[-2,10],[-3,7],[-1,2],[1,5],[4,6],[4,2],[3,3],[3,0],[2,0],[2,-1],[1,-2],[0,-1],[0,-1],[2,-2],[1,-5],[3,-4],[1,-2],[2,-2],[-2,4],[-1,4],[-1,9],[0,3],[1,0],[3,0],[0,1],[-4,3],[-1,3],[-1,1],[0,2],[2,3],[1,0],[1,1],[2,-1],[1,-1],[2,-5],[1,-2],[1,0],[1,1],[1,2],[1,1],[1,0],[3,-1],[1,1],[0,1],[0,3],[1,1],[0,1],[-1,3],[1,1],[7,-2],[2,-2],[-1,-5]],[[1230,8539],[4,-6],[0,-1],[-1,-4],[-2,-1],[0,-2],[2,-1],[1,1],[4,5],[1,2],[1,0],[5,-2],[5,-3],[1,-2],[1,-3],[-1,-8],[-4,-1],[-2,0],[-2,1],[-3,-3],[3,-2],[7,0],[3,-5],[0,-3],[-1,-6],[-4,1],[-4,4],[-8,5],[-2,0],[-1,-1],[0,-3],[0,-6],[-2,-4],[-6,2],[-3,5],[-2,8],[-8,9],[-3,2],[-3,6],[2,4],[0,3],[1,1],[3,2],[1,4],[2,-3],[3,-4],[0,3],[1,3],[3,0],[2,0],[1,3],[3,1],[2,-1]],[[1269,8538],[0,-2],[-4,0],[-4,3],[-2,2],[1,2],[3,1],[4,-3],[2,-3]],[[1259,8534],[7,-1],[5,0],[5,-9],[3,-7],[1,-5],[1,-4],[2,-5],[-1,-1],[-2,4],[-2,6],[-1,2],[-1,1],[-1,3],[-2,5],[0,2],[-1,2],[-1,0],[-1,0],[-1,-1],[0,-4],[1,-4],[5,-10],[4,-6],[0,-2],[1,-5],[-2,-2],[2,-5],[0,-1],[0,-1],[-5,-2],[-5,-9],[-4,-5],[-3,-1],[-1,1],[-1,2],[0,3],[-1,3],[2,2],[2,11],[0,4],[-3,5],[-2,4],[-1,5],[-1,15],[-1,5],[-1,4],[-2,3],[-1,4],[0,3],[0,2],[2,-2],[3,-6],[2,-3]],[[766,8545],[1,0],[1,3],[1,0],[3,-3],[2,1],[2,-4],[1,0],[1,1],[0,-1],[0,-3],[-2,-4],[-1,-1],[-2,1],[-2,2],[0,2],[-1,0],[-2,-3],[0,-1],[1,-2],[0,-1],[-2,0],[-2,0],[-2,-2],[-1,1],[0,3],[-1,0],[-1,-4],[-1,-2],[-3,-2],[0,-1],[-2,0],[-2,-1],[-2,0],[-9,4],[-2,2],[8,8],[4,4],[2,-1],[2,-1],[1,1],[0,3],[-2,3],[0,1],[5,2],[2,0],[2,-1],[1,-1],[2,-3]],[[764,8552],[-1,0],[-2,2],[-1,2],[1,1],[4,3],[2,0],[1,-1],[0,-2],[-1,-1],[-3,-4]],[[530,8558],[-2,-1],[-2,0],[-2,6],[1,0],[3,4],[6,3],[2,0],[-6,-12]],[[984,8629],[-1,0],[2,4],[3,4],[2,2],[3,2],[0,-2],[-4,-4],[-5,-6]],[[888,8643],[-1,-1],[-6,1],[1,3],[5,2],[4,-3],[-3,-2]],[[896,8629],[-3,-1],[-1,2],[2,4],[1,2],[1,1],[4,5],[4,3],[3,5],[4,8],[1,2],[1,1],[3,-2],[2,-3],[-1,-2],[-9,-10],[-1,-1],[-1,-4],[-1,-1],[-1,-1],[-1,-1],[0,-3],[-1,-1],[-2,0],[-1,-1],[-1,-1],[-2,-1]],[[385,8662],[3,-3],[1,0],[4,1],[2,-1],[1,-1],[1,-2],[0,-3],[0,-3],[0,-5],[0,-1],[2,-3],[1,-3],[0,-3],[-5,-1],[-5,-1],[-4,-2],[-1,-2],[1,-2],[-1,-1],[-1,1],[-2,2],[-3,1],[-8,2],[-10,7],[-4,1],[-4,5],[-4,7],[3,1],[2,0],[12,-1],[1,5],[2,1],[3,1],[4,3],[1,0],[2,-1],[3,1],[2,1],[1,-1]],[[969,8659],[-1,-1],[-2,0],[-2,1],[5,4],[0,-1],[0,-3]],[[933,8666],[1,-2],[5,0],[2,0],[1,-1],[-1,-1],[-2,-1],[-6,-3],[-5,-3],[-1,0],[-1,4],[-1,1],[0,2],[0,1],[1,2],[2,2],[1,0],[4,-1]],[[898,8666],[0,-2],[-1,-1],[1,-3],[-1,-5],[-1,-3],[-1,-1],[0,-1],[-1,0],[0,1],[0,2],[-2,0],[0,4],[1,1],[0,2],[0,1],[2,5],[0,1],[0,-2],[1,0],[1,3],[1,-2]],[[777,8661],[-1,-1],[2,3],[1,6],[1,-1],[1,-1],[-3,-6],[-1,0]],[[202,8666],[6,-4],[3,1],[3,-4],[2,-2],[-5,2],[-6,0],[-9,7],[-4,2],[1,4],[4,3],[1,-6],[4,-3]],[[891,8687],[-4,0],[-1,1],[-1,0],[1,3],[0,1],[2,1],[2,-1],[0,-2],[1,-3]],[[237,8849],[1,-1],[2,0],[5,0],[4,-2],[4,1],[6,4],[3,1],[4,1],[3,-1],[4,-3],[1,-1],[1,-2],[1,-3],[1,-2],[7,-3],[4,-1],[1,-1],[1,-2],[4,-1],[3,0],[2,0],[7,0],[7,-3],[-1,-5],[-2,-3],[-7,1],[-8,-1],[-3,-3],[-2,-3],[0,-4],[-2,-1],[-1,-1],[-1,2],[-2,6],[-1,2],[-1,1],[-4,1],[-3,2],[-3,0],[-1,2],[-1,3],[-1,1],[-3,3],[-3,1],[-9,4],[-3,1],[-3,-1],[-3,-2],[-3,-2],[-3,-2],[-3,0],[-4,1],[-3,2],[-1,2],[-1,3],[0,3],[1,3],[1,7],[3,1],[5,-5]],[[386,8998],[-1,0],[0,1],[3,2],[6,3],[-4,-3],[-4,-3]],[[1388,8403],[-1,-3],[-1,-3],[-1,-4],[0,-4],[0,-4],[0,-3],[2,-7],[1,-3],[0,-3],[-4,-9],[-1,-5],[0,-2]],[[1373,8338],[-1,2],[-7,1],[-2,8],[-1,6],[-2,6],[0,1],[1,4],[7,3],[0,1],[-2,1],[-1,1],[-1,6],[0,5],[0,4],[-1,7],[-1,4],[-5,9],[0,2],[2,3],[1,2],[-7,-4],[-10,-5],[-4,-3],[-1,-1],[0,-1],[1,-3],[0,-1],[-1,-2],[-1,-5],[-2,-5],[-1,-1],[-4,2],[-1,1],[-2,7],[0,2],[2,2],[2,3],[2,5],[5,14],[2,0],[6,2],[-8,2],[-2,0],[-1,2],[-1,3],[-1,3],[-3,1],[-2,2],[-2,3],[-1,2],[-1,2],[0,3],[-1,1],[-2,1],[-1,1],[0,6],[-5,2],[-1,2],[-3,4],[-1,2],[0,2],[1,4],[-1,1],[-2,0],[-16,7],[1,9],[-3,13],[-3,5],[1,2],[1,1],[1,0],[6,-4],[5,-4],[1,1],[-9,9],[-2,3],[0,3],[0,2],[0,1],[9,-1],[-8,3],[-2,0],[-2,-4],[-1,-1],[-2,1],[-2,5],[-2,3],[-4,5],[-1,3],[0,5],[0,4],[3,10],[2,2],[0,1],[-1,0],[-1,-1],[-2,-5],[-3,-7],[-2,-3],[-2,1],[-2,3],[-4,4],[-5,1],[-3,4],[-5,11],[0,5],[-1,2],[-2,1],[-2,3],[-2,14],[-3,9],[-1,5],[0,5],[-1,-4],[-1,-2],[-2,0],[2,-4],[1,-2],[-1,0],[-2,0],[3,-7],[2,-10],[2,-8],[1,-6],[1,-5],[1,-4],[2,-10],[0,-2],[0,-1],[-1,-2],[-1,-1],[-5,1],[-1,3],[-3,4],[-3,2],[-8,-1],[-1,1],[0,3],[1,7],[-1,2],[-4,10],[0,2],[6,4],[-3,1],[-2,-2],[-1,1],[-2,6],[-1,2],[0,1],[0,-6],[1,-3],[0,-2],[0,-2],[-1,-2],[-1,-1],[-1,0],[-2,1],[-2,2],[-2,1],[-1,1],[-1,3],[-2,2],[-7,2],[-4,3],[-1,-1],[2,-3],[0,-2],[-1,0],[-2,-3],[0,-1],[2,1],[3,0],[4,-2],[3,-2],[1,-1],[1,-2],[0,-1],[4,-2],[0,-1],[-2,-4],[4,0],[3,-1],[3,-5],[1,-3],[1,-4],[-1,-2],[-1,0],[-10,-2],[-3,-4],[-1,0],[-2,1],[-5,4],[-6,3],[-13,11],[0,3],[-1,1],[-2,1],[-3,2],[-3,5],[-2,3],[0,3],[-2,3],[-6,6],[-3,2],[-3,1],[-2,1],[-1,1],[1,1],[0,1],[-5,1],[-5,3],[-13,8],[-6,5],[-4,2],[-2,1],[0,2],[1,1],[2,1],[2,1],[3,5],[0,2],[-2,4],[0,3],[0,2],[0,2],[0,1],[2,1],[0,1],[1,-1],[4,-4],[0,-2],[0,-6],[1,-8],[0,1],[0,2],[1,5],[0,2],[1,2],[1,1],[3,0],[2,0],[-7,4],[-4,6],[-1,0],[-3,1],[-2,-3],[-7,-8],[-2,-1],[-8,-5],[-6,-1],[-6,1],[-5,1],[-14,7],[-2,2],[3,5],[0,1],[-1,4],[-1,2],[-1,0],[0,-1],[0,-3],[-1,-1],[-2,-2],[-4,-1],[-12,4],[-13,3],[-11,0],[-15,-2],[-9,-3],[-5,0],[-4,1],[-1,1],[3,1],[-1,2],[-2,3],[-4,3],[-6,1],[-3,1],[-1,1],[-2,1],[-3,2],[-1,2],[1,7],[1,4],[1,3],[3,5],[-1,0],[-4,-4],[-3,-3],[-4,-5],[-1,-2],[-3,-2],[-3,0],[-6,3],[-4,2],[-3,0],[-2,0],[3,3],[1,2],[2,4],[0,1],[-13,1],[0,2],[0,1],[-1,1],[-2,1],[-2,-1],[-5,-2],[-1,2],[0,1],[2,0],[2,3],[-3,2],[-2,2],[-1,1],[0,6],[1,3],[8,4],[-2,1],[-6,0],[-4,-3],[-4,-4],[-3,-2],[-1,1],[-2,0],[-3,0],[-1,-1],[-1,-2],[-1,-1],[-1,-1],[-1,1],[-1,1],[-3,2],[-1,1],[-1,-1],[-1,-3],[-1,-1],[-4,-1],[-2,0],[-3,3],[0,1],[1,3],[6,12],[-1,0],[-2,-2],[-4,-5],[-2,-1],[-3,0],[-1,0],[-2,0],[-2,-1],[-1,-2],[-1,-1],[1,0],[3,1],[2,1],[0,-1],[-2,-5],[-2,-5],[-1,-1],[-2,0],[-3,-1],[0,-1],[5,-4],[1,-1],[2,-1],[1,-1],[-1,-4],[-1,-2],[-1,0],[-3,0],[-1,-1],[-3,-2],[-1,-2],[3,1],[3,1],[4,0],[3,1],[1,2],[2,-1],[2,-2],[1,-2],[-1,-2],[-1,-2],[-3,0],[-1,-2],[-1,-1],[0,-3],[0,-3],[0,-6],[-1,-1],[-1,0],[-1,-1],[-3,-8],[-1,-1],[-1,1],[-1,0],[-1,-1],[-2,-1],[-3,0],[-3,0],[-4,2],[-2,1],[-1,2],[-4,-2],[-1,0],[-3,6],[0,-1],[-1,-5],[-1,-2],[-2,-4],[-2,-8],[0,1],[-2,7],[-1,1],[-2,-4],[0,-1],[0,-5],[-5,2],[-1,0],[1,-4],[0,-1],[-6,-7],[-2,0],[-1,1],[-1,0],[-4,-3],[-1,0],[-2,2],[-1,0],[0,-2],[0,-3],[-2,-3],[-4,-5],[-2,-2],[-1,-4],[-3,2],[-4,1],[1,-2],[0,-1],[-2,-1],[-2,0],[-2,1],[-3,-1],[-4,-2],[-3,0],[-5,4],[-1,0],[0,2],[1,3],[1,2],[1,2],[4,3],[5,1],[3,2],[4,4],[2,3],[4,8],[-1,1],[-9,-8],[-1,0],[-2,0],[-7,2],[-1,2],[-1,3],[2,8],[1,4],[3,6],[5,6],[1,5],[3,11],[0,5],[-1,6],[0,3],[1,1],[10,6],[5,4],[9,7],[3,0],[1,-3],[3,-1],[2,-2],[3,1],[4,1],[6,0],[13,-5],[3,0],[0,1],[-2,3],[-9,1],[-3,2],[-11,7],[-2,3],[1,1],[2,2],[1,1],[1,1],[1,3],[3,3],[3,3],[8,5],[-3,0],[-5,-1],[-2,-1],[-4,-3],[-1,-2],[-2,-5],[-1,-1],[-4,0],[-10,-1],[-2,3],[-2,0],[-9,-6],[-3,-3],[-3,-4],[-3,-2],[-5,-2],[-4,-2],[-4,-4],[-1,-3],[0,-1],[1,-5],[-1,-1],[-3,0],[-3,-3],[-8,-9],[-1,-3],[0,-1],[1,-3],[0,-1],[-3,-3],[-4,-4],[-3,-2],[-2,0],[-2,1],[-4,3],[-3,0],[0,-1],[4,-2],[4,-4],[2,-3],[1,-2],[0,-3],[-1,-2],[-2,-5],[-3,-1],[-7,-1],[-2,-2],[-1,0],[5,-2],[0,-1],[0,-4],[-2,-1],[-4,-2],[-3,-1],[-1,1],[1,2],[0,1],[-2,1],[-1,-1],[-5,-5],[-1,0],[2,-1],[0,-1],[-3,-3],[-1,-3],[-2,-2],[-7,-6],[0,-2],[-2,-5],[-1,-5],[2,-2],[6,-2],[3,-1],[4,-2],[6,-4],[3,-3],[0,-2],[0,-1],[-1,-2],[-2,-4],[-5,-6],[-2,-1],[-4,-2],[-1,-1],[-4,-5],[-2,-3],[1,-3],[-1,-1],[-6,-4],[0,-1],[2,0],[0,-3],[-1,-4],[-1,-1],[-3,0],[-5,-2],[0,-3],[-12,-3],[-2,-5],[-2,-2],[-4,-5],[-3,-1],[-3,-1],[-2,-2],[0,-2],[-1,-1],[-3,-3],[-1,-3],[-1,-1],[-5,-1],[-1,-1],[-1,-4],[-1,0],[-2,1],[-2,-1],[-6,-5],[-1,-2],[0,-1],[1,-1],[2,-3],[-1,-2],[-2,-6],[0,-1],[-3,-1],[-1,-4],[-2,1],[-2,-1],[-1,-2],[-2,-1],[-1,0],[-2,-2],[-2,-3],[-2,-2],[-2,-1],[-2,0],[-1,0],[-2,0],[-1,-1],[-2,-2],[-1,-5],[-1,-2],[-1,-1],[-2,1],[-3,1],[-2,-1],[-5,-3],[-1,-2],[3,0],[1,-1],[0,-1],[-1,0],[-3,0],[-1,-1],[-2,-1],[-5,-2],[-1,-1],[-4,-5],[0,-2],[2,1],[2,-1],[2,-2],[0,-1],[1,-3],[-4,-5],[-1,-2],[-1,-1],[-1,6],[0,1],[-1,0],[-1,-2],[-3,-6],[-2,-3],[-18,-9],[-2,-2],[-1,-3],[0,-3],[-2,-3],[-1,-1],[0,1],[0,8],[-1,2],[-1,1],[-1,0],[-1,0],[-2,-2],[-1,-1],[-1,0],[-3,-1],[-5,-6],[-4,-2],[-1,-1],[-1,-3],[-1,-1],[-2,0],[-2,1],[-1,-1],[-2,-3],[-1,0],[-3,1],[-2,-1],[-2,-3],[-2,-2],[-2,-1],[-6,-1],[-2,1],[-1,1],[0,3],[1,3],[1,2],[1,1],[2,0],[3,-1],[0,1],[-1,1],[-3,2],[-3,1],[-2,-1],[-2,-1],[-1,-2],[-1,-2],[-1,-6],[-1,-2],[-6,-11],[-3,-3],[-3,0],[-1,-1],[-2,-3],[-1,-1],[-2,0],[-1,0],[-1,1],[0,1],[1,1],[0,2],[-2,4],[-1,2],[-3,0],[0,-2],[1,-8],[0,-2],[-2,-2],[-4,-3],[-1,0],[-4,5],[-3,1],[0,-1],[0,-4],[0,-3],[-3,-3],[-2,-2],[-1,0],[0,3],[1,4],[0,3],[0,3],[0,2],[0,2],[5,4],[2,1],[1,-2],[1,0],[2,1],[1,1],[0,2],[2,3],[4,3],[4,6],[4,8],[6,7],[6,6],[6,5],[14,7],[1,-1],[-1,-2],[0,-1],[2,0],[5,1],[2,1],[0,-1],[-1,-2],[-3,-2],[1,-1],[4,-7],[1,-1],[1,0],[1,1],[-1,5],[2,1],[3,0],[2,-1],[1,-1],[1,-1],[3,-1],[1,0],[1,2],[-1,2],[-5,4],[-1,1],[0,3],[0,3],[2,4],[2,6],[2,4],[4,5],[3,2],[7,8],[14,7],[4,5],[5,5],[2,1],[0,-2],[0,-2],[3,-1],[2,0],[1,0],[1,2],[-1,3],[0,4],[0,3],[1,2],[2,4],[3,5],[4,6],[3,3],[2,1],[3,2],[4,6],[1,1],[3,1],[1,0],[1,-2],[1,0],[3,-1],[2,1],[0,1],[-2,0],[-1,1],[-1,4],[-2,2],[-1,2],[1,4],[2,8],[0,9],[1,6],[4,1],[6,2],[-4,2],[-1,0],[-3,1],[-1,6],[0,4],[2,4],[6,8],[8,6],[-1,0],[-1,2],[3,11],[3,10],[-4,-9],[-5,-6],[-15,-7],[-10,-7],[-4,-1],[-3,1],[-3,6],[-1,3],[-2,3],[1,6],[1,3],[3,1],[4,-2],[3,0],[-4,3],[-6,3],[-2,-1],[-2,-5],[-3,-3],[-2,1],[-1,2],[1,-5],[-2,-6],[-1,-4],[3,-12],[-1,-4],[-4,-2],[-4,4],[-8,14],[-2,4],[-6,7],[-2,-1],[-3,-3],[-2,-1],[-7,5],[-3,3],[-3,5],[-4,-2],[-4,-3],[-4,-5],[-3,0],[-8,-4],[-1,0],[-1,-3],[-1,-1],[-1,-4],[-11,-3],[-11,2],[4,2],[4,2],[4,4],[-2,6],[0,3],[0,4],[4,5],[-4,0],[-3,-2],[-3,5],[-1,7],[3,5],[2,4],[1,5],[0,4],[-3,7],[-6,16],[-3,11],[-5,6],[4,10],[4,9],[5,4],[0,1],[-3,0],[-2,-1],[-2,-3],[-1,-2],[-6,-12],[-4,-5],[-2,-2],[4,-2],[0,-2],[1,-4],[-1,-5],[-1,-3],[-4,0],[-4,-4],[-10,-4],[-13,-3],[-6,1],[-7,5],[0,3],[1,2],[-10,9],[-5,9],[-4,0],[-3,3],[-4,3],[0,3],[1,3],[-3,1],[-3,0],[-3,1],[9,11],[3,8],[3,1],[3,-1],[5,-3],[4,-1],[2,-2],[1,-3],[-2,-4],[-1,-3],[2,1],[5,5],[3,4],[2,-1],[1,0],[2,-5],[3,-4],[5,4],[3,5],[-2,3],[-3,1],[-8,2],[2,1],[5,0],[2,2],[-2,2],[-3,2],[-6,-6],[-13,0],[-9,3],[-8,0],[-2,0],[-1,2],[5,5],[3,2],[0,2],[-2,0],[-4,-1],[-1,2],[0,3],[-1,0],[-1,-2],[-2,1],[-2,2],[1,1],[2,3],[-1,0],[-2,0],[-1,-3],[0,-3],[0,-4],[-3,0],[-2,0],[-2,4],[-2,8],[-4,2],[-2,4],[3,5],[-1,2],[-3,1],[-4,-3],[-1,3],[-1,2],[0,4],[1,0],[1,-1],[7,2],[1,1],[-6,3],[-1,4],[2,1],[4,1],[7,1],[-3,4],[-1,2],[0,3],[1,5],[7,11],[7,10],[2,2],[4,2],[3,-1],[3,-2],[0,1],[-1,0],[-1,4],[4,2],[3,4],[0,2],[-3,-2],[-3,-3],[0,3],[-1,7],[1,7],[1,3],[3,3],[7,1],[1,-1],[0,2],[-4,4],[2,3],[1,2],[8,3],[5,-1],[6,-3],[3,-4],[0,-2],[-1,-1],[-2,-2],[-1,-1],[1,-1],[2,3],[4,3],[2,-2],[2,-2],[2,0],[6,2],[4,2],[4,5],[5,4],[7,11],[2,4],[3,1],[2,-1],[1,-3],[3,-1],[13,0],[6,2],[5,4],[5,6],[3,4],[1,5],[-2,6],[-2,6],[-2,13],[-6,8],[-5,2],[-3,0],[2,5],[6,0],[4,1],[4,2],[1,2],[1,4],[0,5],[-1,2],[-2,2],[-3,4],[-2,1],[-1,0],[-8,-7],[-5,0],[-3,1],[-3,-4],[-9,-4],[-4,-4],[-9,-9],[-2,-4],[-2,0],[-2,8],[-9,8],[-3,-3],[1,-2],[2,-2],[4,-1],[-2,-2],[-1,-3],[-3,2],[-6,5],[-7,2],[-16,0],[-11,-5],[-1,1],[-1,1],[-2,-1],[0,-2],[-2,-1],[-2,-1],[-4,1],[-9,3],[-19,4],[-5,2],[-5,6],[1,4],[2,2],[-1,5],[-3,2],[-8,8],[-3,4],[1,0],[1,-1],[3,-1],[6,2],[2,5],[5,1],[4,0],[-1,1],[-1,1],[-11,3],[-2,-1],[-20,5],[-16,8],[-2,2],[-1,4],[2,3],[2,2],[0,-2],[1,-2],[9,4],[5,6],[9,1],[2,2],[3,3],[4,5],[6,3],[4,3],[5,1],[4,-2],[2,-1],[8,0],[2,1],[1,1],[1,1],[-8,4],[1,3],[1,2],[9,5],[7,2],[4,0],[11,6],[6,2],[11,1],[9,1],[2,-3],[-4,1],[-3,-1],[2,0],[2,-2],[-1,-2],[-3,-7],[0,-5],[-2,-2],[-2,-2],[10,-8],[14,0],[8,1],[5,-2],[4,-1],[10,1],[8,-1],[3,0],[7,12],[3,2],[3,-2],[4,-2],[3,1],[2,-3],[-1,6],[-2,3],[-11,4],[-8,-2],[-3,2],[1,5],[-8,11],[-4,3],[-4,0],[-2,4],[-2,5],[4,2],[3,1],[3,-2],[3,-7],[3,-1],[0,-6],[3,-6],[9,-6],[7,2],[5,0],[3,-1],[8,-6],[3,0],[12,3],[0,5],[-1,3],[-3,3],[-7,-1],[-6,4],[-6,-1],[-9,-6],[-5,2],[-3,3],[-5,4],[-1,6],[4,6],[3,4],[-2,2],[-7,2],[-12,-2],[0,2],[0,3],[-5,-5],[-5,1],[-7,-1],[-15,5],[-5,5],[-2,5],[-4,11],[-5,8],[-35,25],[-16,6],[-8,8],[-5,1],[-4,1],[-6,2],[4,3],[3,1],[-3,-3],[2,-1],[3,2],[2,2],[3,9],[3,12],[-1,5],[19,-1],[13,1],[5,1],[16,2],[4,2],[8,4],[9,8],[8,10],[1,3],[1,-1],[1,0],[1,4],[1,9],[4,9],[16,19],[8,8],[3,3],[2,3],[2,-3],[1,0],[1,-1],[-2,-1],[-3,-2],[-3,-2],[-1,-1],[2,0],[6,2],[4,2],[18,4],[10,7],[0,1],[14,9],[2,-1],[3,-1],[-4,-5],[2,-2],[-2,-6],[5,0],[1,-3],[1,2],[-1,4],[1,4],[1,2],[3,-1],[9,3],[-10,0],[-6,6],[-4,0],[11,9],[11,5],[2,0],[1,-1],[0,-1],[-2,-1],[-2,-2],[1,-2],[1,0],[5,1],[2,2],[11,0],[3,1],[1,1],[13,0],[3,1],[8,5],[8,6],[3,3],[7,8],[5,5],[9,5],[2,-1],[-3,-1],[-2,-2],[3,-3],[18,-6],[4,0],[2,-4],[-1,-3],[-5,-4],[-9,-4],[2,-1],[2,-4],[3,0],[5,1],[3,2],[8,7],[2,4],[2,1],[6,-1],[3,-2],[4,-3],[-1,-4],[-2,-2],[6,-2],[5,-1],[6,-2],[7,4],[6,1],[6,0],[7,2],[13,-3],[3,1],[5,-1],[5,-2],[2,-2],[-5,-4],[-1,-5],[2,-2],[3,0],[1,-3],[2,0],[11,0],[-1,-1],[0,-2],[-4,-3],[20,-2],[3,2],[4,0],[9,3],[3,-1],[4,-3],[4,0],[3,0],[8,4],[9,0],[4,-1],[4,1],[11,-5],[5,0],[5,-6],[3,0],[4,2],[3,0],[3,-2],[4,-1],[3,-3],[2,-2],[18,-2],[9,1],[13,-1],[6,-1],[6,0],[11,-6],[6,-1],[1,-2],[16,-1],[5,3],[10,1],[9,3],[5,0],[6,-1],[2,0],[2,1],[14,-4],[8,-6],[3,-4],[17,-6],[5,-3],[3,-3],[2,-1],[1,1],[6,0],[2,0]],[[3296,5915],[-1,0],[1,1],[0,1],[0,-1],[0,-1]],[[3299,5932],[0,-1],[-1,1],[1,0],[0,1],[-1,0],[0,1],[1,0],[0,1],[1,1],[0,-1],[-1,-1],[0,-2]],[[3300,5942],[0,-1],[-2,4],[0,4],[1,3],[1,1],[1,0],[1,-3],[-1,-6],[-1,-2]],[[3305,5695],[-1,-2],[-1,6],[1,2],[3,4],[1,1],[0,-1],[0,-1],[1,-2],[0,-3],[-1,-3],[-3,-1]],[[3310,5710],[-3,-2],[0,2],[1,2],[2,1],[0,1],[1,1],[1,0],[1,-1],[-2,-2],[-1,-2]],[[3188,5812],[-1,-1],[-3,1],[-1,2],[0,2],[3,0],[2,-3],[0,-1]],[[3226,5825],[1,-8],[0,-1],[-3,-5],[-2,0],[-2,0],[-1,1],[-2,3],[-1,-1],[-4,1],[-1,1],[1,4],[3,2],[1,0],[1,-2],[2,-2],[2,-1],[1,4],[3,6],[1,-2]],[[3019,5867],[-1,-3],[-2,-3],[-2,-2],[-11,-5],[-1,-2],[-1,-2],[0,-5],[0,-4],[3,-13],[1,-3],[5,-7],[-1,-1],[-2,0],[1,-9],[3,-6],[0,-4],[-2,-13],[-4,-7],[-2,-9],[-2,-3],[-4,-17],[3,-10],[0,-5],[3,-7],[2,-3],[1,-2],[0,-5],[1,-7],[1,-4],[2,-1],[3,0],[6,4],[2,2],[1,4],[3,7],[0,10],[1,11],[-1,7],[-3,11],[-2,7],[-3,7],[-2,12],[-1,3],[-1,6],[-1,9],[3,3],[-1,7],[6,2],[12,12],[8,3],[9,7],[2,3],[2,5],[1,1],[4,-5],[3,2],[1,4],[-2,7],[-2,0],[-8,-3],[-1,4],[0,2],[-2,9],[1,7],[2,6],[2,2],[3,2],[3,-3],[1,-4],[1,-3],[1,-9],[1,-10],[1,-6],[2,-5],[2,0],[1,1],[9,1],[5,-3],[6,-2],[6,-7],[6,-8],[1,-7],[1,-6],[1,-4],[-1,-4],[1,-7],[1,-6],[3,-5],[7,-1],[8,3],[13,3],[4,2],[20,1],[4,-3],[1,-3],[0,-3],[6,-12],[6,-2],[5,-4],[4,-2],[6,-3],[2,0],[3,1],[2,0],[19,21],[10,0],[1,1],[1,2],[-3,3],[-8,1],[-3,-2],[-1,5],[2,0],[9,2],[11,-1],[8,4],[5,0],[2,0],[7,2],[13,-3],[10,2],[-1,-3],[-4,-2],[-5,-1],[-4,-5],[-9,1],[-6,-2],[2,-1],[0,-5],[1,-1],[1,0],[2,-4],[0,-3],[1,-5],[-1,-5],[-1,-3],[2,1],[2,3],[0,2],[0,3],[1,-1],[1,-1],[3,-15],[3,-8],[0,1],[1,0],[0,1],[1,4],[1,-2],[1,-1],[0,3],[0,4],[0,2],[1,0],[1,-1],[2,-1],[3,-5],[2,-5],[0,-3],[1,-1],[1,-2],[1,-2],[0,4],[-1,3],[0,3],[4,0],[1,5],[2,-3],[6,-12],[2,-2],[6,-3],[4,-6],[2,-5],[-1,-6],[-4,-2],[-1,-4],[-1,-3],[0,-4],[-1,-4],[-1,-1],[0,-6],[-2,-7],[-2,-7],[-10,0],[3,-3],[2,-2],[4,-6],[3,5],[4,0],[5,5],[2,1],[9,-3],[2,4],[2,1],[4,-1],[5,-4]],[[3205,6244],[-2,0],[1,2],[2,0],[1,0],[-2,-2]],[[3211,6247],[-1,0],[0,1],[0,2],[3,0],[-2,-3]],[[3214,6263],[0,-2],[-2,2],[-1,0],[-1,1],[3,0],[1,-1]],[[3201,6209],[2,-3],[3,0],[-3,-2],[-6,-1],[0,4],[4,2]],[[3204,6241],[-2,-2],[-1,1],[-1,0],[1,2],[3,-1]],[[3198,6240],[-2,-1],[-3,3],[3,1],[1,-1],[1,-2]],[[7961,5684],[-1,0],[-1,1],[3,4],[0,-3],[0,-1],[-1,-1]],[[7890,5782],[0,-3],[0,-6],[-1,-7],[0,-3],[0,-2],[-2,13],[-3,5],[0,2],[1,0],[3,3],[1,0],[1,-2]],[[7976,5783],[-2,-4],[0,3],[2,2],[0,1],[1,0],[-1,-2]],[[7972,6379],[-1,0],[-2,4],[1,3],[3,-2],[0,-1],[0,-1],[0,-2],[-1,-1]],[[7968,6383],[-1,-1],[-1,2],[-1,2],[1,3],[1,-4],[1,-2]],[[7986,6389],[-2,-1],[-1,0],[2,3],[1,3],[1,1],[0,-3],[-1,-3]],[[7988,6406],[-4,-7],[-1,0],[1,8],[1,2],[2,-3],[1,0]],[[7998,6423],[-1,-1],[-3,0],[-3,-5],[-2,-2],[-3,-2],[-3,-3],[-1,-5],[0,-4],[-1,-4],[-5,-7],[-1,1],[-1,2],[-2,0],[-1,-1],[-1,0],[-2,-2],[-2,1],[-1,2],[-1,0],[-1,0],[-1,-2],[2,-9],[1,-4],[-6,-12],[1,-8],[-2,-6],[-3,-4],[-7,-13],[-3,0],[-2,-3],[-5,-20],[0,-7],[0,-5],[0,-5],[-2,-9],[-2,-5],[-1,-5],[3,-11],[1,-1],[1,-6],[1,-4],[2,-4],[4,-11],[3,-3],[2,-3],[5,-9],[3,-7],[-2,-4],[1,-9],[-3,3],[0,-1],[4,-5],[6,-17],[5,-8],[6,-10],[1,-9],[5,-6],[6,-9],[-1,-2],[2,-2],[4,-5],[2,-4],[1,-5],[1,-1],[1,1],[2,1],[1,-1],[2,-5],[2,-4],[1,-4],[1,0],[1,0],[0,-4],[0,-2],[3,-7],[2,-6],[3,-11],[3,-5],[2,-4],[2,-2],[2,-12],[1,-10],[3,-12],[1,-5],[0,-9],[2,-10],[1,-6],[1,-7],[0,-3],[1,-3],[1,-11],[0,-5],[-1,5],[0,-15],[1,-8],[0,-10],[1,-4],[1,-11],[2,-4],[0,-14],[0,-6],[-1,4],[-2,4],[-1,-2],[-2,-4],[2,-14],[-2,1],[0,-20],[1,-4],[0,-3],[0,-2],[-1,3],[0,3],[0,-1],[0,-2],[-1,-3],[-1,-4],[1,-4],[0,-3],[0,-3],[-1,-4],[-3,0],[-1,-8],[0,-7],[-5,-1],[-3,-7],[-4,-3],[-4,-6],[-4,-6],[-3,-1],[-2,-2],[-3,-10],[-4,-1],[-8,-8],[-3,-4],[-2,-2],[-3,-3],[-1,1],[-1,3],[-3,1],[-2,4],[0,4],[0,2],[-1,-3],[-1,-10],[0,-2],[-1,-1],[-3,3],[-2,6],[-4,-4],[2,-1],[1,0],[1,-1],[1,-4],[0,-2],[0,-2],[-3,-1],[-5,1],[3,-4],[4,-2],[1,-3],[0,-2],[-2,-3],[-1,-4],[0,-2],[0,-3],[-2,-2],[-1,0],[-3,4],[-9,17],[2,-5],[9,-19],[1,-6],[1,-4],[-1,-2],[-2,-3],[-3,0],[-5,7],[-7,17],[-3,2],[8,-19],[1,-5],[1,-5],[0,-3],[-1,-3],[-18,-17],[-3,-8],[-2,-9],[-4,-5],[-2,-5],[-6,-3],[-3,1],[3,9],[-2,3],[0,22],[1,24],[1,12],[3,3],[2,2],[1,3],[-1,3],[-1,4],[-2,2],[-3,0],[-2,5],[-1,0],[-2,-1],[-2,2],[0,3],[-3,4],[-2,4]],[[7929,6229],[-2,2],[-2,0]],[[9718,4021],[-1,-3],[-1,0],[-2,2],[0,3],[3,0],[1,-2]],[[9707,4058],[-1,-6],[-3,2],[-2,4],[-1,4],[0,8],[2,1],[1,-1],[0,-7],[4,-5]],[[9703,4093],[-2,-3],[-1,0],[-7,7],[0,2],[0,7],[1,4],[2,1],[1,0],[1,-6],[3,-2],[-2,-2],[3,-4],[1,-4]],[[9678,4173],[3,-8],[1,0],[-2,-6],[-3,-1],[-4,2],[1,2],[-1,2],[-1,0],[-1,-1],[-1,1],[1,3],[2,6],[1,0],[1,0],[3,0]],[[9678,4217],[1,0],[-1,-3],[-3,3],[-3,-1],[-1,0],[-1,2],[-1,4],[0,4],[2,2],[1,-3],[1,-1],[1,-1],[2,-4],[2,-2]],[[9674,4243],[-3,-1],[-5,2],[-1,3],[-1,2],[1,2],[2,1],[3,6],[1,-3],[1,-6],[1,-2],[1,-2],[0,-2]],[[9649,4257],[2,-2],[1,-2],[4,-6],[1,0],[1,-3],[1,-1],[1,-4],[1,-3],[-2,-4],[-4,2],[-2,-5],[-3,1],[0,3],[-1,6],[-1,9],[0,5],[-1,3],[-2,-2],[-1,-1],[-2,5],[1,8],[0,3],[2,0],[2,-2],[2,-10]],[[9644,4278],[0,-1],[-3,3],[0,4],[3,-1],[0,-5]],[[9672,4264],[-1,0],[0,3],[-2,14],[1,12],[1,-2],[2,-23],[0,-3],[-1,-1]],[[9663,4295],[-2,-3],[-3,0],[-1,2],[4,8],[5,2],[-3,-9]],[[9671,4301],[-1,-4],[-1,4],[0,18],[0,1],[0,1],[2,-13],[0,-7]],[[9631,4330],[2,-19],[2,0],[1,1],[1,4],[1,7],[1,1],[1,0],[-1,-3],[1,-5],[1,-3],[1,-1],[1,-15],[1,-3],[-1,-2],[-2,-6],[-5,1],[-3,-4],[-2,0],[0,4],[-1,3],[-2,6],[0,12],[-3,20],[0,6],[1,6],[1,1],[2,-6],[2,-5]],[[9654,4362],[-1,-3],[-3,1],[-1,1],[0,5],[1,2],[2,1],[3,-2],[-1,-5]],[[9652,4383],[-1,-1],[-1,1],[-1,7],[0,2],[2,2],[2,-4],[0,-2],[0,-2],[0,-1],[-1,-1],[0,-1]],[[54,4359],[-1,0],[-2,0],[-1,4],[1,1],[1,-1],[1,-2],[1,-1],[0,-1]],[[107,4416],[-1,-1],[0,3],[0,3],[1,1],[1,-2],[-1,-4]],[[237,4375],[-7,0],[-4,2],[-1,0],[-4,6],[0,3],[2,2],[3,1],[7,-5],[1,-3],[2,-1],[1,-1],[0,-3],[0,-1]],[[213,4408],[3,-5],[1,-7],[-1,-7],[-3,1],[-4,-1],[-2,0],[-3,9],[-2,4],[-1,3],[3,0],[4,2],[5,1]],[[6493,5912],[1,-1],[3,2],[8,0],[9,-6],[-2,-2],[-1,-2],[-4,-2],[-4,-5],[-11,-3],[-4,2],[-3,4],[-5,7],[2,4],[1,1],[1,2],[2,3],[3,0],[4,-4]],[[6187,5973],[-2,-2],[1,5],[2,1],[-1,-4]],[[6188,5989],[0,-2],[-1,1],[-2,3],[2,3],[1,-3],[0,-2]],[[6182,6065],[0,-1],[-1,2],[1,5],[1,2],[0,-4],[0,-2],[-1,-2]],[[6474,6143],[-14,-11],[-4,-4],[-3,-6],[-3,-7],[-1,-12],[1,-11],[0,-6],[-4,-4],[-3,-3],[-4,-5],[-2,-1],[-2,-3],[-2,-3],[-8,-6],[-9,-5],[-13,-6],[-5,-6],[-5,-5],[-7,-1],[-10,-6],[-6,-5],[-7,-8],[-1,-3],[-1,-5],[-3,-5],[-4,-9],[-3,-4],[-2,0],[-4,-2],[-5,-1],[-8,3],[-2,-2],[-1,-3],[-6,-6],[-7,-11],[-4,-3],[-8,-4],[-5,-5],[-3,-1],[-5,-1],[-8,0],[-8,-2],[-7,-3],[-4,-6],[-4,-10],[-6,-4],[-2,-3],[-2,-7],[-4,-2],[-3,-1],[-4,3],[-7,-8],[-3,-2],[-4,0],[-3,-2],[-2,0],[-3,4],[-6,4],[-4,-3],[0,8],[-7,25],[2,21],[0,3],[-2,10],[-4,9],[0,11],[-1,8],[-1,8],[0,2],[0,2],[-2,13],[0,2],[-1,3],[1,2],[0,2],[-1,4],[-1,7],[-6,6],[1,6],[2,-2],[1,-2],[0,4],[0,2],[-2,16],[3,22],[-1,20]],[[6051,2480],[-1,-1],[-6,1],[0,2],[1,3],[1,2],[3,-1],[2,-3],[1,-1],[-1,-2]],[[5913,3637],[-1,-13],[-4,-21],[-1,-9],[-4,-34],[-4,-18],[-3,-7],[-7,-12],[-2,-3],[-2,-1],[-3,-2],[-12,-25],[-5,-13],[-4,-17],[-4,-10],[-6,-21],[-5,-16],[-5,-15],[-9,-20],[-4,-6],[-3,-3],[-7,-12],[-9,-19],[-8,-16],[-11,-19],[-7,-9],[-10,-16],[-2,-2],[-11,-16],[-8,-9],[-13,-11],[-5,-3],[-13,3],[-5,-1],[-4,-7],[0,-9],[-2,-2],[-3,1],[-8,4],[-5,-1],[-3,-5],[-2,-6],[-6,-1],[-12,7],[-13,4],[-3,0],[-7,-5],[-2,0],[-10,1],[-5,3],[-5,0],[-4,-3],[-5,-1],[-12,-17],[-7,0],[-6,-2],[-2,0],[-6,2],[-2,0],[-2,-1],[-3,-3],[-7,-1],[-3,-3],[-11,-16],[-3,1],[-2,1],[-6,0],[-7,9],[-2,-1],[0,3],[0,4],[-1,3],[-1,2],[-3,-1],[-1,4],[-4,1],[-2,-1],[-1,-1],[-1,4],[1,3],[-1,4],[0,4],[-2,2],[-1,0],[-3,0],[-2,0],[-1,-2],[-1,-3],[0,-11],[-1,3],[-2,7],[0,6],[0,8],[3,3],[0,5],[-1,5],[-3,11],[-1,6],[-3,3],[-2,9],[-3,3],[-1,6],[-2,5],[-1,8],[2,4],[1,3],[2,-4],[3,2],[3,5],[2,9],[1,13],[-1,9],[-3,21],[-1,6],[-6,15],[-8,21],[-9,33],[-4,20],[-7,40],[-6,23],[-7,21],[-1,1]],[[5815,3905],[0,1],[8,2],[7,-2],[8,-6],[8,-2],[7,1],[5,1],[5,-1],[3,-2],[3,-4]],[[5844,4283],[-4,0],[-7,0],[-8,0],[-6,-3],[-6,-5],[-7,-7],[-2,-3],[-1,-2],[-1,-3],[-1,-6],[0,-9],[-1,-7],[-2,-6],[-10,-8],[-6,-6],[-7,-7],[-5,-10],[-3,-11],[-5,-15],[-6,-12],[-6,-14],[-7,-4],[-5,1],[-7,5],[-5,1],[-4,-3],[-4,1],[-4,5],[-2,2],[-3,-1],[-3,0],[-5,3]]],"transform":{"scale":[0.036003600360036005,0.01736158967459246],"translate":[-180,-89.99892578124998]}} \ No newline at end of file diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json new file mode 100644 index 00000000..db17014e --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_addHost_02.json @@ -0,0 +1,21 @@ +{ + "event": "addHost", + "payload": { + "id": "0E:2A:69:30:13:97/-1", + "ingress": "0E:2A:69:30:13:97/-1/0-of:0000000000000002/3", + "egress": "of:0000000000000002/3-0E:2A:69:30:13:97/-1/0", + "cp": { + "device": "of:0000000000000002", + "port": 3 + }, + "labels": [ + "192.168.0.2", + "0E:2A:69:30:13:97" + ], + "metaUi": { + "x": 340, + "y": 100 + }, + "props": {} + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json deleted file mode 100644 index 4f35403f..00000000 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "event": "showHighlights", - "payload": { - "devices": [ - { - "id": "of:0000000000000001", - "badge": { - "status": "i", - "gid": "xMark", - "msg": "x marks the spot" - } - }, - { - "id": "of:0000000000000002", - "badge": { - "status": "w", - "gid": "crown", - "msg": "it's good to be the King" - } - }, - { - "id": "of:0000000000000003", - "badge": { - "status": "e", - "gid": "chain", - "msg": "the weakest link" - } - }, - { - "id": "of:0000000000000004", - "badge": { - "status": "i", - "txt": "1", - "msg": "singular sensation" - } - }, - { - "id": "of:0000000000000005", - "badge": { - "status": "w", - "txt": "42", - "msg": "life, the universe, and everything!" - } - }, - { - "id": "of:0000000000000006", - "badge": { - "status": "e", - "txt": "99", - "msg": "cadbury's flake" - } - } - ], - "hosts": [], - "links": [ - { - "css": "primary", - "id": "of:0000000000000001/5-of:0000000000000002/7", - "label": "Foo!" - } - ] - } -} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json new file mode 100644 index 00000000..5038df10 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_addHost_03.json @@ -0,0 +1,21 @@ +{ + "event": "addHost", + "payload": { + "id": "0E:2A:69:30:13:a8/-1", + "ingress": "0E:2A:69:30:13:a8/-1/0-of:0000000000000002/4", + "egress": "of:0000000000000002/4-0E:2A:69:30:13:a8/-1/0", + "cp": { + "device": "of:0000000000000002", + "port": 4 + }, + "labels": [ + "192.168.0.3", + "0E:2A:69:30:13:a8" + ], + "metaUi": { + "x": 480, + "y": 90 + }, + "props": {} + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json deleted file mode 100644 index 615efd25..00000000 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "event": "showHighlights", - "payload": { - "devices": [], - "hosts": [], - "links": [] - } -} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json new file mode 100644 index 00000000..615efd25 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_12_showHighlights_clear.json @@ -0,0 +1,8 @@ +{ + "event": "showHighlights", + "payload": { + "devices": [], + "hosts": [], + "links": [] + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json new file mode 100644 index 00000000..4f35403f --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_13_showHighlights_devices.json @@ -0,0 +1,63 @@ +{ + "event": "showHighlights", + "payload": { + "devices": [ + { + "id": "of:0000000000000001", + "badge": { + "status": "i", + "gid": "xMark", + "msg": "x marks the spot" + } + }, + { + "id": "of:0000000000000002", + "badge": { + "status": "w", + "gid": "crown", + "msg": "it's good to be the King" + } + }, + { + "id": "of:0000000000000003", + "badge": { + "status": "e", + "gid": "chain", + "msg": "the weakest link" + } + }, + { + "id": "of:0000000000000004", + "badge": { + "status": "i", + "txt": "1", + "msg": "singular sensation" + } + }, + { + "id": "of:0000000000000005", + "badge": { + "status": "w", + "txt": "42", + "msg": "life, the universe, and everything!" + } + }, + { + "id": "of:0000000000000006", + "badge": { + "status": "e", + "txt": "99", + "msg": "cadbury's flake" + } + } + ], + "hosts": [], + "links": [ + { + "css": "primary", + "id": "of:0000000000000001/5-of:0000000000000002/7", + "label": "Foo!" + } + ] + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json new file mode 100644 index 00000000..a935496f --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_14_showHighlights_hosts.json @@ -0,0 +1,32 @@ +{ + "event": "showHighlights", + "payload": { + "devices": [], + "hosts": [ + { + "id": "0E:2A:69:30:13:86/-1", + "badge": { + "status": "e", + "txt": "99", + "msg": "cadbury's flake" + } + }, + { + "id": "0E:2A:69:30:13:97/-1", + "badge": { + "status": "i", + "gid": "xMark", + "msg": "x marks the spot" + } + }, + { + "id": "0E:2A:69:30:13:a8/-1", + "badge": { + "status": "w", + "gid": "crown" + } + } + ], + "links": [] + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json new file mode 100644 index 00000000..615efd25 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_15_showHighlights_clear.json @@ -0,0 +1,8 @@ +{ + "event": "showHighlights", + "payload": { + "devices": [], + "hosts": [], + "links": [] + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json new file mode 100644 index 00000000..96046061 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_addHost_01.json @@ -0,0 +1,21 @@ +{ + "event": "addHost", + "payload": { + "id": "0E:2A:69:30:13:86/-1", + "ingress": "0E:2A:69:30:13:86/-1/0-of:0000000000000001/2", + "egress": "of:0000000000000001/2-0E:2A:69:30:13:86/-1/0", + "cp": { + "device": "of:0000000000000001", + "port": 2 + }, + "labels": [ + "192.168.0.1", + "0E:2A:69:30:13:86" + ], + "metaUi": { + "x": 210, + "y": 100 + }, + "props": {} + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json deleted file mode 100644 index 615efd25..00000000 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "event": "showHighlights", - "payload": { - "devices": [], - "hosts": [], - "links": [] - } -} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json index ae093d69..c5bad4f8 100644 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json @@ -1,12 +1,12 @@ { "comments": [ - "Demo of adding badges to devices" + "Demo of adding badges to devices and hosts" ], "title": "Demo adding badges", "params": { - "lastAuto": 9 + "lastAuto": 12 }, "description": [ - "Demonstrate the device badging feature." + "Demonstrate the device/host badging feature." ] } -- cgit 1.2.3-korg