Create Automatic Group based on odd numbered IP addresses (or even)

How would I go about creating a relevance to create a group based on whether or not the IP address of the device is even or odd? I seemed to get most of it, but I’m having a hard time actually using the IP address in the relevance clause.

I’ve gotten this far:

Q: ((((tuple string item 3 of it) of concatenation ", " of substrings separated                                                                                                                   
by "." of "10.102.34.75") as integer) MOD 2) = 0                                                                                                                                                  
A: False                                                                                                                                                                                          
T: 1610   

But, I can’t seem to use the actual IP of a client.
I’m getting this error:

Q: ((((tuple string item 3 of it) of concatenation ", " of substrings separated                                                                                                                   
by "." of (addresses of ip interfaces of network) as string) as integer) MOD 2)                                                                                                                   
= 0                                                                                                                                                                                               
E: The operator "substrings separated by" is not defined.  

Any suggestions?

In the case that a device has multiple IP addresses, what logic do you want to use?

Something like the following might be a place to start, but currently returns multiple boolean values if there are multiple IPs:

(it mod 2 = 0) of ((following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)) as integer)

You could do something like the following to have it return a singular True/False based on logically ANDing the boolean values returned from the above:

conjunction of (it mod 2 = 0) of ((following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)) as integer)

This will essentially return True so long as all IPs are even (if any are odd, it will return False).

1 Like

Thanks @Aram. All of the devices that I am creating this for only have 1 IP address, so luckily I don’t have to worry about multiple IP’s. It looks like the second solution is working. I do have a questions though: Would you be able to break it down for me and explain why it works, and what it it’s doing? I’m learning the relevance language, but find it to be very confusing sometimes.

Sure thing! I should have done that above :slight_smile:

My approach was the following. I first started with the out of the box relevance that we use for the ‘IP Address’ property (that you can see from Tools → Manage Properties):

if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing

I see that this returns a string (as specified in the relevance, but is also evident in the Fixlet Debugger by ensuring ‘View → Show Type Information’ is enabled). We don’t need the entire IP address to determine even or odd, so, we can parse the string to return the last ‘octet’ (we could have just as easily returned only the last character too). To do this, we can wrap the relevance logic for IP Address in parens, and have it parse the return:

following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)

Note that I pluralized ‘texts’ and ‘lasts’ above since there can be multiple IP Addresses returned, and so, we’d want to parse each one.

Next, we’ll want to perform the mod calculation, however, to do so, we’ll first have to convert the string to an integer. We can do this by casting the entire logic as integer:

(following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)) as integer

We can then perform our mod calculation. Here is where it gets a bit interesting. To calculate mod for a singular result/answer, we would just do something like the following:

Q: 100 mod 2
A: 0
T: 0.020 ms
I: singular integer

However, we’ve already noted that there can be multiple IP Addresses, and so, we’ll have to take a slightly different approach. If we leverage the above form, we’ll get a singular expression is required error (the following link is useful to better understand common relevance errors and how to fix them: Common Relevance Error Messages). If we reference the 4 major forms of relevance, in this case, we’ll need to be able to iterate over the list to perform the mod calculation. We can do that with the fourth form: (it) of <property> of <object>. So, the following will iterate on the results:

(it) of ((following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)) as integer)

And we can now add the calculation logic:

(it mod 2 = 0) of ((following texts of lasts "." of (if ( exists true whose (if true then ( exists ip interfaces of network) else false) ) then addresses whose (it as string != "0.0.0.0") of ip interfaces whose (not loopback of it) of network as string else nothing)) as integer)

Hope that helps show how you might go about building something like this. There are various approaches, but I tend to build in steps. I’m sure others may have additional thoughts to share here too on their approaches.

3 Likes