diff --git a/include/net/devlink.h b/include/net/devlink.h
index fbb9a2668e24..64dc3e292c2c 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1613,6 +1613,15 @@ void devlink_free(struct devlink *devlink);
  *			    of event queues. Should be used by device drivers to
  *			    configure maximum number of event queues
  *			    of a function managed by the devlink port.
+ * @port_fn_bridge_offload_get: Callback used to get port function's bridge
+ *				 offload capability. Should be used by device drivers
+ *				 to report the current state of offload
+ *				 capability of a function managed by the devlink
+ *				 port.
+ * @port_fn_bridge_offload_get: Callback used to set port function's bridge
+ *				 offload capability. Should be used by device drivers to
+ *				 enable/disable offload capability of a
+ *				 function managed by the devlink port.
  *
  * Note: Driver should return -EOPNOTSUPP if it doesn't support
  * port function (@port_fn_*) handling for a particular port.
@@ -1668,6 +1677,10 @@ struct devlink_port_ops {
 	int (*port_fn_max_io_eqs_set)(struct devlink_port *devlink_port,
 				      u32 max_eqs,
 				      struct netlink_ext_ack *extack);
+	void (*port_fn_bridge_offload_get)(struct devlink_port *devlink_port,
+					   bool *is_enable);
+	void (*port_fn_bridge_offload_set)(struct devlink_port *devlink_port,
+					   bool enable);
 };
 
 void devlink_port_init(struct devlink *devlink,
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 9401aa343673..e2682bc9ecb1 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -668,6 +668,7 @@ enum devlink_port_fn_attr_cap {
 	DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT,
 	DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT,
 	DEVLINK_PORT_FN_ATTR_CAP_IPSEC_PACKET_BIT,
+	DEVLINK_PORT_FN_ATTR_CAP_BRIDGE_OFFLOAD_BIT,
 
 	/* Add new caps above */
 	__DEVLINK_PORT_FN_ATTR_CAPS_MAX,
@@ -678,6 +679,7 @@ enum devlink_port_fn_attr_cap {
 	_BITUL(DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT)
 #define DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO _BITUL(DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT)
 #define DEVLINK_PORT_FN_CAP_IPSEC_PACKET _BITUL(DEVLINK_PORT_FN_ATTR_CAP_IPSEC_PACKET_BIT)
+#define DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD _BITUL(DEVLINK_PORT_FN_ATTR_CAP_BRIDGE_OFFLOAD_BIT)
 
 enum devlink_port_function_attr {
 	DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
diff --git a/net/devlink/port.c b/net/devlink/port.c
index be9158b4453c..d7f9276c3601 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -148,6 +148,21 @@ static int devlink_port_fn_ipsec_packet_fill(struct devlink_port *devlink_port,
 	return 0;
 }
 
+static int devlink_port_bridge_offload_fill(struct devlink_port *devlink_port,
+					    struct nla_bitfield32 *caps)
+{
+	bool is_enable;
+
+	if (!devlink_port->ops->port_fn_bridge_offload_get ||
+	    devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL)
+		return 0;
+
+	devlink_port->ops->port_fn_bridge_offload_get(devlink_port, &is_enable);
+
+	devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD, is_enable);
+	return 0;
+}
+
 static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
 				     struct sk_buff *msg,
 				     struct netlink_ext_ack *extack,
@@ -172,6 +187,10 @@ static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
 	if (err)
 		return err;
 
+	err = devlink_port_bridge_offload_fill(devlink_port, &caps);
+	if (err)
+		return err;
+
 	if (!caps.selector)
 		return 0;
 	err = nla_put_bitfield32(msg, DEVLINK_PORT_FN_ATTR_CAPS, caps.value,
@@ -393,6 +412,12 @@ devlink_port_fn_ipsec_packet_set(struct devlink_port *devlink_port, bool enable,
 	return devlink_port->ops->port_fn_ipsec_packet_set(devlink_port, enable, extack);
 }
 
+static void
+devlink_port_fn_bridge_offload_set(struct devlink_port *devlink_port, bool enable)
+{
+	return devlink_port->ops->port_fn_bridge_offload_set(devlink_port, enable);
+}
+
 static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
 				    const struct nlattr *attr,
 				    struct netlink_ext_ack *extack)
@@ -431,6 +456,10 @@ static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
 		if (err)
 			return err;
 	}
+	if (caps.selector & DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD) {
+		devlink_port_fn_bridge_offload_set(devlink_port, caps_value &
+							 DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD);
+	}
 	return 0;
 }
 
@@ -765,6 +794,18 @@ static int devlink_port_function_validate(struct devlink_port *devlink_port,
 				return -EOPNOTSUPP;
 			}
 		}
+		if (caps.selector & DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD) {
+			if (!ops->port_fn_bridge_offload_set) {
+				NL_SET_ERR_MSG_ATTR(extack, attr,
+						    "Port doesn't support bridge offload function attribute");
+				return -EOPNOTSUPP;
+			}
+			if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL) {
+				NL_SET_ERR_MSG_ATTR(extack, attr,
+						    "bridge offload function attribute supported for physical ports only");
+				return -EOPNOTSUPP;
+			}
+		}
 	}
 	if (tb[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS] &&
 	    !ops->port_fn_max_io_eqs_set) {
