Subject: [Idr] BGP Flowspec rules precedence order (RFC 5575)

From: PVLR Pavana Murthy <[email-masked]>
Date: Mon, 12 Feb 2018 16:33:29 +0530

Hello,
  In the RFC 5575, the following is given for the comparing the Flowspec
components of types other then prefix.

} else {
common =
MIN(component_length(comp1), component_length(comp2));
cmp = memcmp(data(comp1), data(comp2), common);
// not equal, lowest value has precedence
// equal, longest string has precedence
}

Here, what does *data* refrer to  ?

Is it the binary form of 1) [op, value]> / [op, bitmask]  or 2) Just
[value] / [bitmask]

eg:

1)  01 *18 58 58 58* 04 *01 46 81 50  ----> Dst.Prefix: 88.88.88.0/24
<http://88.88.88.0/24>  Port: 70 | 80*

2)  01* 18 58 58 58 *04* 03 5a c5 6e    ---->   Dst.Prefix: 88.88.88.0/24
<http://88.88.88.0/24>  Port: >=90 & <= 110*

*In the above FS rules,  Dst. Prefix is same in both, so we need to compare
the data of next type 4 (Port). *
*So do we need to do memcmp of  (01 46 81 50) and  (03 5a c5 6e) ?*

Thanks,
Pavana*.*

---

From: Christoph Loibl <[email-masked]>
Date: Wed, 14 Feb 2018 22:41:00 +0100

Hi Pavana,

Did you have a look into the actual code (thanks to Job’s comment) that is contained in the RFC5575bis draft which should be identical from the behaviour:

https://tools.ietf.org/html/draft-ietf-idr-rfc5575bis-06 <https://tools.ietf.org/html/draft-ietf-idr-rfc5575bis-06>

Christoph

--
Christoph Loibl
[email-masked] | CL8-RIPE | PGP-Key-ID: 0x4B2C0055 | http://www.nextlayer.at

> On 12.02.2018, at 12:03, PVLR Pavana Murthy <[email-masked]> wrote:
> 
> Hello,
>   In the RFC 5575, the following is given for the comparing the Flowspec components of types other then prefix.
> 
> } else {
> common =
> Here, what does data refrer to  ?
> 
> Is it the binary form of 1) [op, value]> / [op, bitmask]  or 2) Just [value] / [bitmask]
> 
> eg:
> 
> 
> 1)  01 18 58 58 58 04 01 46 81 50  ----> Dst.Prefix: 88.88.88.0/24 <http://88.88.88.0/24>  Port: 70 | 80
> 
> 2)  01 18 58 58 58 04 03 5a c5 6e    ---->   Dst.Prefix: 88.88.88.0/24 <http://88.88.88.0/24>  Port: >=90 & <= 110
> 
> In the above FS rules,  Dst. Prefix is same in both, so we need to compare the data of next type 4 (Port).
> So do we need to do memcmp of  (01 46 81 50) and  (03 5a c5 6e) ?
> 
> Thanks,
> Pavana.
> 
> 
> 
> _______________________________________________
> Idr mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/idr

---

From: PVLR Pavana Murthy <[email-masked]>
Date: Thu, 15 Feb 2018 09:38:14 +0530

Hi Christoph,
  Even in the  RFC5575bis,  the following is given  for comparing
non-prefix type components.

 else:
               # assuming comp_a.value, comp_b.value of type bytearray
               if len(comp_a.value) == len(comp_b.value):
                   if comp_a.value > comp_b.value:
                       return B_HAS_PRECEDENCE
                   if comp_a.value < comp_b.value:
                       return A_HAS_PRECEDENCE
                   # components equal -> continue with next component
               else:
                   common = min(len(comp_a.value), len(comp_b.value))
                   if comp_a.value[:common] > comp_b.value[:common]:
                       return B_HAS_PRECEDENCE
                   elif comp_a.value[:common] < comp_b.value[:common]:
                       return A_HAS_PRECEDENCE
                   # the first common bytes match
                   elif len(comp_a.value) > len(comp_b.value):
                       return A_HAS_PRECEDENCE
                   else:
                       return B_HAS_PRECEDENCE

*What is  comp_a.value here ? Is it the binary sting of [op,
value]/[op,bitmask] or only value/bitmask ?*

Thanks,

Pavana.

On Thu, Feb 15, 2018 at 3:11 AM, Christoph Loibl <[email-masked]> wrote:

> Hi Pavana,
>
> Did you have a look into the actual code (thanks to Job’s comment) that is
> contained in the RFC5575bis draft which should be identical from the
> behaviour:
>
> https://tools.ietf.org/html/draft-ietf-idr-rfc5575bis-06
>
> Christoph
>
> --
> Christoph Loibl
> *In the above FS rules,  Dst. Prefix is same in both, so we need to
> compare the data of next type 4 (Port). *

---

From: Christoph Loibl <[email-masked]>
Date: Thu, 15 Feb 2018 08:37:51 +0100

Hi Pavana,

You can rather easily test the behaviour when you feed your case into the python function:

def main():
    fs1 = FS_nlri(components=[
        FS_component(component_type=IP_DESTINATION, value=ipaddress.ip_network('88.88.88.0/24')),
        FS_component(component_type=4, value=bytearray([0x01, 0x46, 0x81, 0x50]))
    ])

    fs2 = FS_nlri(components=[
        FS_component(component_type=IP_DESTINATION, value=ipaddress.ip_network('88.88.88.0/24')),
        FS_component(component_type=4, value=bytearray([0x03, 0x5a, 0xc5, 0x6e]))
    ])
    print(flow_rule_cmp(fs1, fs2))

What happens is (I refer to line numbers of the code in the github repo
https://github.com/stoffi92/flowspec-cmp/blob/master/flow_cmp.py <https://github.com/stoffi92/flowspec-cmp/blob/master/flow_cmp.py> :

*) The IP components are compared and as you mentioned: no decision can be made since the ip components are equal. (we reach line 74 for the equal ip components and continue with the next iteration)

*) The second component _types_ are equal but not IP (we end up in the branch in line 80 since the components are type=4 and not 1 or 2)

*) The length of the second components is compared and equal, so we continue in line 82

** See below: this is basically where the compare that you asked for happens **

*) Now we come to the point where we compare the string of bytes one by one. As long as they are equal. (this is basically what memcmp does - this is not very explicit in the python code, since it is done by the <, > operators for the bytearray implicitly)

In your case what it does is, that it compares 0x01 to 0x03 and figures out that 0x01 is the lower value so it takes the branch in line 84 and returns with A_HAS_PRECEDENCE from line 85 (if both of your components would start with 0x01 it would continue to the second byte and so on).

Your first FS nlri has precedence because of the “lower” value.

>> 01 18 58 58 58 04 01 46 81 50  ----> Dst.Prefix: 88.88.88.0/24 <http://88.88.88.0/24>  Port: 70 | 80

Discamer: I assumed that you encoded the components themselfs correctly (the 01 46 81 50 and 03 5a c5 6e)

Does this answer your question?

Christoph

> On 15.02.2018, at 05:08, PVLR Pavana Murthy <[email-masked]> wrote:
> 
> Hi Christoph,
>   Even in the  RFC5575bis,  the following is given  for comparing non-prefix type components.
> 
>  else:
> What is  comp_a.value here ? Is it the binary sting of [op, value]/[op,bitmask] or only value/bitmask ?
> 
> Thanks,
> Pavana.
> 
> On Thu, Feb 15, 2018 at 3:11 AM, Christoph Loibl <[email-masked] <mailto:[email-masked]>> wrote:
> Hi Pavana,
> 
> [email-masked] <mailto:[email-masked]> | CL8-RIPE | PGP-Key-ID: 0x4B2C0055 | http://www.nextlayer.at <http://www.nextlayer.at/>
> 
> 
> 
>> On 12.02.2018, at 12:03, PVLR Pavana Murthy <[email-masked] <mailto:[email-masked]>> wrote:
>> 
>> Hello,
>> [email-masked] <mailto:[email-masked]>
>> https://www.ietf.org/mailman/listinfo/idr <https://www.ietf.org/mailman/listinfo/idr>
> 
>

---

From: PVLR Pavana Murthy <[email-masked]>
Date: Thu, 15 Feb 2018 14:35:49 +0530

Hi Christoph,
   Thanks a lot for the detailed explanation. That answers my question
completely :-).

On Thu, Feb 15, 2018 at 1:07 PM, Christoph Loibl <[email-masked]> wrote:

>         FS_component(component_type=IP_DESTINATION,
> value=ipaddress.ip_network('88.88.88.0/24')),
>         FS_component(component_type=IP_DESTINATION,
> value=ipaddress.ip_network('88.88.88.0/24')),
> https://github.com/stoffi92/flowspec-cmp/blob/master/flow_cmp.py :
>
> *) The IP components are compared and as you mentioned: no decision can be
> made since the ip components are equal. (we reach line 74 for the equal ip
> components and continue with the next iteration)
>
> *) The second component _types_ are equal but not IP (we end up in the
> branch in line 80 since the components are type=4 and not 1 or 2)
>
> *) Now we come to the point where we compare the string of bytes one by
> one. As long as they are equal. (this is basically what memcmp does - this
> is not very explicit in the python code, since it is done by the <, >
> operators for the bytearray implicitly)
>
> In your case what it does is, that it compares 0x01 to 0x03 and figures
> out that 0x01 is the lower value so it takes the branch in line 84 and
> returns with A_HAS_PRECEDENCE from line 85 (if both of your components
> would start with 0x01 it would continue to the second byte and so on).
>
> 01 *18 58 58 58* 04 *01 46 81 50  ----> Dst.Prefix: 88.88.88.0/24
> *What is  comp_a.value here ? Is it the binary sting of [op, value]/[op,bitmask] or only value/bitmask ?*
>
>
> Thanks,
>
> Pavana.
>
>
>> Did you have a look into the actual code (thanks to Job’s comment) that
>> is contained in the RFC5575bis draft which should be identical from the
>> behaviour:
>>
>> 2)  01* 18 58 58 58 *04* 03 5a c5 6e    ---->   Dst.Prefix:
>> 88.88.88.0/24 <http://88.88.88.0/24>  Port: >=90 & <= 110*
>>