DMR IDs
DMR ID's
I've been getting more into amateur DMR and of course you need an ID. Radioid.net is the DB for this of course, but the scheme in use was developed by DMR-MARC. They came up with some convoluted scheme back in the day using Mobile Country Codes as a prefix to segregate the ID's so uses could load only the countries they wish in their contact lists. There is no hierarchical authority (ala DNS) where Radioid.net passes off lookups to country (or lower) levels, and the entire DB stands at under 1mb as text, so this segregation is simply for the users.
Contents
DMR ID
First some words on the DMR ID from the specs. It's simple, a 24 bit number, however certain types of DMR systems only use the first 16 bits (Cap Plus trunking for one). Hams tend to use the entire 24 bit ID, and it's typically represented at decimal.
24 bits = 16,777,215 possible ID's
16 bits = 65,536 possible ID's for cap plus
DMR-MARC scheme
DMR MARC's scheme uses the Mobile Country Code ("MCC") as the first part of the ID in decimal, then one digit for sub-country (State), and 3 decimal digits for the user.
First doing this as decimal means we cannot use any ID over 9,999,999 as MNC cannot begin with a 1, thus we're limited to the 7 decimal digits. This removes 6,777,216 ID's from the scope of use.
Another issue is using a 3 digits for the MCC. There are only 226 MCC's leaving 774 blocks of 10000 ID's unused or 7,740,000 total ID's unable to be used. (actually a bit less than this due to the next issue)
Sub Country level (state/province)
In the MMMSUUU decimal format there is only a possible number of 10 sub country levels. This is an issue for many countries which have more than 10 sub-regions. What is done here is to invent new country codes, and DMR has invented 8 unique codes:
263 - Germany 264 - Germany 313 - USA 314 - USA 315 - USA 317 - USA 535 - USA (Guam) 658 - Ascension Island
In total there are only 170 of the 226 MCCs in use by DMR, even adding in the invalid codes, there's 178. This leaves 822 blocks unused, or 8,220,000 IDs.
Totals
In this DMR-MARC scheme presented there is much waste and having to invent new country codes, thus "shoehorning" the DMR ID into something it was not designed for. Adding up the loss below:
16,777,215 possible IDs in DMR 6,777,216 - IDs over 10,000,000 8,220,000 - Unused MCC IDs 65,535 - CAP Plus ID range ------------- 1,714,464 - Total DMR ID's available for use
This scheme throws out 90% of the available ID space as unusable! There was a total lack of thought put into this in terms of scalability.
Capacity Plus IDs
LCP or Link Capacity Plus is a controller-less trunking system for >16 sites put forth by Motorola and is quite popular. One of the requirements for this is the DMR ID of the subscribers must be 2^16, not 2^24 or > 65,536. In all Motorola radios, the unit ID is set once, it cannot be changed per system. This means if you're an amateur and want to run a common radio on your LCP work system and the ham bands, you need a Capacity Plus ID.
When it was administered by DMR-MARC a person had to have a valid reason (LCP use) for a low ID, but was still assigned as using MCC as the first 3 digits, thus restricting the availability further. Knowing hams if there was not a restriction they all would want a "Low ID" and go for this, so it's a valid concern to ensure the availability of this for people who need it.
Now the problem is at some point the Brandmeister DMR network stopped importing the low ID's from radioid.net and has capped the allowed ID's. If you have a CPLUS ID in the Brandmeister network, you're allowed to use it, but they will refuse all new ID's. This presents a problem for new users, as Brandmeister will drop any traffic that doesn't have a "valid" ID, but they refuse to import/update their DB. As Brandmeister provides some of the most popular talkgroups, this can lead to further fracturing of the DMR network, and one-way audio where traffic goes via Brandmeister.
I'd suggest Brandmeister start allowing these CPLUS ID's to be passed and allowed on their network. There's not many in use, under 300 total are registered with radioid.net.
Ideas to fix this mess
I'd propose the following features of any number scheme
- Must be scalable
- group ID's on national/state boundaries to facilitate importing into radios
- support sub-delegation of authority
Proposal
Since we're dealing with a 24 bit (3 byte/octet) binary number, we should dispose with the idea of thinking in decimal. If we think how IANA and the RIR's allocate IP space, we can do the same with DMR ID's.
Looking at the number of DMR IDs in the USA:
awk -F\; '$1 !~ /^1/ && length($1) == 7 && $1 ~ /^31[0-5]/ { print }' dmrid.dat |wc 58574 58574 900443
58574 total ID's for 779626 [1] license amateurs in the US is about 7.5% of all licenses. This is the highest number of DMR ID's of any country.
The UK has the highest number of IDs by percentage, but is still well under the USA in terms of number of ID's in use.
US 7.5% of licenses 58,574 Total IDs UK 17.5% of licenses 13,305 Total IDs Canada 7.1% of licenses 5,000 Total IDs Germany 14.0% of licenses 8,883 Total IDs
The counts for amateur radio operators per controy were taken from Wikipedia [2]
Per this data, if we look at the top 10 countries there are 1,827,613 total hams (and after this the counts drop off where the rest of countries total are under 200k). If we assume 10% of all hams will have a DMR ID, this is ~183,000 DMR ID's or 18k per country of the top 10. Other than the USA, this is indeed the case.
What I'd propose is using a Bit/Mask for allocating blocks of ID's per country, and each country gets a segment that could be further subdivided.
The world is divided into 4 regions:
- Americas (North America, South America, Central America, Caribbean)
- Asia Pacific (Central & South Asia, Northeastern Asia, Southeastern Asia, Australia and Oceania)
- Europe (Northern Europe, Southern Europe, Eastern Europe, Western Europe)
- Middle East/Africa (Middle East, Northern Africa, Southern Africa)
We allocate each region on the first 4 bits (nibble) of the DMR ID:
00.00.00 - Americas 10.00.00 - OPEN 20.00.00 - OPEN 30.00.00 - OPEN 40.00.00 - Asia Pacific 50.00.00 - OPEN 60.00.00 - OPEN 70.00.00 - OPEN 80.00.00 - Europe 90.00.00 - OPEN A0.00.00 - OPEN B0.00.00 - OPEN C0.00.00 - Middle East/Africa D0.00.00 - OPEN E0.00.00 - OPEN F0.00.00 - OPEN
This would provide 2^20 addresses per region (1 million) with the ability to expand up to 2 million by moving to a /3 or /2 for 2 or 4 million IDs respectively. Should we get over 4 million in use in a region we can move to allocating an unused block earmarked for another region.
Each region would then allocate as needed to each country.
Americas 0/4 - 000000 - 0FFFFF - allocate on the /8 boundary, but give /10's or 16k blocks to each country:
00.00.00 - Reserved (00.00.00-00.FF.FF is CPLUS ID range) 01.00.00 - OPEN 02.00.00 - Canada 03.00.00 - OPEN 04.00.00 - Latin America 05.00.00 - OPEN 06.00.00 - OPEN 07.00.00 - OPEN 08.00.00 - USA North East 09.00.00 - USA South East 0A.00.00 - USA West 0B.00.00 - USA Big States 0C.00.00 - OPEN 0D.00.00 - OPEN 0E.00.00 - OPEN 0F.00.00 - OPEN
Now USA's 08.00.00/6 we allocate on the /10 boundary (16,383), but give /12 to each state (4095) Other than the popular states. This can be adjusted easily if needed, and many of the western states could use a smaller pool.
08.00.00/10 - - 08.00.00/12 - Maine - 08.10.00/12 - Vermont - 08.20.00/12 - New Hampshire - 08.30.00/12 - Rhode Island 08.40.00/10 - 08.40.00/12 - Connecticut - 08.50.00/12 - Pennsylvania - 08.60.00/12 - Maryland - 08.70.00/12 - DC 08.80.00/10 - 08.80.00/12 - North Virginia - 08.90.00/12 - Virginia - 08.A0.00/12 - West VA - 08.B0.00/12 - Massachusetts 08.C0.00/10 - - 08.80.00/11 - NYC Metro - - NYC Metro - 08.A0.00/12 - NY - 08.B0.00/12 - NJ 09.00.00/10 - NC, SC, GA, TN 09.40.00/10 - OH, KY, IN, AL 09.80.00/10 - MS, LA, AR, MO 09.C0.00/10 - UNUSED 0A.00.00/10 - UNUSED 0A.40.00/10 - WA, OR, ID, NV, UT 0A.80.00/10 - MO, WY, ND, SD, OK, NE, KS (smaller than a /12) 0A.C0.00/10 - AZ, NM, TX 0B.00.00/10 - FL 0B.40.00/10 - UNUSED 0B.80.00/10 - CA 0B.C0.00/10 - UNUSED
Advantages to Proposal
If a user wants to program their HT with contacts for a given state, they can simply download the range/mask they want. If they want all Florida they select 0B.00.00/10 which is range 0x0B0000-0B3FFF or decimal 720,896 - 737,279.
Should Florida need to expand they can simply increase their mask size to /9 and combine 0B.00.00/10 and 0B.40.00/10 into 0B.00.00/9.
Regions could manage their own databases. It's quite easy to define a range of 81.00.00/8 to France and let them manage their own ID assignments. They could be carved out and any lookup would know if you see something in 81.00.00-81.FF.FF go it's managed by the regional authority.
Country wide expansion is easy as well, should there not be an adjacent block, we can allocate another block which is not contiguous. IANA does this all the time and it works well. At the projected growth rate of amateur radio DMR this would allow some 50 years of growth if planned well.
Conversion and compatibility. Obviously converting to this method would take some time. Due to the way allocations work in the prior MCC scheme, there would be the ability to move users into anything above 50.00.00/4 immediately, as there are no MCC's above that in use today.
backup data
awk to process dmrid file
#match DMR ID's not starting with 1 and 7 digits long. awk -F\; '$1 !~ /^1/ && length($1) == 7 { print }' dmrid.dat |wc 184388 184388 2870086 # process the db, and sort into unique country codes. awk -F\; '$1 !~ /^1/ && length($1) == 7 { print substr($1,1,3) }' dmrid.dat | sort | uniq |wc 178 178 712
#Compare the unique MCC from the DMR db and the real MCC file awk -F";" 'NR==FNR{a[$1]=$1;next} {if (a[$1]) ;else print "Invalid MCC", $1;} ' MCC-Valid.txt dmr-mcc-in-use.txt Invalid MCC 263 Invalid MCC 264 Invalid MCC 313 Invalid MCC 314 Invalid MCC 315 Invalid MCC 317 Invalid MCC 535 Invalid MCC 658 |wc 8 24 128
Python 3 Program
I've written this program to help calculate the DMR ID ranges based on masks. It will take the input as 6 decimal point seperated bytes, and output the ranges in hex and decimal.
$ ./dmr-calc.py 10.00.00/12 DMR ID: 0x100000 Dec: 01048576 Mask : 0xFFF000 Alt: /12 First : 0x100000 Dec: 01048576 Last : 0x100FFF Dec: 01052671 Size : 0x000FFF Dec: 00004095
dmr-calc.py
#!/usr/bin/env python3.8 # Use: ./dmr-calc.py <hh.hh.hh/mask> # copyright 2021 Bryan Fields bryan@bryanfields.net # Licensed under the AGPL 3.0 # Vursion 0.90 # this is a PoC for assigning 24 bit DMR ID's in accordance with the # method proposed in https://wiki.w9cr.net/index.php/DMR_IDs import sys if __name__=="__main__": id = 0 mask = 0 slash = 0 if len(sys.argv) == 2: (id, slash) = sys.argv[1].split('/') #split it up if it exists id = [int(x, 16) for x in id.split(".")] #confert it to int id = int((int(id[0]<<16)) + (int(id[1]<<8)) + (int(id[2]))) slash = int(slash) mask = (((1<<24)-1) << (24-slash)) & (int(0xFFFFFF)) else: print("Use: {0} <DMR ID in hh.hh.hh/mask bits>".format(sys.argv[0])) sys.exit(-1) baseid = (id & mask) lastid = (id & mask) | (0xffffff^mask) nworksize = (lastid - baseid) dmrid = ( str( "%06.0X" % id)) #print ("dmr ID == %s.%s.%s Decima: %08i" % (dmrid[0:2], dmrid[2:4], dmrid[4:6], id)) print("DMR ID: 0x%06.0X Dec: %08i" % (id, id)) print("Mask : 0x%06.0X Alt: /%s" % (mask, slash)) print("First : 0x%06.0X Dec: %08i" % (baseid, baseid)) print("Last : 0x%06.0X Dec: %08i" % (lastid, lastid)) print("Size : 0x%06.0X Dec: %08i" % (nworksize, nworksize)) sys.exit()
Other things
1 DMR ID's These DMR ID's start with 1
6 digit DMR ID's that are not valid on radioid.net These don't lookup in the database as they are not starting with 1 and are 6 digits, not 7.
References
- ↑ ARRL List of number of Hams in USA for 2021
- ↑ number of counts of hams in 2019 per country