)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"de18b173_2b79b35e","updated":"2026-04-07 13:23:15.000000000","message":"Thank you for the review, Brian!","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c27558eaecfaebc2b1fefd977cceb2ed6290f3b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"720ac2b1_82a2e957","updated":"2026-04-08 09:45:31.000000000","message":"recheck: The pep8 error looks like a result of the AI scraper DoS, not an error from this patch.","commit_id":"16c421ba99f77a5fd7ab6712b7ac7a734004dc92"}],"api-ref/source/v2/ports.inc":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":37,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"The Allowed address pairs reject multicast extension"},{"line_number":40,"context_line":"(``aap-reject-multicast``) makes it discoverable when the API started to"},{"line_number":41,"context_line":"reject allowed address pairs containing multicast addresses.  Multicast"},{"line_number":42,"context_line":"allowed address pairs were so far never properly supported, but without"},{"line_number":43,"context_line":"this extension the API silently accepted them."}],"source_content_type":"text/x-c++src","patch_set":1,"id":"ee1a0846_46cdf312","line":40,"range":{"start_line":40,"start_character":27,"end_line":40,"end_character":72},"updated":"2026-04-02 16:36:33.000000000","message":"s/changes the API to (?)","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":37,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"The Allowed address pairs reject multicast extension"},{"line_number":40,"context_line":"(``aap-reject-multicast``) makes it discoverable when the API started to"},{"line_number":41,"context_line":"reject allowed address pairs containing multicast addresses.  Multicast"},{"line_number":42,"context_line":"allowed address pairs were so far never properly supported, but without"},{"line_number":43,"context_line":"this extension the API silently accepted them."}],"source_content_type":"text/x-c++src","patch_set":1,"id":"378c87e7_e8d92e55","line":40,"range":{"start_line":40,"start_character":27,"end_line":40,"end_character":72},"in_reply_to":"ee1a0846_46cdf312","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":39,"context_line":"The Allowed address pairs reject multicast extension"},{"line_number":40,"context_line":"(``aap-reject-multicast``) makes it discoverable when the API started to"},{"line_number":41,"context_line":"reject allowed address pairs containing multicast addresses.  Multicast"},{"line_number":42,"context_line":"allowed address pairs were so far never properly supported, but without"},{"line_number":43,"context_line":"this extension the API silently accepted them."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"The rejected addresses are:"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"092d162e_46700636","line":42,"range":{"start_line":42,"start_character":27,"end_line":42,"end_character":33},"updated":"2026-04-02 16:36:33.000000000","message":"nit: can remove \"so far\" here","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":39,"context_line":"The Allowed address pairs reject multicast extension"},{"line_number":40,"context_line":"(``aap-reject-multicast``) makes it discoverable when the API started to"},{"line_number":41,"context_line":"reject allowed address pairs containing multicast addresses.  Multicast"},{"line_number":42,"context_line":"allowed address pairs were so far never properly supported, but without"},{"line_number":43,"context_line":"this extension the API silently accepted them."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"The rejected addresses are:"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"d2f49b5b_5f33fe9b","line":42,"range":{"start_line":42,"start_character":27,"end_line":42,"end_character":33},"in_reply_to":"092d162e_46700636","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"}],"neutron_lib/api/validators/__init__.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1291,"context_line":"    validate_ip_address()."},{"line_number":1292,"context_line":"    \"\"\""},{"line_number":1293,"context_line":"    ip \u003d netaddr.IPAddress(data)"},{"line_number":1294,"context_line":"    if not ip.is_multicast():"},{"line_number":1295,"context_line":"        return"},{"line_number":1296,"context_line":"    else:"},{"line_number":1297,"context_line":"        msg_data \u003d {\u0027ip\u0027: data}"}],"source_content_type":"text/x-python","patch_set":1,"id":"5ff6a4ea_0e5088e7","line":1294,"range":{"start_line":1294,"start_character":7,"end_line":1294,"end_character":10},"updated":"2026-04-02 16:36:33.000000000","message":"Should maybe be a positive check and return the message in that case, then don\u0027t need the else","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1291,"context_line":"    validate_ip_address()."},{"line_number":1292,"context_line":"    \"\"\""},{"line_number":1293,"context_line":"    ip \u003d netaddr.IPAddress(data)"},{"line_number":1294,"context_line":"    if not ip.is_multicast():"},{"line_number":1295,"context_line":"        return"},{"line_number":1296,"context_line":"    else:"},{"line_number":1297,"context_line":"        msg_data \u003d {\u0027ip\u0027: data}"}],"source_content_type":"text/x-python","patch_set":1,"id":"94cbb42f_e692f783","line":1294,"range":{"start_line":1294,"start_character":7,"end_line":1294,"end_character":10},"in_reply_to":"5ff6a4ea_0e5088e7","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1295,"context_line":"        return"},{"line_number":1296,"context_line":"    else:"},{"line_number":1297,"context_line":"        msg_data \u003d {\u0027ip\u0027: data}"},{"line_number":1298,"context_line":"        msg \u003d \u0027IP %(ip)s is a multicast address, but it must not be.\u0027"},{"line_number":1299,"context_line":"        return _(msg) % msg_data"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"e1d0b39c_38c7694a","line":1298,"range":{"start_line":1298,"start_character":49,"end_line":1298,"end_character":67},"updated":"2026-04-02 16:36:33.000000000","message":"s/which is not supported (?)","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1295,"context_line":"        return"},{"line_number":1296,"context_line":"    else:"},{"line_number":1297,"context_line":"        msg_data \u003d {\u0027ip\u0027: data}"},{"line_number":1298,"context_line":"        msg \u003d \u0027IP %(ip)s is a multicast address, but it must not be.\u0027"},{"line_number":1299,"context_line":"        return _(msg) % msg_data"},{"line_number":1300,"context_line":""},{"line_number":1301,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"36f6d473_c0fa8480","line":1298,"range":{"start_line":1298,"start_character":49,"end_line":1298,"end_character":67},"in_reply_to":"e1d0b39c_38c7694a","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1328,"context_line":"        msg_data \u003d {\u0027net\u0027: net, \u0027mcast_net\u0027: mcast_net}"},{"line_number":1329,"context_line":"        msg \u003d ("},{"line_number":1330,"context_line":"            \u0027Subnet %(net)s overlaps with multicast range %(mcast_net)s,\u0027"},{"line_number":1331,"context_line":"            \u0027 but it must not.\u0027)"},{"line_number":1332,"context_line":"        return _(msg) % msg_data"},{"line_number":1333,"context_line":"    else:"},{"line_number":1334,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":1,"id":"baf8b0cb_056593e5","line":1331,"range":{"start_line":1331,"start_character":14,"end_line":1331,"end_character":29},"updated":"2026-04-02 16:36:33.000000000","message":"s/which is not supported (?)","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1328,"context_line":"        msg_data \u003d {\u0027net\u0027: net, \u0027mcast_net\u0027: mcast_net}"},{"line_number":1329,"context_line":"        msg \u003d ("},{"line_number":1330,"context_line":"            \u0027Subnet %(net)s overlaps with multicast range %(mcast_net)s,\u0027"},{"line_number":1331,"context_line":"            \u0027 but it must not.\u0027)"},{"line_number":1332,"context_line":"        return _(msg) % msg_data"},{"line_number":1333,"context_line":"    else:"},{"line_number":1334,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":1,"id":"c89e0e43_892c1158","line":1331,"range":{"start_line":1331,"start_character":14,"end_line":1331,"end_character":29},"in_reply_to":"baf8b0cb_056593e5","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1330,"context_line":"            \u0027Subnet %(net)s overlaps with multicast range %(mcast_net)s,\u0027"},{"line_number":1331,"context_line":"            \u0027 but it must not.\u0027)"},{"line_number":1332,"context_line":"        return _(msg) % msg_data"},{"line_number":1333,"context_line":"    else:"},{"line_number":1334,"context_line":"        return"},{"line_number":1335,"context_line":""},{"line_number":1336,"context_line":""},{"line_number":1337,"context_line":"def validate_mac_address_not_multicast(data, valid_values\u003dNone):"}],"source_content_type":"text/x-python","patch_set":1,"id":"6cfaa313_1e7e93ac","line":1334,"range":{"start_line":1333,"start_character":4,"end_line":1334,"end_character":14},"updated":"2026-04-02 16:36:33.000000000","message":"Probably don\u0027t need the else or return, unless pep8 is complaining, since returning None is the default","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1330,"context_line":"            \u0027Subnet %(net)s overlaps with multicast range %(mcast_net)s,\u0027"},{"line_number":1331,"context_line":"            \u0027 but it must not.\u0027)"},{"line_number":1332,"context_line":"        return _(msg) % msg_data"},{"line_number":1333,"context_line":"    else:"},{"line_number":1334,"context_line":"        return"},{"line_number":1335,"context_line":""},{"line_number":1336,"context_line":""},{"line_number":1337,"context_line":"def validate_mac_address_not_multicast(data, valid_values\u003dNone):"}],"source_content_type":"text/x-python","patch_set":1,"id":"a3f753e5_4184114f","line":1334,"range":{"start_line":1333,"start_character":4,"end_line":1334,"end_character":14},"in_reply_to":"6cfaa313_1e7e93ac","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1355,"context_line":"        msg_data \u003d {\u0027mac_address\u0027: data}"},{"line_number":1356,"context_line":"        msg \u003d ("},{"line_number":1357,"context_line":"            \u0027MAC address %(mac_address)s is a multicast address, \u0027"},{"line_number":1358,"context_line":"            \u0027but it must not be.\u0027)"},{"line_number":1359,"context_line":"        return _(msg) % msg_data"},{"line_number":1360,"context_line":"    else:"},{"line_number":1361,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":1,"id":"ad8c6612_062fee06","line":1358,"range":{"start_line":1358,"start_character":13,"end_line":1358,"end_character":31},"updated":"2026-04-02 16:36:33.000000000","message":"Same comment as above","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1355,"context_line":"        msg_data \u003d {\u0027mac_address\u0027: data}"},{"line_number":1356,"context_line":"        msg \u003d ("},{"line_number":1357,"context_line":"            \u0027MAC address %(mac_address)s is a multicast address, \u0027"},{"line_number":1358,"context_line":"            \u0027but it must not be.\u0027)"},{"line_number":1359,"context_line":"        return _(msg) % msg_data"},{"line_number":1360,"context_line":"    else:"},{"line_number":1361,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":1,"id":"5015e7a0_c7aec7bb","line":1358,"range":{"start_line":1358,"start_character":13,"end_line":1358,"end_character":31},"in_reply_to":"ad8c6612_062fee06","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":1358,"context_line":"            \u0027but it must not be.\u0027)"},{"line_number":1359,"context_line":"        return _(msg) % msg_data"},{"line_number":1360,"context_line":"    else:"},{"line_number":1361,"context_line":"        return"},{"line_number":1362,"context_line":""},{"line_number":1363,"context_line":""},{"line_number":1364,"context_line":"class UndefinedValidator(Exception):"}],"source_content_type":"text/x-python","patch_set":1,"id":"d7ad674c_ea6a6b64","line":1361,"updated":"2026-04-02 16:36:33.000000000","message":"Same comment as above","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":false,"context_lines":[{"line_number":1358,"context_line":"            \u0027but it must not be.\u0027)"},{"line_number":1359,"context_line":"        return _(msg) % msg_data"},{"line_number":1360,"context_line":"    else:"},{"line_number":1361,"context_line":"        return"},{"line_number":1362,"context_line":""},{"line_number":1363,"context_line":""},{"line_number":1364,"context_line":"class UndefinedValidator(Exception):"}],"source_content_type":"text/x-python","patch_set":1,"id":"33081141_a31e66ad","line":1361,"in_reply_to":"d7ad674c_ea6a6b64","updated":"2026-04-07 13:23:15.000000000","message":"Done","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"}],"neutron_lib/api/validators/allowedaddresspairs.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"040239f0fd49377b8d0261b068935f82377eea75","unresolved":true,"context_lines":[{"line_number":79,"context_line":"            msg \u003d validators.validate_ip_address(ip_address)"},{"line_number":80,"context_line":"        if msg:"},{"line_number":81,"context_line":"            raise exc.HTTPBadRequest(msg)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"        if \u0027/\u0027 in ip_address:"},{"line_number":84,"context_line":"            msg \u003d validators.validate_subnet_not_multicast(ip_address)"},{"line_number":85,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"060868fa_46125f67","line":82,"updated":"2026-04-02 16:36:33.000000000","message":"So we only want to do the below if the extension is loaded, how do we do that?","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"64d6f8ab981a3f818d52c3dbbf5526c6e20ec7f6","unresolved":true,"context_lines":[{"line_number":79,"context_line":"            msg \u003d validators.validate_ip_address(ip_address)"},{"line_number":80,"context_line":"        if msg:"},{"line_number":81,"context_line":"            raise exc.HTTPBadRequest(msg)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"        if \u0027/\u0027 in ip_address:"},{"line_number":84,"context_line":"            msg \u003d validators.validate_subnet_not_multicast(ip_address)"},{"line_number":85,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"5ac5eedd_970a42e7","line":82,"in_reply_to":"060868fa_46125f67","updated":"2026-04-07 13:23:15.000000000","message":"What about the other way around? I mean if we merge the n-lib patch, release it, bump the n-lib requirement in the neutron patch introducing the extension, then we never have a problematic neutron - neutron-lib combination. Or did you mean something else?","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"2ccf1bb7200331d72c8a580fbc4f2669d6379f9a","unresolved":true,"context_lines":[{"line_number":79,"context_line":"            msg \u003d validators.validate_ip_address(ip_address)"},{"line_number":80,"context_line":"        if msg:"},{"line_number":81,"context_line":"            raise exc.HTTPBadRequest(msg)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"        if \u0027/\u0027 in ip_address:"},{"line_number":84,"context_line":"            msg \u003d validators.validate_subnet_not_multicast(ip_address)"},{"line_number":85,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ad4375d8_0a1c8bbb","line":82,"in_reply_to":"5ac5eedd_970a42e7","updated":"2026-04-07 19:59:55.000000000","message":"I think I meant something else.\n\nWithout the extension loaded we shouldn\u0027t check the address or mac any further, right?\n\nWith the extension loaded we should do the checks.\n\nI haven\u0027t found a good example yet explaining this in the code.","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"8c5a27b0abef604450c2db7386a8577f8880ae9d","unresolved":true,"context_lines":[{"line_number":79,"context_line":"            msg \u003d validators.validate_ip_address(ip_address)"},{"line_number":80,"context_line":"        if msg:"},{"line_number":81,"context_line":"            raise exc.HTTPBadRequest(msg)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"        if \u0027/\u0027 in ip_address:"},{"line_number":84,"context_line":"            msg \u003d validators.validate_subnet_not_multicast(ip_address)"},{"line_number":85,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"28f0abbb_58e8ea60","line":82,"in_reply_to":"7d32b825_1d7848a3","updated":"2026-04-09 17:07:40.000000000","message":"Right, I guess this is a case where this doesn\u0027t really need to be modular, just discoverable.","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"b0cf2585213a5a8b9c39ab2f5387af94f785dd06","unresolved":true,"context_lines":[{"line_number":79,"context_line":"            msg \u003d validators.validate_ip_address(ip_address)"},{"line_number":80,"context_line":"        if msg:"},{"line_number":81,"context_line":"            raise exc.HTTPBadRequest(msg)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"        if \u0027/\u0027 in ip_address:"},{"line_number":84,"context_line":"            msg \u003d validators.validate_subnet_not_multicast(ip_address)"},{"line_number":85,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"7d32b825_1d7848a3","line":82,"in_reply_to":"ad4375d8_0a1c8bbb","updated":"2026-04-08 09:44:34.000000000","message":"Oh, I get it. When a service plugin implements an extension, then we always have a way to enable/disable the extension via loading the service plugin from the config (or not).\n\nHowever I think we don\u0027t need all extensions to be modular and enable/disable them. Some extensions are not modules, just a way for the API user to discover which API behavior to expect when we had to make changes to API behaviors.\n\nOr at least so far I was thinking of this extension like that. That\u0027s why I added its alias to the ml2 plugin\u0027s _supported_extension_aliases in the neutron patch.\n\n(Long-long ago we supported non-ml2 plugins, but I believe we stopped supporting them, so if something comes from ml2, then it\u0027s always there.)\n\nBut of course we can do this differently and make this extension modular: I can create a service plugin in the neutron patch, that does nothing else, but loads the extension. Or keep it in ml2 and add a config option to enable/disable the extension. I believe we have multiple extensions like that already.\n\nIs that something we want here? Who would want to turn this off and for what reason? I mean turning it on/off *at config time* without actually implementing support for multicast addresses in AAPs? (Because if someone implements it, they can just remove the whole extension from the code and add a new one.)\n\nI don\u0027t see a use case for that, but if you do, let me know and I\u0027ll create either the config option or the service plugin.","commit_id":"252fdeeddbd4620b5c3e7c8362f3d9b84e76528f"}]}
