)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"5970f143_d6b4dcd8","updated":"2026-05-05 14:48:06.000000000","message":"The agent extension looks good to me.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"02a17dcaccf859a8923aa54f67a0e4d0383a279d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"bcece3db_22deef8f","updated":"2026-05-12 18:05:12.000000000","message":"Some minor/easy comments now but I think we need extensive functional tests with this patch.","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7f7a70ad93a89ab4bddf4b775c4247670e2f9a8d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"6a43ae49_22c68183","updated":"2026-05-08 13:05:53.000000000","message":"recheck due to server creation timeout","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"a9bc51956f3b7fff1afcd3a7ddd91ab9ef53b33e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"8458a438_49f00046","updated":"2026-05-15 07:05:23.000000000","message":"Please address Miro\u0027s comments and it is LGTM for me","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"4990deaa_59497fe4","in_reply_to":"8458a438_49f00046","updated":"2026-05-15 17:04:04.000000000","message":"Partially addressed Miro\u0027s comment.  The uuid part of VRF naming pattern will wait until there is code in the main agent thread to handle lookup in ovsdb.","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e5fbd3b2d60f7d68212315c685b89953091377c4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"4df2970c_0047d16f","updated":"2026-05-18 14:58:36.000000000","message":"Some minor comments that can be addressed in a followup","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"259038b74cefae78f853aacc9b5cd054915f6b8b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"39baf3ee_b3f48c70","updated":"2026-05-19 19:58:21.000000000","message":"Function test failure might be due to this: https://review.opendev.org/c/openstack/neutron/+/989160\nPep8 failure might be tracked here: https://bugs.launchpad.net/neutron/+bug/2151750","commit_id":"0b12b3a845287fa052e4b63823e98aa442e40547"},{"author":{"_account_id":13861,"name":"yatin","email":"ykarel@redhat.com","username":"yatinkarel"},"change_message_id":"4d0dc8a9d8013a153e7b2ae973f7e6069c57d868","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"303e5113_628c10be","updated":"2026-05-20 06:14:37.000000000","message":"recheck pep8 and functional jobs fixed","commit_id":"0b12b3a845287fa052e4b63823e98aa442e40547"}],"neutron/agent/linux/nl_dispatcher.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"1531de87d23f09de284f6133c884a28d787fe62b","unresolved":true,"context_lines":[{"line_number":87,"context_line":"                        LOG.warning(\"Netlink receive buffer overrun, \""},{"line_number":88,"context_line":"                                    \"re-dumping\")"},{"line_number":89,"context_line":"                        self._dump_existing()"},{"line_number":90,"context_line":"                    else:"},{"line_number":91,"context_line":"                        LOG.debug(\"Transient netlink error, retrying\")"},{"line_number":92,"context_line":"        except Exception:"},{"line_number":93,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":94,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"095a59b5_9473287b","line":91,"range":{"start_line":90,"start_character":0,"end_line":91,"end_character":70},"updated":"2026-04-20 13:38:45.000000000","message":"We must not swallow the raised error here","commit_id":"df21c80008b059c97e59f6806006ba9b2a4484d8"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b98b2fcc0278312cfbb6916e79a78925276facb3","unresolved":false,"context_lines":[{"line_number":87,"context_line":"                        LOG.warning(\"Netlink receive buffer overrun, \""},{"line_number":88,"context_line":"                                    \"re-dumping\")"},{"line_number":89,"context_line":"                        self._dump_existing()"},{"line_number":90,"context_line":"                    else:"},{"line_number":91,"context_line":"                        LOG.debug(\"Transient netlink error, retrying\")"},{"line_number":92,"context_line":"        except Exception:"},{"line_number":93,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":94,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"f8ebc591_4863aa53","line":91,"range":{"start_line":90,"start_character":0,"end_line":91,"end_character":70},"in_reply_to":"095a59b5_9473287b","updated":"2026-05-04 14:48:20.000000000","message":"Done","commit_id":"df21c80008b059c97e59f6806006ba9b2a4484d8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"1531de87d23f09de284f6133c884a28d787fe62b","unresolved":true,"context_lines":[{"line_number":91,"context_line":"                        LOG.debug(\"Transient netlink error, retrying\")"},{"line_number":92,"context_line":"        except Exception:"},{"line_number":93,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def _dispatch(self, msg):"},{"line_number":96,"context_line":"        \"\"\"Dispatch message to all registered handlers.\"\"\""},{"line_number":97,"context_line":"        for handler in self._handlers:"},{"line_number":98,"context_line":"            handler(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"746255b7_e46edafe","line":98,"range":{"start_line":94,"start_character":0,"end_line":98,"end_character":24},"updated":"2026-04-20 13:38:45.000000000","message":"Would there be a reason to not register the handlers per the message type as I suggested in the previous PS?","commit_id":"df21c80008b059c97e59f6806006ba9b2a4484d8"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b98b2fcc0278312cfbb6916e79a78925276facb3","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                        LOG.debug(\"Transient netlink error, retrying\")"},{"line_number":92,"context_line":"        except Exception:"},{"line_number":93,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def _dispatch(self, msg):"},{"line_number":96,"context_line":"        \"\"\"Dispatch message to all registered handlers.\"\"\""},{"line_number":97,"context_line":"        for handler in self._handlers:"},{"line_number":98,"context_line":"            handler(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"c43d6d53_9638f844","line":98,"range":{"start_line":94,"start_character":0,"end_line":98,"end_character":24},"in_reply_to":"746255b7_e46edafe","updated":"2026-05-04 14:48:20.000000000","message":"Done","commit_id":"df21c80008b059c97e59f6806006ba9b2a4484d8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _dispatch(self, msg):"},{"line_number":75,"context_line":"        \"\"\"Dispatch message to the handler registered for its type.\"\"\""},{"line_number":76,"context_line":"        handler \u003d self._handlers.get(msg.get(\u0027event\u0027))"},{"line_number":77,"context_line":"        if handler:"},{"line_number":78,"context_line":"            handler(msg)"},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"432aa5a3_df6c0645","line":76,"range":{"start_line":76,"start_character":33,"end_line":76,"end_character":36},"updated":"2026-05-05 14:48:06.000000000","message":"Why do we need to call `get()` and the check right away? Can we just use KeyError if the message has no registered handler?","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def _dispatch(self, msg):"},{"line_number":75,"context_line":"        \"\"\"Dispatch message to the handler registered for its type.\"\"\""},{"line_number":76,"context_line":"        handler \u003d self._handlers.get(msg.get(\u0027event\u0027))"},{"line_number":77,"context_line":"        if handler:"},{"line_number":78,"context_line":"            handler(msg)"},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"46510e17_b9983d24","line":76,"range":{"start_line":76,"start_character":33,"end_line":76,"end_character":36},"in_reply_to":"432aa5a3_df6c0645","updated":"2026-05-07 14:44:40.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":98,"context_line":"                            LOG.error(\"Netlink socket error: %s, \""},{"line_number":99,"context_line":"                                      \"giving up after %d retries\","},{"line_number":100,"context_line":"                                      e, retries)"},{"line_number":101,"context_line":"                            break"},{"line_number":102,"context_line":"                        LOG.error(\"Netlink socket error: %s, \""},{"line_number":103,"context_line":"                                  \"reopening in %d seconds \""},{"line_number":104,"context_line":"                                  \"(retry %d/%d)\", e, self.RETRY_BACKOFF,"}],"source_content_type":"text/x-python","patch_set":6,"id":"680c7a70_2b4d6d45","line":101,"updated":"2026-05-05 14:48:06.000000000","message":"So in case of we run out of retries, we break here, close the socket but the OVN agent keeps running. What happens to this extension and the netlink monitoring?","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                            LOG.error(\"Netlink socket error: %s, \""},{"line_number":99,"context_line":"                                      \"giving up after %d retries\","},{"line_number":100,"context_line":"                                      e, retries)"},{"line_number":101,"context_line":"                            break"},{"line_number":102,"context_line":"                        LOG.error(\"Netlink socket error: %s, \""},{"line_number":103,"context_line":"                                  \"reopening in %d seconds \""},{"line_number":104,"context_line":"                                  \"(retry %d/%d)\", e, self.RETRY_BACKOFF,"}],"source_content_type":"text/x-python","patch_set":6,"id":"787d8292_e1b90a26","line":101,"in_reply_to":"13dfb8d5_ae94bf30","updated":"2026-05-07 14:44:40.000000000","message":"Updated to retry indefinitely for this error, OSError.\n\nThe thread can still die without killing the OVN agent.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ee3e4ffe676c5f5e23efc7d0de551626ee142262","unresolved":true,"context_lines":[{"line_number":98,"context_line":"                            LOG.error(\"Netlink socket error: %s, \""},{"line_number":99,"context_line":"                                      \"giving up after %d retries\","},{"line_number":100,"context_line":"                                      e, retries)"},{"line_number":101,"context_line":"                            break"},{"line_number":102,"context_line":"                        LOG.error(\"Netlink socket error: %s, \""},{"line_number":103,"context_line":"                                  \"reopening in %d seconds \""},{"line_number":104,"context_line":"                                  \"(retry %d/%d)\", e, self.RETRY_BACKOFF,"}],"source_content_type":"text/x-python","patch_set":6,"id":"13dfb8d5_ae94bf30","line":101,"in_reply_to":"680c7a70_2b4d6d45","updated":"2026-05-06 02:15:59.000000000","message":"The extension exits and the only way to recover is to restart OVN agent (manually).  Can keep retrying or force OVN agent to exit here.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"02a17dcaccf859a8923aa54f67a0e4d0383a279d","unresolved":true,"context_lines":[{"line_number":74,"context_line":"        \"\"\"Dispatch message to the handler registered for its type.\"\"\""},{"line_number":75,"context_line":"        try:"},{"line_number":76,"context_line":"            handler \u003d self._handlers[msg.get(\u0027event\u0027)]"},{"line_number":77,"context_line":"            handler(msg)"},{"line_number":78,"context_line":"        except KeyError:"},{"line_number":79,"context_line":"            LOG.debug(\"No handler for event %s\", msg.get(\u0027event\u0027))"},{"line_number":80,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"bbb88868_d278b1f2","line":77,"updated":"2026-05-12 18:05:12.000000000","message":"This should be outside of the try block. The handler can be anything, even a function that raises KeyError that is unhandled. In such case we should raise it up","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ddcc3bb38566180ca96ca90ce020337b93dfb8a1","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        \"\"\"Dispatch message to the handler registered for its type.\"\"\""},{"line_number":75,"context_line":"        try:"},{"line_number":76,"context_line":"            handler \u003d self._handlers[msg.get(\u0027event\u0027)]"},{"line_number":77,"context_line":"            handler(msg)"},{"line_number":78,"context_line":"        except KeyError:"},{"line_number":79,"context_line":"            LOG.debug(\"No handler for event %s\", msg.get(\u0027event\u0027))"},{"line_number":80,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"843ea0d1_152e47b3","line":77,"in_reply_to":"bbb88868_d278b1f2","updated":"2026-05-14 02:37:07.000000000","message":"Done","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":67,"context_line":"        self._thread.start()"},{"line_number":68,"context_line":"        LOG.info(\"NetlinkDispatcher started\")"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _open_sock(self):"},{"line_number":71,"context_line":"        if self._ipr is not None:"},{"line_number":72,"context_line":"            self._close_sock()"},{"line_number":73,"context_line":"        self._ipr \u003d IPRoute()"},{"line_number":74,"context_line":"        self._ipr.bind(self._groups)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def _close_sock(self):"},{"line_number":77,"context_line":"        if self._ipr is not None:"},{"line_number":78,"context_line":"            self._ipr.close()"},{"line_number":79,"context_line":"            self._ipr \u003d None"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _replay(self):"},{"line_number":82,"context_line":"        \"\"\"Dump current state and replay it through all handlers.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"8ed850e4_cdc6a992","line":79,"range":{"start_line":70,"start_character":0,"end_line":79,"end_character":28},"updated":"2026-05-15 13:24:28.000000000","message":"Would it make sense to implement it with a context manager instead?","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":67,"context_line":"        self._thread.start()"},{"line_number":68,"context_line":"        LOG.info(\"NetlinkDispatcher started\")"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _open_sock(self):"},{"line_number":71,"context_line":"        if self._ipr is not None:"},{"line_number":72,"context_line":"            self._close_sock()"},{"line_number":73,"context_line":"        self._ipr \u003d IPRoute()"},{"line_number":74,"context_line":"        self._ipr.bind(self._groups)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def _close_sock(self):"},{"line_number":77,"context_line":"        if self._ipr is not None:"},{"line_number":78,"context_line":"            self._ipr.close()"},{"line_number":79,"context_line":"            self._ipr \u003d None"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _replay(self):"},{"line_number":82,"context_line":"        \"\"\"Dump current state and replay it through all handlers.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"c713b7f4_93499702","line":79,"range":{"start_line":70,"start_character":0,"end_line":79,"end_character":28},"in_reply_to":"8ed850e4_cdc6a992","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"f0fcf8f2f21a72c1b4eb888123f634d356922327","unresolved":true,"context_lines":[{"line_number":103,"context_line":"            self._replay()"},{"line_number":104,"context_line":"            while True:"},{"line_number":105,"context_line":"                try:"},{"line_number":106,"context_line":"                    for msg in self._ipr.get():"},{"line_number":107,"context_line":"                        self._dispatch(msg)"},{"line_number":108,"context_line":"                        retries \u003d 0"},{"line_number":109,"context_line":"                except OSError as e:"}],"source_content_type":"text/x-python","patch_set":13,"id":"0cd9facf_4b529034","line":106,"range":{"start_line":106,"start_character":31,"end_line":106,"end_character":46},"updated":"2026-05-15 03:20:04.000000000","message":"this call is painfully slow on my machine. I am not sure if you run into it, I need to investigate","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"58511d6290f70a1f91343e605d0d095e91b73bf4","unresolved":false,"context_lines":[{"line_number":103,"context_line":"            self._replay()"},{"line_number":104,"context_line":"            while True:"},{"line_number":105,"context_line":"                try:"},{"line_number":106,"context_line":"                    for msg in self._ipr.get():"},{"line_number":107,"context_line":"                        self._dispatch(msg)"},{"line_number":108,"context_line":"                        retries \u003d 0"},{"line_number":109,"context_line":"                except OSError as e:"}],"source_content_type":"text/x-python","patch_set":13,"id":"3413da2d_228a8f4a","line":106,"range":{"start_line":106,"start_character":31,"end_line":106,"end_character":46},"in_reply_to":"0cd9facf_4b529034","updated":"2026-05-15 03:24:58.000000000","message":"never mind...","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":120,"context_line":"                        time.sleep(self.RETRY_BACKOFF)"},{"line_number":121,"context_line":"                        self._open_sock()"},{"line_number":122,"context_line":"                        self._replay()"},{"line_number":123,"context_line":"        except Exception:"},{"line_number":124,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":125,"context_line":"        finally:"},{"line_number":126,"context_line":"            self._close_sock()"}],"source_content_type":"text/x-python","patch_set":13,"id":"2ad43c7f_c7ce1395","line":124,"range":{"start_line":123,"start_character":0,"end_line":124,"end_character":54},"updated":"2026-05-15 13:24:28.000000000","message":"Shouldn\u0027t we let the agent crash too? to my understanding we won\u0027t recover and dead agent is better than running agent without the netlink thread, isn\u0027t it?","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":120,"context_line":"                        time.sleep(self.RETRY_BACKOFF)"},{"line_number":121,"context_line":"                        self._open_sock()"},{"line_number":122,"context_line":"                        self._replay()"},{"line_number":123,"context_line":"        except Exception:"},{"line_number":124,"context_line":"            LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":125,"context_line":"        finally:"},{"line_number":126,"context_line":"            self._close_sock()"}],"source_content_type":"text/x-python","patch_set":13,"id":"e50ab17c_d408f5cb","line":124,"range":{"start_line":123,"start_character":0,"end_line":124,"end_character":54},"in_reply_to":"2ad43c7f_c7ce1395","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":18,"context_line":"import time"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"from pyroute2 import IPRoute"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"d32bffdd_09592bff","line":21,"updated":"2026-05-15 13:24:28.000000000","message":"we should not be importing objects from modules","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import time"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":"from pyroute2 import IPRoute"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"d7e5b592_00e9b46e","line":21,"in_reply_to":"d32bffdd_09592bff","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"003ec504e8e4f0f6e26038d0711cbe866ef04dfb","unresolved":true,"context_lines":[{"line_number":118,"context_line":"                                          \"(retry %d)\", e,"},{"line_number":119,"context_line":"                                          self.RETRY_BACKOFF, retries)"},{"line_number":120,"context_line":"                                time.sleep(self.RETRY_BACKOFF)"},{"line_number":121,"context_line":"                                break"},{"line_number":122,"context_line":"            except Exception:"},{"line_number":123,"context_line":"                LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":124,"context_line":"                os._exit(1)"}],"source_content_type":"text/x-python","patch_set":15,"id":"b4b12ee0_08520eb6","line":121,"range":{"start_line":121,"start_character":0,"end_line":121,"end_character":37},"updated":"2026-05-15 17:24:37.000000000","message":"This is going to stop the main infinite loop leaving the agent again without the monitor, it won\u0027t even retry, or am I missing something?","commit_id":"85a26af9c97051f5775dce881351dca44a22b8ad"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7fe3caec064ea3b21fbb5931ed6129cd25d261f1","unresolved":false,"context_lines":[{"line_number":118,"context_line":"                                          \"(retry %d)\", e,"},{"line_number":119,"context_line":"                                          self.RETRY_BACKOFF, retries)"},{"line_number":120,"context_line":"                                time.sleep(self.RETRY_BACKOFF)"},{"line_number":121,"context_line":"                                break"},{"line_number":122,"context_line":"            except Exception:"},{"line_number":123,"context_line":"                LOG.exception(\"NetlinkDispatcher crashed\")"},{"line_number":124,"context_line":"                os._exit(1)"}],"source_content_type":"text/x-python","patch_set":15,"id":"a1b994ee_9c01658a","line":121,"range":{"start_line":121,"start_character":0,"end_line":121,"end_character":37},"in_reply_to":"b4b12ee0_08520eb6","updated":"2026-05-18 02:10:25.000000000","message":"This breaks out of the inner while-loop on line 104, and the socket closes.  The outer while-loop reopens the socket and tries again.","commit_id":"85a26af9c97051f5775dce881351dca44a22b8ad"}],"neutron/agent/ovn/extensions/bgp/netlink_monitor.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"2cb3e1f04e0211d69f4183a37f30f73927e3a989","unresolved":true,"context_lines":[{"line_number":25,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class NetlinkMonitor:"},{"line_number":29,"context_line":"    \"\"\"Monitor netlink for EVPN VRF creation and deletion events."},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    Runs a daemon thread that binds a netlink socket to RTNLGRP_LINK"}],"source_content_type":"text/x-python","patch_set":1,"id":"18a79be2_51ec0b7f","line":28,"range":{"start_line":28,"start_character":6,"end_line":28,"end_character":20},"updated":"2026-04-13 15:47:14.000000000","message":"I think this is a great start. I thought about something more generic rather than tailored for the vrf/bgp use-case.\n\nSo this class would be in some `common` package and it would be used in the BGP agent extension like\n```\nNetlinkMonitor:\n    ...\n    def register_handler(self, msg_type, handler):\n        self._handlers[msg_type].append(handler)\n        \n    def _handle_message(self, msg):\n        \"\"\"Handle link messages based on link type.\"\"\"\n        msg_type \u003d self._link_kind(msg)\n        for msg_handler in self._handlers.get(msg_type, []):\n            msg_handler(msg)\n    ...   \n    \nclass BGPExtension:\n    def __init__(self):\n        ...\n        self.nl_monitor \u003d linux_common.NetlinkMonitor()\n        self.nl_monitor.resgister_handler(self.handle_vrf)\n        self.nl_monitor.start()\n \n    def handle_vrf(self, msg):\n        # Handle the VRF stuff\n```","commit_id":"1fbf69b0b8af095c589e31d03515cb84c6c467b2"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"bd5e42adffa6863982b158b3ac919c76af4b1f98","unresolved":false,"context_lines":[{"line_number":25,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class NetlinkMonitor:"},{"line_number":29,"context_line":"    \"\"\"Monitor netlink for EVPN VRF creation and deletion events."},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    Runs a daemon thread that binds a netlink socket to RTNLGRP_LINK"}],"source_content_type":"text/x-python","patch_set":1,"id":"d4a54887_b1f0433e","line":28,"range":{"start_line":28,"start_character":6,"end_line":28,"end_character":20},"in_reply_to":"18a79be2_51ec0b7f","updated":"2026-05-04 14:48:36.000000000","message":"Done","commit_id":"1fbf69b0b8af095c589e31d03515cb84c6c467b2"}],"neutron/agent/ovn/extensions/evpn/__init__.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from oslo_log import log"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from pyroute2.netlink.rtnl import RTMGRP_LINK"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from neutron.agent.linux import nl_dispatcher"},{"line_number":21,"context_line":"from neutron.agent.ovn.extensions.evpn import netlink_monitor"}],"source_content_type":"text/x-python","patch_set":6,"id":"adb005cf_3e7ede7c","line":18,"updated":"2026-05-05 14:48:06.000000000","message":"We should not import objects from modules: https://docs.openstack.org/charm-guide/victoria/coding-guidelines.html#import-ordering-and-style","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from oslo_log import log"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from pyroute2.netlink.rtnl import RTMGRP_LINK"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from neutron.agent.linux import nl_dispatcher"},{"line_number":21,"context_line":"from neutron.agent.ovn.extensions.evpn import netlink_monitor"}],"source_content_type":"text/x-python","patch_set":6,"id":"4fad3294_007af62a","line":18,"in_reply_to":"adb005cf_3e7ede7c","updated":"2026-05-07 14:44:40.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":35,"context_line":"        self.nl_dispatcher \u003d nl_dispatcher.NetlinkDispatcher("},{"line_number":36,"context_line":"            RTMGRP_LINK)"},{"line_number":37,"context_line":"        self.nl_dispatcher.register_handler("},{"line_number":38,"context_line":"            \u0027RTM_NEWLINK\u0027, vrf_handler.handle_newlink)"},{"line_number":39,"context_line":"        self.nl_dispatcher.register_handler("},{"line_number":40,"context_line":"            \u0027RTM_DELLINK\u0027, vrf_handler.handle_dellink)"},{"line_number":41,"context_line":"        self.nl_dispatcher.start()"}],"source_content_type":"text/x-python","patch_set":6,"id":"58601be4_f777b773","line":38,"range":{"start_line":38,"start_character":12,"end_line":38,"end_character":25},"updated":"2026-05-05 14:48:06.000000000","message":"Perhaps we shall create constants for these? I know pyroute2 uses strings but would be good to avoid it in Neutron.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        self.nl_dispatcher \u003d nl_dispatcher.NetlinkDispatcher("},{"line_number":36,"context_line":"            RTMGRP_LINK)"},{"line_number":37,"context_line":"        self.nl_dispatcher.register_handler("},{"line_number":38,"context_line":"            \u0027RTM_NEWLINK\u0027, vrf_handler.handle_newlink)"},{"line_number":39,"context_line":"        self.nl_dispatcher.register_handler("},{"line_number":40,"context_line":"            \u0027RTM_DELLINK\u0027, vrf_handler.handle_dellink)"},{"line_number":41,"context_line":"        self.nl_dispatcher.start()"}],"source_content_type":"text/x-python","patch_set":6,"id":"0e9223c6_94a831e1","line":38,"range":{"start_line":38,"start_character":12,"end_line":38,"end_character":25},"in_reply_to":"58601be4_f777b773","updated":"2026-05-07 14:44:40.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"4520aec367b4d1e13a5ef2bc45052c626b64ad3f","unresolved":true,"context_lines":[{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from oslo_log import log"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from pyroute2.netlink import rtnl"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from neutron.agent.linux import nl_dispatcher"}],"source_content_type":"text/x-python","patch_set":12,"id":"b02797f4_59dd2e41","line":17,"updated":"2026-05-15 07:03:40.000000000","message":"nit: this empty line is not needed here","commit_id":"8a6b36ec501e60506379c11c594290e9548516b6"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from oslo_log import log"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from pyroute2.netlink import rtnl"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from neutron.agent.linux import nl_dispatcher"}],"source_content_type":"text/x-python","patch_set":12,"id":"02a54c76_46ede982","line":17,"in_reply_to":"b02797f4_59dd2e41","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"8a6b36ec501e60506379c11c594290e9548516b6"}],"neutron/agent/ovn/extensions/evpn/constants.py":[{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"0247fb2d1c0b22a6281dee22271c6ec67dc1b802","unresolved":true,"context_lines":[{"line_number":13,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"EVPN_VRF_PREFIX \u003d \u0027evpnvrf-\u0027    # Placeholder pattern"},{"line_number":17,"context_line":"EVPN_LINK_KIND_VRF \u003d \u0027vrf\u0027"},{"line_number":18,"context_line":"EVPN_RTM_NEWLINK \u003d \u0027RTM_NEWLINK\u0027"},{"line_number":19,"context_line":"EVPN_RTM_DELLINK \u003d \u0027RTM_DELLINK\u0027"}],"source_content_type":"text/x-python","patch_set":10,"id":"cfb43a89_a9320f16","line":16,"updated":"2026-05-15 02:51:42.000000000","message":"this prefix should be `vr`. as per the [spec naming convention](https://opendev.org/openstack/neutron-specs/src/branch/master/specs/2026.2/bgp_evpn_type_5_route_support.rst#thoughts-on-naming-convention)","commit_id":"5879bc1155b49ce0d593b336004c9a70036468e9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":13,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":14,"context_line":"#    under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"EVPN_VRF_PREFIX \u003d \u0027evpnvrf-\u0027    # Placeholder pattern"},{"line_number":17,"context_line":"EVPN_LINK_KIND_VRF \u003d \u0027vrf\u0027"},{"line_number":18,"context_line":"EVPN_RTM_NEWLINK \u003d \u0027RTM_NEWLINK\u0027"},{"line_number":19,"context_line":"EVPN_RTM_DELLINK \u003d \u0027RTM_DELLINK\u0027"}],"source_content_type":"text/x-python","patch_set":10,"id":"b6686416_d2cd923c","line":16,"in_reply_to":"cfb43a89_a9320f16","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"5879bc1155b49ce0d593b336004c9a70036468e9"}],"neutron/agent/ovn/extensions/evpn/netlink_monitor.py":[{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"255cf79b23c3b6d5dd6c9f18f12617c3a94ffcc6","unresolved":true,"context_lines":[{"line_number":48,"context_line":"                    return ifname, int("},{"line_number":49,"context_line":"                        ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"                except (ValueError, IndexError):"},{"line_number":51,"context_line":"                    pass"},{"line_number":52,"context_line":"        return None"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def handle_newlink(self, msg):"}],"source_content_type":"text/x-python","patch_set":3,"id":"4fd070a4_ce02bfe9","line":51,"updated":"2026-04-30 02:04:31.000000000","message":"I personally don\u0027t like to `pass` any exception. At least log a warn/info log,\nE.g. `f\"Failed to parse vrf from {ifname}\"`\n\nnit: I dont see how that code would produce an IndexError","commit_id":"944aa7f457f8382f5b991c282e9fb24146ae6a4a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b98b2fcc0278312cfbb6916e79a78925276facb3","unresolved":false,"context_lines":[{"line_number":48,"context_line":"                    return ifname, int("},{"line_number":49,"context_line":"                        ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"                except (ValueError, IndexError):"},{"line_number":51,"context_line":"                    pass"},{"line_number":52,"context_line":"        return None"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def handle_newlink(self, msg):"}],"source_content_type":"text/x-python","patch_set":3,"id":"20393c75_1dd6a361","line":51,"in_reply_to":"4fd070a4_ce02bfe9","updated":"2026-05-04 14:48:20.000000000","message":"I rewrote this to take out placeholder code.","commit_id":"944aa7f457f8382f5b991c282e9fb24146ae6a4a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":32,"context_line":"        self._known_vrfs \u003d set()"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    @staticmethod"},{"line_number":35,"context_line":"    def _link_kind(msg):"},{"line_number":36,"context_line":"        \"\"\"Extract IFLA_INFO_KIND from nested IFLA_LINKINFO.\"\"\""},{"line_number":37,"context_line":"        linkinfo \u003d msg.get_attr(\u0027IFLA_LINKINFO\u0027)"},{"line_number":38,"context_line":"        if linkinfo:"}],"source_content_type":"text/x-python","patch_set":6,"id":"499bce4b_5dd9b60a","line":35,"range":{"start_line":35,"start_character":8,"end_line":35,"end_character":18},"updated":"2026-05-05 14:48:06.000000000","message":"nit: As the word link can also sound as a verb, I\u0027d use `_get_link_kind`","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self._known_vrfs \u003d set()"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    @staticmethod"},{"line_number":35,"context_line":"    def _link_kind(msg):"},{"line_number":36,"context_line":"        \"\"\"Extract IFLA_INFO_KIND from nested IFLA_LINKINFO.\"\"\""},{"line_number":37,"context_line":"        linkinfo \u003d msg.get_attr(\u0027IFLA_LINKINFO\u0027)"},{"line_number":38,"context_line":"        if linkinfo:"}],"source_content_type":"text/x-python","patch_set":6,"id":"4a8a8753_6ae31605","line":35,"range":{"start_line":35,"start_character":8,"end_line":35,"end_character":18},"in_reply_to":"499bce4b_5dd9b60a","updated":"2026-05-07 14:44:40.000000000","message":"Removed this function since the get_nested() suggestion works.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":34,"context_line":"    @staticmethod"},{"line_number":35,"context_line":"    def _link_kind(msg):"},{"line_number":36,"context_line":"        \"\"\"Extract IFLA_INFO_KIND from nested IFLA_LINKINFO.\"\"\""},{"line_number":37,"context_line":"        linkinfo \u003d msg.get_attr(\u0027IFLA_LINKINFO\u0027)"},{"line_number":38,"context_line":"        if linkinfo:"},{"line_number":39,"context_line":"            return linkinfo.get_attr(\u0027IFLA_INFO_KIND\u0027)"},{"line_number":40,"context_line":"        return None"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":43,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"017b1819_342cda82","line":40,"range":{"start_line":37,"start_character":0,"end_line":40,"end_character":19},"updated":"2026-05-05 14:48:06.000000000","message":"Would this do the same?\n```\nreturn msg.get_nested(\u0027IFLA_LINKINFO\u0027, \u0027IFLA_INFO_KIND\u0027)\n```","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    @staticmethod"},{"line_number":35,"context_line":"    def _link_kind(msg):"},{"line_number":36,"context_line":"        \"\"\"Extract IFLA_INFO_KIND from nested IFLA_LINKINFO.\"\"\""},{"line_number":37,"context_line":"        linkinfo \u003d msg.get_attr(\u0027IFLA_LINKINFO\u0027)"},{"line_number":38,"context_line":"        if linkinfo:"},{"line_number":39,"context_line":"            return linkinfo.get_attr(\u0027IFLA_INFO_KIND\u0027)"},{"line_number":40,"context_line":"        return None"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":43,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"410bb800_faa49e93","line":40,"range":{"start_line":37,"start_character":0,"end_line":40,"end_character":19},"in_reply_to":"017b1819_342cda82","updated":"2026-05-07 14:44:40.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":43,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""},{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"}],"source_content_type":"text/x-python","patch_set":6,"id":"46f5ce25_f6a08b34","line":44,"updated":"2026-05-05 14:48:06.000000000","message":"Is the None value used anywhere? It seems to me when None is returned it means we didn\u0027t parse and we should not do anything, which should be treated as an exception.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ee3e4ffe676c5f5e23efc7d0de551626ee142262","unresolved":true,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":43,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""},{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"}],"source_content_type":"text/x-python","patch_set":6,"id":"49ee8456_5c73b97f","line":44,"in_reply_to":"46f5ce25_f6a08b34","updated":"2026-05-06 02:15:59.000000000","message":"When we subscribe for RTM_NEWLINK or RTM_DELLINK messages, we get all the \"ip link add\" and \"ip link del\" messages.  We only care about link messages that are type vrf and only the vrf links that are EVPN VRFs.  (OVN can also create VRFs for core BGP.)\n\nSo, result is None occurs when the message is about all other types of links that the extension doesn\u0027t care to process.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":43,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""},{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"}],"source_content_type":"text/x-python","patch_set":6,"id":"0c402eb1_b973ae5c","line":44,"in_reply_to":"49ee8456_5c73b97f","updated":"2026-05-07 14:44:40.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":48,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":49,"context_line":"                result \u003d ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"        return result"}],"source_content_type":"text/x-python","patch_set":6,"id":"24d9f7b1_c964beb2","line":47,"updated":"2026-05-05 14:48:06.000000000","message":"We should rely on naming here and treat all vrfs as created by the ovn-controller.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"29858243e27e782f53f9f031931653eabc24a839","unresolved":true,"context_lines":[{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":48,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":49,"context_line":"                result \u003d ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"        return result"}],"source_content_type":"text/x-python","patch_set":6,"id":"56507bc5_ba6a9049","line":47,"in_reply_to":"24d9f7b1_c964beb2","updated":"2026-05-06 13:01:26.000000000","message":"Correction: We should *NOT* rely on naming :) and just assume only ovn-controller can be the one creating vrfs.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        result \u003d None"},{"line_number":45,"context_line":"        if self._link_kind(msg) \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":48,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":49,"context_line":"                result \u003d ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"        return result"}],"source_content_type":"text/x-python","patch_set":6,"id":"ae3e9374_ac5b7194","line":47,"in_reply_to":"56507bc5_ba6a9049","updated":"2026-05-07 14:44:40.000000000","message":"Even when assuming that only ovn-controller create VRFs, can\u0027t assume all VRFs are for EVPN, since ovn-controller also creates VRFs for core BGP.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":54,"context_line":"        if result:"},{"line_number":55,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":56,"context_line":"            ifname, vni \u003d result"},{"line_number":57,"context_line":"            if vni not in self._known_vrfs:"},{"line_number":58,"context_line":"                self._known_vrfs.add(vni)"},{"line_number":59,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"ca2f181f_5745a118","line":57,"updated":"2026-05-05 14:48:06.000000000","message":"Why do we need this check and when can it happen we\u0027d get new vrf for already known vrfs?","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"1505a4027509b4bcb776a1cc3286ef9a223643d5","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        if result:"},{"line_number":55,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":56,"context_line":"            ifname, vni \u003d result"},{"line_number":57,"context_line":"            if vni not in self._known_vrfs:"},{"line_number":58,"context_line":"                self._known_vrfs.add(vni)"},{"line_number":59,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"d5e6fd94_942926a7","line":57,"in_reply_to":"76f99021_43c97a81","updated":"2026-05-07 14:44:40.000000000","message":"I forgot that this check exists because both \"ip link add\" and \"ip link set \u003clink\u003e up\" both come as RTM_NEWLINK messages and there\u0027s no way to distinguish them.  The flag NLM_F_CREATE in the message is not set in these messages that the kernel relays.  So, it is necessary to check to filter out the second RTM_NEWLINK message.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ee3e4ffe676c5f5e23efc7d0de551626ee142262","unresolved":true,"context_lines":[{"line_number":54,"context_line":"        if result:"},{"line_number":55,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":56,"context_line":"            ifname, vni \u003d result"},{"line_number":57,"context_line":"            if vni not in self._known_vrfs:"},{"line_number":58,"context_line":"                self._known_vrfs.add(vni)"},{"line_number":59,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"76f99021_43c97a81","line":57,"in_reply_to":"ca2f181f_5745a118","updated":"2026-05-06 02:15:59.000000000","message":"You\u0027re right.  We don\u0027t need to check here.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ac22c490690a98f28566e8dd4e188854e664e27b","unresolved":true,"context_lines":[{"line_number":34,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":35,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""},{"line_number":36,"context_line":"        result \u003d None"},{"line_number":37,"context_line":"        if msg.get_nested(\u0027IFLA_LINKINFO\u0027, \u0027IFLA_INFO_KIND\u0027) \u003d\u003d \\"},{"line_number":38,"context_line":"                evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":39,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":40,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"}],"source_content_type":"text/x-python","patch_set":11,"id":"fc85d059_4b6b84a9","line":37,"updated":"2026-05-12 18:47:18.000000000","message":"nit: It reads better if there was `self._get_link_msg() \u003d\u003d KIND`. Also","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ddcc3bb38566180ca96ca90ce020337b93dfb8a1","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":35,"context_line":"        \"\"\"Parse VNI from an EVPN VRF message, or return None.\"\"\""},{"line_number":36,"context_line":"        result \u003d None"},{"line_number":37,"context_line":"        if msg.get_nested(\u0027IFLA_LINKINFO\u0027, \u0027IFLA_INFO_KIND\u0027) \u003d\u003d \\"},{"line_number":38,"context_line":"                evpn_const.EVPN_LINK_KIND_VRF:"},{"line_number":39,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":40,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"}],"source_content_type":"text/x-python","patch_set":11,"id":"7e24b64f_bcf3f44b","line":37,"in_reply_to":"fc85d059_4b6b84a9","updated":"2026-05-14 02:37:07.000000000","message":"Done","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ac22c490690a98f28566e8dd4e188854e664e27b","unresolved":true,"context_lines":[{"line_number":40,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":41,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":42,"context_line":"                result \u003d ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":43,"context_line":"        return result"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def handle_newlink(self, msg):"},{"line_number":46,"context_line":"        result \u003d self._parse_evpn_vrf(msg)"}],"source_content_type":"text/x-python","patch_set":11,"id":"e2c2fd48_5a9899b8","line":43,"updated":"2026-05-12 18:47:18.000000000","message":"```\nreturn None, None\n```\nor better\n```\nraise UnknownMessage\n```","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ddcc3bb38566180ca96ca90ce020337b93dfb8a1","unresolved":false,"context_lines":[{"line_number":40,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":41,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":42,"context_line":"                result \u003d ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":43,"context_line":"        return result"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def handle_newlink(self, msg):"},{"line_number":46,"context_line":"        result \u003d self._parse_evpn_vrf(msg)"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a6c3ce0_f85290e3","line":43,"in_reply_to":"e2c2fd48_5a9899b8","updated":"2026-05-14 02:37:07.000000000","message":"Done","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"02a17dcaccf859a8923aa54f67a0e4d0383a279d","unresolved":true,"context_lines":[{"line_number":47,"context_line":"        if result:"},{"line_number":48,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":49,"context_line":"            ifname, vni \u003d result"},{"line_number":50,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"},{"line_number":51,"context_line":"            # creation; only process the first one per VNI."},{"line_number":52,"context_line":"            if vni not in self._known_vrfs:"},{"line_number":53,"context_line":"                self._known_vrfs.add(vni)"},{"line_number":54,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":11,"id":"bfd98063_cd85ebb1","line":51,"range":{"start_line":50,"start_character":0,"end_line":51,"end_character":59},"updated":"2026-05-12 18:05:12.000000000","message":"This must be tested with the functional tests.","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"461268e46df88835d8af21731d95cd85a829a0a3","unresolved":false,"context_lines":[{"line_number":47,"context_line":"        if result:"},{"line_number":48,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":49,"context_line":"            ifname, vni \u003d result"},{"line_number":50,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"},{"line_number":51,"context_line":"            # creation; only process the first one per VNI."},{"line_number":52,"context_line":"            if vni not in self._known_vrfs:"},{"line_number":53,"context_line":"                self._known_vrfs.add(vni)"},{"line_number":54,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":11,"id":"95c733fc_b3bef684","line":51,"range":{"start_line":50,"start_character":0,"end_line":51,"end_character":59},"in_reply_to":"bfd98063_cd85ebb1","updated":"2026-05-15 03:53:16.000000000","message":"Done","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ac22c490690a98f28566e8dd4e188854e664e27b","unresolved":true,"context_lines":[{"line_number":54,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def handle_dellink(self, msg):"},{"line_number":57,"context_line":"        result \u003d self._parse_evpn_vrf(msg)"},{"line_number":58,"context_line":"        if result:"},{"line_number":59,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":60,"context_line":"            ifname, vni \u003d result"},{"line_number":61,"context_line":"            self._known_vrfs.discard(vni)"},{"line_number":62,"context_line":"            LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":11,"id":"49d1855d_d103dd93","line":60,"range":{"start_line":57,"start_character":0,"end_line":60,"end_character":32},"updated":"2026-05-12 18:47:18.000000000","message":"Either:\n```\nifname, vni \u003d self._parse()\ntry:\n    self.remove(vni)\n    LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)\nexcept KeyError:\n    pass\n```\nor better\n```\ntry:\n    ifname, vni \u003d self._parse()\n    self._known_vrfs.discard(vni)\n    LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)\nexcept UnknownMessage:\n    pass\n```","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ddcc3bb38566180ca96ca90ce020337b93dfb8a1","unresolved":false,"context_lines":[{"line_number":54,"context_line":"                LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def handle_dellink(self, msg):"},{"line_number":57,"context_line":"        result \u003d self._parse_evpn_vrf(msg)"},{"line_number":58,"context_line":"        if result:"},{"line_number":59,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":60,"context_line":"            ifname, vni \u003d result"},{"line_number":61,"context_line":"            self._known_vrfs.discard(vni)"},{"line_number":62,"context_line":"            LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":11,"id":"6d8ed174_7206e8bc","line":60,"range":{"start_line":57,"start_character":0,"end_line":60,"end_character":32},"in_reply_to":"49d1855d_d103dd93","updated":"2026-05-14 02:37:07.000000000","message":"Done","commit_id":"78f5e39812e2596121cea62cf5672cf4f33664ab"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"0247fb2d1c0b22a6281dee22271c6ec67dc1b802","unresolved":true,"context_lines":[{"line_number":60,"context_line":"    def handle_newlink(self, msg):"},{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            result \u003d self._parse_evpn_vrf(msg)"},{"line_number":63,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":64,"context_line":"            ifname, vni \u003d result"},{"line_number":65,"context_line":"            if self._is_in_replay():"},{"line_number":66,"context_line":"                self._replay_vrfs.add(vni)"}],"source_content_type":"text/x-python","patch_set":13,"id":"651ab489_1fd9d491","line":63,"range":{"start_line":63,"start_character":0,"end_line":63,"end_character":63},"updated":"2026-05-15 02:51:42.000000000","message":"same here, we already established naming convention.","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    def handle_newlink(self, msg):"},{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            result \u003d self._parse_evpn_vrf(msg)"},{"line_number":63,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":64,"context_line":"            ifname, vni \u003d result"},{"line_number":65,"context_line":"            if self._is_in_replay():"},{"line_number":66,"context_line":"                self._replay_vrfs.add(vni)"}],"source_content_type":"text/x-python","patch_set":13,"id":"a0fe9ba4_a16fda31","line":63,"range":{"start_line":63,"start_character":0,"end_line":63,"end_character":63},"in_reply_to":"651ab489_1fd9d491","updated":"2026-05-15 17:04:04.000000000","message":"Prefix is fixed, but leaving the uuid and VNI cross reference when there is more code to handle passing information from the dispatcher thread to the main agent thread, since there isn\u0027t any code outside of the dispatcher thread yet.","commit_id":"a18cf48d3348aa6aa2140215c42db32aec63003c"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":48,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":49,"context_line":"                return ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"            raise evpn_exc.UnknownVrfMessage"},{"line_number":51,"context_line":"        raise evpn_exc.UnknownMessage"},{"line_number":52,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"51ab548b_410d851c","line":49,"range":{"start_line":49,"start_character":35,"end_line":49,"end_character":75},"updated":"2026-05-15 13:24:28.000000000","message":"This is a strange way to get the number, wouldn\u0027t `int(ifname.replace(evpn_const.EVPN_VRF_PREFIX, \"\"))` do the same or do we expect to also have prefixes that are the same length but different content?\n\nI also think we should be defensive against ValueError exception raised by int() conversion.","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":46,"context_line":"            ifname \u003d msg.get_attr(\u0027IFLA_IFNAME\u0027)"},{"line_number":47,"context_line":"            if ifname and ifname.startswith(evpn_const.EVPN_VRF_PREFIX):"},{"line_number":48,"context_line":"                # Assume placeholder VRF name pattern evpnvrf- for now"},{"line_number":49,"context_line":"                return ifname, int(ifname[len(evpn_const.EVPN_VRF_PREFIX):])"},{"line_number":50,"context_line":"            raise evpn_exc.UnknownVrfMessage"},{"line_number":51,"context_line":"        raise evpn_exc.UnknownMessage"},{"line_number":52,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"27261fc2_4157ba4d","line":49,"range":{"start_line":49,"start_character":35,"end_line":49,"end_character":75},"in_reply_to":"51ab548b_410d851c","updated":"2026-05-15 17:04:04.000000000","message":"Replaced with int(ifname.replace(evpn_const.EVPN_VRF_PREFIX, \"\")) .\n\nI did not add ValueError exception, since the VNI embedded in the VRF name is just a placeholder for now.  There isn\u0027t enough code in the main agent thread to handle the real VRF name parsing to get obtain the VNI.","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            result \u003d self._parse_evpn_vrf(msg)"},{"line_number":63,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":64,"context_line":"            ifname, vni \u003d result"},{"line_number":65,"context_line":"            if self._is_in_replay():"},{"line_number":66,"context_line":"                self._replay_vrfs.add(vni)"},{"line_number":67,"context_line":"                LOG.info(\"VRF previously created: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":14,"id":"19398f1c_026397b3","line":64,"updated":"2026-05-15 13:24:28.000000000","message":"nit: the result is unused and you can assign to ifname, vni directly","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            result \u003d self._parse_evpn_vrf(msg)"},{"line_number":63,"context_line":"            # Placeholder VRF name includes VNI in the VRF name"},{"line_number":64,"context_line":"            ifname, vni \u003d result"},{"line_number":65,"context_line":"            if self._is_in_replay():"},{"line_number":66,"context_line":"                self._replay_vrfs.add(vni)"},{"line_number":67,"context_line":"                LOG.info(\"VRF previously created: %s (VNI %d)\", ifname, vni)"}],"source_content_type":"text/x-python","patch_set":14,"id":"0eaaafc0_074160db","line":64,"in_reply_to":"19398f1c_026397b3","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":71,"context_line":"                if vni not in self._known_vrfs:"},{"line_number":72,"context_line":"                    self._known_vrfs.add(vni)"},{"line_number":73,"context_line":"                    LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":74,"context_line":"        except (evpn_exc.UnknownMessage, evpn_exc.UnknownVrfMessage):"},{"line_number":75,"context_line":"            # This is not an EVPN VRF"},{"line_number":76,"context_line":"            pass"},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"7b98695e_5e1214f3","line":74,"updated":"2026-05-15 13:24:28.000000000","message":"Shouldn\u0027t this be only around _parse_evpn_vrf?","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":71,"context_line":"                if vni not in self._known_vrfs:"},{"line_number":72,"context_line":"                    self._known_vrfs.add(vni)"},{"line_number":73,"context_line":"                    LOG.info(\"VRF created: %s (VNI %d)\", ifname, vni)"},{"line_number":74,"context_line":"        except (evpn_exc.UnknownMessage, evpn_exc.UnknownVrfMessage):"},{"line_number":75,"context_line":"            # This is not an EVPN VRF"},{"line_number":76,"context_line":"            pass"},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"2fa12794_a394471d","line":74,"in_reply_to":"7b98695e_5e1214f3","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c0b0f072a20f8839e7ac2f6f31bd765761763590","unresolved":true,"context_lines":[{"line_number":80,"context_line":"            ifname, vni \u003d self._parse_evpn_vrf(msg)"},{"line_number":81,"context_line":"            self._known_vrfs.discard(vni)"},{"line_number":82,"context_line":"            LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)"},{"line_number":83,"context_line":"        except (evpn_exc.UnknownMessage, evpn_exc.UnknownVrfMessage):"},{"line_number":84,"context_line":"            # This is not an EVPN VRF"},{"line_number":85,"context_line":"            pass"}],"source_content_type":"text/x-python","patch_set":14,"id":"e1289dad_ad6413a6","line":83,"updated":"2026-05-15 13:24:28.000000000","message":"ditto","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"7a67a9e9ed526b914c764f9b8042edc08cb9fe87","unresolved":false,"context_lines":[{"line_number":80,"context_line":"            ifname, vni \u003d self._parse_evpn_vrf(msg)"},{"line_number":81,"context_line":"            self._known_vrfs.discard(vni)"},{"line_number":82,"context_line":"            LOG.info(\"VRF deleted: %s (VNI %d)\", ifname, vni)"},{"line_number":83,"context_line":"        except (evpn_exc.UnknownMessage, evpn_exc.UnknownVrfMessage):"},{"line_number":84,"context_line":"            # This is not an EVPN VRF"},{"line_number":85,"context_line":"            pass"}],"source_content_type":"text/x-python","patch_set":14,"id":"a2188c13_51d216f9","line":83,"in_reply_to":"e1289dad_ad6413a6","updated":"2026-05-15 17:04:04.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":13861,"name":"yatin","email":"ykarel@redhat.com","username":"yatinkarel"},"change_message_id":"2e29e02c25235e926dab34e4b2edfae2936e82ef","unresolved":true,"context_lines":[{"line_number":25,"context_line":"    \"\"\"Handle netlink messages for EVPN VRF interfaces."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    Filters for VRF interfaces whose name starts with the EVPN VRF"},{"line_number":28,"context_line":"    prefix (evpnvrf-).  Tracks known VRFs to deduplicate RTM_NEWLINK"},{"line_number":29,"context_line":"    messages from state changes."},{"line_number":30,"context_line":"    \"\"\""},{"line_number":31,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"0799534f_61c8b045","line":28,"updated":"2026-05-18 08:17:41.000000000","message":"prefix outdated here","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"8eabdbe1c0460b3cefc8455f1fe961625320623d","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    \"\"\"Handle netlink messages for EVPN VRF interfaces."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    Filters for VRF interfaces whose name starts with the EVPN VRF"},{"line_number":28,"context_line":"    prefix (evpnvrf-).  Tracks known VRFs to deduplicate RTM_NEWLINK"},{"line_number":29,"context_line":"    messages from state changes."},{"line_number":30,"context_line":"    \"\"\""},{"line_number":31,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"4e9dffe2_4558dc23","line":28,"in_reply_to":"0799534f_61c8b045","updated":"2026-05-18 13:01:42.000000000","message":"Done","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"9e018025d70b8d05c88eae432ed96b7f7d9b8933","unresolved":true,"context_lines":[{"line_number":70,"context_line":"            # This is not an EVPN VRF"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        if self._is_in_replay():"},{"line_number":73,"context_line":"            self._replay_vrfs.add(evpnvrf)"},{"line_number":74,"context_line":"            LOG.info(\"VRF previously created: %s\", evpnvrf)"},{"line_number":75,"context_line":"        else:"},{"line_number":76,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"}],"source_content_type":"text/x-python","patch_set":16,"id":"bf8147c6_35ba0310","line":73,"updated":"2026-05-18 07:06:43.000000000","message":"how this works if `self._replay_vrfs` is declared as `None` in L34?","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"8eabdbe1c0460b3cefc8455f1fe961625320623d","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            # This is not an EVPN VRF"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        if self._is_in_replay():"},{"line_number":73,"context_line":"            self._replay_vrfs.add(evpnvrf)"},{"line_number":74,"context_line":"            LOG.info(\"VRF previously created: %s\", evpnvrf)"},{"line_number":75,"context_line":"        else:"},{"line_number":76,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"}],"source_content_type":"text/x-python","patch_set":16,"id":"a7b57f92_2f6c5232","line":73,"in_reply_to":"8b4e37ba_1c5e7add","updated":"2026-05-18 13:01:42.000000000","message":"In this patch, at the start of replay, _replay_vrfs is set to an empty set.  During replay, VRFs received are added to _replay_vrfs.  At the end of replay, _known_vrfs points to _replay_vrfs and _replay_vrfs is set to None.\n\nThis is the stub replay code since this code only tracks existence of VRFs right now.  The actual code is in the FSM patch.\n\nIn the FSM patch, at the end of replay, stale VRFs and their corresponding Evpn instances, the VRFs in _known_vrfs but not in _replay_vrfs, are deleted.","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"138dce0ace40c99acecec9cd008d851fa00f8e3f","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            # This is not an EVPN VRF"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        if self._is_in_replay():"},{"line_number":73,"context_line":"            self._replay_vrfs.add(evpnvrf)"},{"line_number":74,"context_line":"            LOG.info(\"VRF previously created: %s\", evpnvrf)"},{"line_number":75,"context_line":"        else:"},{"line_number":76,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"}],"source_content_type":"text/x-python","patch_set":16,"id":"440587ec_0f3b318d","line":73,"in_reply_to":"a7b57f92_2f6c5232","updated":"2026-05-18 14:36:39.000000000","message":"Ok, I don\u0027t know how I did not notice \"if\" in just one line above 😀","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":13861,"name":"yatin","email":"ykarel@redhat.com","username":"yatinkarel"},"change_message_id":"2e29e02c25235e926dab34e4b2edfae2936e82ef","unresolved":true,"context_lines":[{"line_number":70,"context_line":"            # This is not an EVPN VRF"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        if self._is_in_replay():"},{"line_number":73,"context_line":"            self._replay_vrfs.add(evpnvrf)"},{"line_number":74,"context_line":"            LOG.info(\"VRF previously created: %s\", evpnvrf)"},{"line_number":75,"context_line":"        else:"},{"line_number":76,"context_line":"            # The kernel sends multiple RTM_NEWLINK messages during VRF"}],"source_content_type":"text/x-python","patch_set":16,"id":"8b4e37ba_1c5e7add","line":73,"in_reply_to":"bf8147c6_35ba0310","updated":"2026-05-18 08:17:41.000000000","message":"but L72 should guard the None case, or /me missing something.","commit_id":"3f03cfd012d2361eefce430f9ed43a048204aee3"},{"author":{"_account_id":13861,"name":"yatin","email":"ykarel@redhat.com","username":"yatinkarel"},"change_message_id":"719608344e0c1f979141b3c0b039ae2c0f5f4796","unresolved":true,"context_lines":[{"line_number":25,"context_line":"    \"\"\"Handle netlink messages for EVPN VRF interfaces."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    Filters for VRF interfaces whose name starts with the EVPN VRF"},{"line_number":28,"context_line":"    prefix (vr\u003cLR uuid\u003e).  Tracks known VRFs to deduplicate RTM_NEWLINK"},{"line_number":29,"context_line":"    messages from state changes."},{"line_number":30,"context_line":"    \"\"\""},{"line_number":31,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"62f9f027_82e43201","line":28,"range":{"start_line":28,"start_character":15,"end_line":28,"end_character":22},"updated":"2026-05-19 09:20:04.000000000","message":"it\u0027s  not full uuid, but first 12 characters, also now wondering if we using partial uuids, seems it can conflict some time, or that is taken care somewhere?","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"8143ea1580182c890d81c574543e1ddb49d4877c","unresolved":true,"context_lines":[{"line_number":25,"context_line":"    \"\"\"Handle netlink messages for EVPN VRF interfaces."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    Filters for VRF interfaces whose name starts with the EVPN VRF"},{"line_number":28,"context_line":"    prefix (vr\u003cLR uuid\u003e).  Tracks known VRFs to deduplicate RTM_NEWLINK"},{"line_number":29,"context_line":"    messages from state changes."},{"line_number":30,"context_line":"    \"\"\""},{"line_number":31,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"eb462157_7a25c6a7","line":28,"range":{"start_line":28,"start_character":15,"end_line":28,"end_character":22},"in_reply_to":"62f9f027_82e43201","updated":"2026-05-19 13:50:30.000000000","message":"correct just the first 12 characters, I think the changes of collisions are very low. We do same thing for VM tap interfaces where the tap interface is `tap+slice of port uuid`. Alos, we make lot more tap ports in openstack then we will VRFs.","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b4e57c6197a3505c1f076801f1cef921bb92a15a","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    \"\"\"Handle netlink messages for EVPN VRF interfaces."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    Filters for VRF interfaces whose name starts with the EVPN VRF"},{"line_number":28,"context_line":"    prefix (vr\u003cLR uuid\u003e).  Tracks known VRFs to deduplicate RTM_NEWLINK"},{"line_number":29,"context_line":"    messages from state changes."},{"line_number":30,"context_line":"    \"\"\""},{"line_number":31,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"e4649b7d_190f6c20","line":28,"range":{"start_line":28,"start_character":15,"end_line":28,"end_character":22},"in_reply_to":"eb462157_7a25c6a7","updated":"2026-05-19 15:54:03.000000000","message":"Done","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e86866a9a830c3669de737730a132e367361900e","unresolved":true,"context_lines":[{"line_number":40,"context_line":"        link_kind \u003d msg.get_nested(\u0027IFLA_LINKINFO\u0027, \u0027IFLA_INFO_KIND\u0027)"},{"line_number":41,"context_line":"        return link_kind \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def _is_evpn_vrf(self, ifname):"},{"line_number":44,"context_line":"        # EVPN VRF name is 14 characters: EVPN_VRF_PREFIX followed by"},{"line_number":45,"context_line":"        # the first 12 characters of the logical router\u0027s UUID."},{"line_number":46,"context_line":"        return (ifname and"},{"line_number":47,"context_line":"                len(ifname) \u003d\u003d 14 and"},{"line_number":48,"context_line":"                ifname.startswith(evpn_const.EVPN_VRF_PREFIX))"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":51,"context_line":"        \"\"\"Parse EVPN VRF name from a netlink message.\"\"\""}],"source_content_type":"text/x-python","patch_set":18,"id":"84d8f20d_2bc72032","line":48,"range":{"start_line":43,"start_character":0,"end_line":48,"end_character":62},"updated":"2026-05-18 14:59:50.000000000","message":"In error I commented on this in a different PS - https://review.opendev.org/c/openstack/neutron/+/986832/5..6/neutron/agent/ovn/extensions/evpn/netlink_monitor.py","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"3cfbac7df3aaf78d04f02e4455cff3f510fb5dcd","unresolved":false,"context_lines":[{"line_number":40,"context_line":"        link_kind \u003d msg.get_nested(\u0027IFLA_LINKINFO\u0027, \u0027IFLA_INFO_KIND\u0027)"},{"line_number":41,"context_line":"        return link_kind \u003d\u003d evpn_const.EVPN_LINK_KIND_VRF"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def _is_evpn_vrf(self, ifname):"},{"line_number":44,"context_line":"        # EVPN VRF name is 14 characters: EVPN_VRF_PREFIX followed by"},{"line_number":45,"context_line":"        # the first 12 characters of the logical router\u0027s UUID."},{"line_number":46,"context_line":"        return (ifname and"},{"line_number":47,"context_line":"                len(ifname) \u003d\u003d 14 and"},{"line_number":48,"context_line":"                ifname.startswith(evpn_const.EVPN_VRF_PREFIX))"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def _parse_evpn_vrf(self, msg):"},{"line_number":51,"context_line":"        \"\"\"Parse EVPN VRF name from a netlink message.\"\"\""}],"source_content_type":"text/x-python","patch_set":18,"id":"7acf9b58_1c84bad3","line":48,"range":{"start_line":43,"start_character":0,"end_line":48,"end_character":62},"in_reply_to":"84d8f20d_2bc72032","updated":"2026-05-18 16:09:45.000000000","message":"Incorporated in this patch https://review.opendev.org/c/openstack/neutron/+/986832","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"}],"neutron/tests/functional/agent/ovn/extensions/test_evpn.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e5fbd3b2d60f7d68212315c685b89953091377c4","unresolved":true,"context_lines":[{"line_number":33,"context_line":"        except Exception:"},{"line_number":34,"context_line":"            pass"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    def test_vrf_handler_lifecycle(self):"},{"line_number":37,"context_line":"        vrf_handler \u003d netlink_monitor.VrfHandler()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"        dispatcher \u003d nl_dispatcher.NetlinkDispatcher(rtnl.RTMGRP_LINK)"}],"source_content_type":"text/x-python","patch_set":18,"id":"5eff7c54_5ed3e95d","line":36,"updated":"2026-05-18 14:58:36.000000000","message":"shall we split this into \"actions\" - ie. create vs delete? if we test a lifecycle and very first action fails, we won\u0027t get coverage for the rest because the execution stops.","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"3cfbac7df3aaf78d04f02e4455cff3f510fb5dcd","unresolved":false,"context_lines":[{"line_number":33,"context_line":"        except Exception:"},{"line_number":34,"context_line":"            pass"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    def test_vrf_handler_lifecycle(self):"},{"line_number":37,"context_line":"        vrf_handler \u003d netlink_monitor.VrfHandler()"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"        dispatcher \u003d nl_dispatcher.NetlinkDispatcher(rtnl.RTMGRP_LINK)"}],"source_content_type":"text/x-python","patch_set":18,"id":"8ac0a2c1_d02c88f1","line":36,"in_reply_to":"5eff7c54_5ed3e95d","updated":"2026-05-18 16:09:45.000000000","message":"The way the functional tests work and the way the dispatcher thread is currently written, independently testing newlink and dellink can only be done in unit tests.  The test_evpn.py unit test tests newline and dellink independently.\n\nA functional test run is a process.\n\nThe dispatcher thread is currently written for the duration of the process.\n\nSo, there is no way to restart the dispatcher thread within a functional test.","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"}],"neutron/tests/unit/agent/linux/test_nl_dispatcher.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e0964c0c29b46df436d33faca67a00408f9f8b98","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2026 Red Hat, Inc."},{"line_number":2,"context_line":"# All Rights Reserved."},{"line_number":3,"context_line":"#"},{"line_number":4,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"}],"source_content_type":"text/x-python","patch_set":6,"id":"98a51fc6_54201c0b","line":1,"updated":"2026-05-05 14:48:06.000000000","message":"As the netlink dispatcher mostly interacts with kernel, I wonder if it makes sense to have such unittests for it. I\u0027d rather have isolated functional tests that would work with real netlink messages.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"8cfb2ab5dc0a3b4fdeb16bbc4b13046d9d5d7382","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2026 Red Hat, Inc."},{"line_number":2,"context_line":"# All Rights Reserved."},{"line_number":3,"context_line":"#"},{"line_number":4,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"}],"source_content_type":"text/x-python","patch_set":6,"id":"7c5ddf28_6eb0d2f3","line":1,"in_reply_to":"0b80f6bf_925408c7","updated":"2026-05-07 14:44:57.000000000","message":"Done","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"ee3e4ffe676c5f5e23efc7d0de551626ee142262","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2026 Red Hat, Inc."},{"line_number":2,"context_line":"# All Rights Reserved."},{"line_number":3,"context_line":"#"},{"line_number":4,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"}],"source_content_type":"text/x-python","patch_set":6,"id":"0b80f6bf_925408c7","line":1,"in_reply_to":"98a51fc6_54201c0b","updated":"2026-05-06 02:15:59.000000000","message":"I can remove it.  I find it to be a lightweight tool to test for conditions such as buffer full in the dispatcher loop.","commit_id":"dc86f6e374d947769a8c0713f6c77536e1a13ac9"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e5fbd3b2d60f7d68212315c685b89953091377c4","unresolved":true,"context_lines":[{"line_number":182,"context_line":"        self.mock_time.sleep.assert_called_once_with("},{"line_number":183,"context_line":"            self.dispatcher.RETRY_BACKOFF)"},{"line_number":184,"context_line":"        self.assertEqual("},{"line_number":185,"context_line":"            2, self.mock_iproute.IPRoute.call_count)"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"    def test_socket_error_retries_reset_on_success(self):"},{"line_number":188,"context_line":"        handler \u003d mock.Mock()"}],"source_content_type":"text/x-python","patch_set":18,"id":"eca60b92_b39c4be6","line":185,"range":{"start_line":185,"start_character":20,"end_line":185,"end_character":40},"updated":"2026-05-18 14:58:36.000000000","message":"Isn\u0027t it `mock_ipr` ?","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"3cfbac7df3aaf78d04f02e4455cff3f510fb5dcd","unresolved":false,"context_lines":[{"line_number":182,"context_line":"        self.mock_time.sleep.assert_called_once_with("},{"line_number":183,"context_line":"            self.dispatcher.RETRY_BACKOFF)"},{"line_number":184,"context_line":"        self.assertEqual("},{"line_number":185,"context_line":"            2, self.mock_iproute.IPRoute.call_count)"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"    def test_socket_error_retries_reset_on_success(self):"},{"line_number":188,"context_line":"        handler \u003d mock.Mock()"}],"source_content_type":"text/x-python","patch_set":18,"id":"8ad7be39_d42974d4","line":185,"range":{"start_line":185,"start_character":20,"end_line":185,"end_character":40},"in_reply_to":"eca60b92_b39c4be6","updated":"2026-05-18 16:09:45.000000000","message":"This is to check that IPRoute() is called twice, not to check an instance of IPRoute().\n\nIPRoute() is called twice in this test, the first time when the dispatcher loop starts and the second time when dispatcher loop breaks out of the inner while-loop due to an OSError, closes the socket, and then reopens the socket when IPRoute() is called again.","commit_id":"3d6fda56d365ae1382cfe4a8074c6cab90866276"}],"neutron/tests/unit/agent/ovn/extensions/test_evpn.py":[{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"8143ea1580182c890d81c574543e1ddb49d4877c","unresolved":true,"context_lines":[{"line_number":35,"context_line":"    return _make_nlmsg(ifname, kind\u003dkind)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def _make_msg_no_linkinfo(ifname):"},{"line_number":39,"context_line":"    return _make_nlmsg(ifname)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class TestVrfHandler(base.BaseTestCase):"}],"source_content_type":"text/x-python","patch_set":14,"id":"13928580_4e8d0500","line":39,"range":{"start_line":38,"start_character":0,"end_line":39,"end_character":30},"updated":"2026-05-19 13:50:30.000000000","message":"nit: I mentioned this function later. It does exactly what `_make_nlmsg` do but with different name","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b4e57c6197a3505c1f076801f1cef921bb92a15a","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    return _make_nlmsg(ifname, kind\u003dkind)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"def _make_msg_no_linkinfo(ifname):"},{"line_number":39,"context_line":"    return _make_nlmsg(ifname)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class TestVrfHandler(base.BaseTestCase):"}],"source_content_type":"text/x-python","patch_set":14,"id":"5287e788_37239700","line":39,"range":{"start_line":38,"start_character":0,"end_line":39,"end_character":30},"in_reply_to":"13928580_4e8d0500","updated":"2026-05-19 15:54:03.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"8143ea1580182c890d81c574543e1ddb49d4877c","unresolved":true,"context_lines":[{"line_number":79,"context_line":"        self.assertEqual(set(), self.handler._known_vrfs)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def test_ignores_no_linkinfo(self):"},{"line_number":82,"context_line":"        msg \u003d _make_msg_no_linkinfo(\u0027evpnvrf-10\u0027)"},{"line_number":83,"context_line":"        self.handler.handle_newlink(msg)"},{"line_number":84,"context_line":"        self.assertEqual(set(), self.handler._known_vrfs)"},{"line_number":85,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"640dee8d_4a6d2048","line":82,"updated":"2026-05-19 13:50:30.000000000","message":"nit: I would just rename the `msg` to `msg_with_no_linkinfo` and then you dont need the `_make_msg_no_linksinfo` function at all.","commit_id":"cc6a462f82224216e3674529479edacec490d09a"},{"author":{"_account_id":38298,"name":"Helen Chen","display_name":"Helen Chen","email":"ichen@redhat.com","username":"ingwherchen"},"change_message_id":"b4e57c6197a3505c1f076801f1cef921bb92a15a","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        self.assertEqual(set(), self.handler._known_vrfs)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def test_ignores_no_linkinfo(self):"},{"line_number":82,"context_line":"        msg \u003d _make_msg_no_linkinfo(\u0027evpnvrf-10\u0027)"},{"line_number":83,"context_line":"        self.handler.handle_newlink(msg)"},{"line_number":84,"context_line":"        self.assertEqual(set(), self.handler._known_vrfs)"},{"line_number":85,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"b7ea7116_f5f6c2cc","line":82,"in_reply_to":"640dee8d_4a6d2048","updated":"2026-05-19 15:54:03.000000000","message":"Done","commit_id":"cc6a462f82224216e3674529479edacec490d09a"}]}
