diff --git a/datapath/actions.c b/datapath/actions.c
index 5871d82..5a43255 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -475,6 +475,53 @@ static void execute_hash(struct sk_buff *skb, const struct nlattr *attr)
 	key->ovs_flow_hash = hash;
 }
 
+/**
+ * Checks a response packet from a server, to see if a potential heartbleed attack is happening
+ */
+static int check_heartbleed(struct sk_buff *skb, const struct nlattr *attr) {
+
+	struct tcphdr *th;
+	char *payload;
+	u16 minPayloadSize;	// recommended: 69 or more
+
+	// TODO Validate that this is an IP TCP packet, match rule should ensure that
+	// TODO support IPv4 and IPv6, size check below is for IPv4 only and does not include IP options
+
+	// Check length of skb; is it a TCP packet with payload?
+	minPayloadSize = nla_get_u16(attr);
+	if ( skb->len < ( 14 + sizeof(struct iphdr) + sizeof(struct tcphdr) + minPayloadSize ))
+		return 0;	// too small
+
+	th = tcp_hdr(skb);	// works for both IPv4 and IPv6
+
+	// see http://www.bluecoat.com/security-blog/2014-04-14/security-analytics-hunt-heartbleed-traffic
+	// tcp[((tcp[12:1] & 0xf0) >> 2):2] = 0x1803 &&
+	// tcp[((tcp[12:1] & 0xf0) >> 2) + 2] < 0x04 &&
+	// tcp[(((tcp[12:1] & 0xf0) >> 2) + 3):2] = 0x0003 &&
+	// tcp[((tcp[12:1] & 0xf0) >> 2) + 5] = 0x01 &&
+	// tcp[(((tcp[12:1] & 0xf0) >> 2) + 6):2] > 0x64
+	//
+	// see also http://www.riverbed.com/blogs/Retroactively-detecting-a-prior-Heartbleed-exploitation-from-stored-packets-using-a-BPF-expression.html
+	//
+
+	payload = (char *)((unsigned char *)th + (th->doff * 4));
+
+	static const char TLS_HEARTBEAT_MSG = 0x18;
+	static const char TLS_V3 = 0x03;
+	static const char TLS_MINOR_V0_4 = 0x04;
+
+	if unlikely( payload[0] == TLS_HEARTBEAT_MSG ) {
+		if ( payload[1] == TLS_V3 ) {
+			if ( payload[2] < TLS_MINOR_V0_4 ) {
+				pr_warn("check_heartbleed: Potential large TLS heartbeat response, dropping\n" );
+				return 1;
+			}
+		}
+	}
+	return 0;	// no error
+}
+
+
 static int execute_set_action(struct sk_buff *skb,
 				 const struct nlattr *nested_attr)
 {
@@ -611,6 +658,11 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			if (unlikely(err)) /* skb already freed. */
 				return err;
 			break;
+
+		// JvB: added
+		case OVS_ACTION_ATTR_HEARTBLEED_CHECK:
+			err = check_heartbleed(skb, a);
+			break;
 		}
 
 		if (unlikely(err)) {
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 803a94c..2d378c0 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -1448,7 +1448,8 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
 			[OVS_ACTION_ATTR_POP_VLAN] = 0,
 			[OVS_ACTION_ATTR_SET] = (u32)-1,
 			[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
-			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash)
+			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
+			[OVS_ACTION_ATTR_HEARTBLEED_CHECK] = sizeof(u16),
 		};
 		const struct ovs_action_push_vlan *vlan;
 		int type = nla_type(a);
@@ -1515,6 +1516,13 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
 			skip_copy = true;
 			break;
 
+		case OVS_ACTION_ATTR_HEARTBLEED_CHECK: {
+			u16 minPayload = nla_get_u16(a);
+			if ((minPayload < 40) || minPayload > 1460)
+				return -EINVAL;
+			break;
+		}
+
 		default:
 			return -EINVAL;
 		}
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index 544c5ba..134bb51 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -561,6 +561,11 @@ struct ovs_action_hash {
 	uint32_t  hash_basis;
 };
 
+struct ovs_action_check_heartbleed {
+	__be16 max_payload;	/* Max SSL heartbeat response to allow ( TCP bytes ) */
+};
+
+
 /**
  * enum ovs_action_attr - Action types.
  *
@@ -603,6 +608,9 @@ enum ovs_action_attr {
 	OVS_ACTION_ATTR_POP_MPLS,     /* __be16 ethertype. */
 	OVS_ACTION_ATTR_RECIRC,	      /* u32 recirc_id. */
 	OVS_ACTION_ATTR_HASH,	      /* struct ovs_action_hash. */
+
+	OVS_ACTION_ATTR_CHECK_HEARTBLEED,	/* u16 max_payload */
+
 	__OVS_ACTION_ATTR_MAX
 };
 
diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
index e3e2d39..312c287 100644
--- a/include/openflow/openflow-1.1.h
+++ b/include/openflow/openflow-1.1.h
@@ -210,6 +210,9 @@ enum ofp11_action_type {
     OFPAT11_GROUP,            /* Apply group. */
     OFPAT11_SET_NW_TTL,       /* IP TTL. */
     OFPAT11_DEC_NW_TTL,       /* Decrement IP TTL. */
+
+    OFPAT11_CHECK_HEARTBLEED = 27, /* JvB: Added here, should be vendor extension */
+
     OFPAT11_EXPERIMENTER = 0xffff
 };
 
@@ -763,4 +766,14 @@ struct ofp11_flow_removed {
 };
 OFP_ASSERT(sizeof(struct ofp11_flow_removed) == 40);
 
+/* Action structure for OFPAT11_CHECK_HEARTBLEED. */
+struct ofp11_action_check_heartbleed {
+    ovs_be16 type;                    /* OFPAT11_GROUP. */
+    ovs_be16 len;                     /* Length is 8. */
+    ovs_be16 max_payload;             /* Maximum TCP payload to allow in TLS v3 heartbeat response packets */
+    uint8_t pad2[2];          		  /* Align to 64-bits. */
+};
+OFP_ASSERT(sizeof(struct ofp11_action_check_heartbleed) == 8);
+
+
 #endif /* openflow/openflow-1.1.h */
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 12ad679..b1d07f3 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -248,6 +248,14 @@ odp_execute_actions__(void *dp, struct ofpbuf *packet, bool steal,
                                more_actions || left > NLA_ALIGN(a->nla_len));
             break;
 
+        case OVS_ACTION_ATTR_CHECK_HEARTBLEED: {
+        	const struct ovs_action_check_heartbleed *check = nl_attr_get(a);
+        	if ( check_heartbleed( packet, check->max_payload ) ) {
+        		return;		// stop executing more actions ( like output )
+        	}
+        	break;
+        }
+
         case OVS_ACTION_ATTR_UNSPEC:
         case __OVS_ACTION_ATTR_MAX:
             OVS_NOT_REACHED();
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 8e95c9e..f4d17e9 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -84,6 +84,8 @@ odp_action_len(uint16_t type)
     case OVS_ACTION_ATTR_SET: return -2;
     case OVS_ACTION_ATTR_SAMPLE: return -2;
 
+    case OVS_ACTION_ATTR_CHECK_HEARTBLEED: return sizeof(uint16_t);
+
     case OVS_ACTION_ATTR_UNSPEC:
     case __OVS_ACTION_ATTR_MAX:
         return -1;
@@ -467,6 +469,13 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
     case OVS_ACTION_ATTR_SAMPLE:
         format_odp_sample_action(ds, a);
         break;
+
+    case OVS_ACTION_ATTR_CHECK_HEARTBLEED: {
+        ovs_be16 maxPayload = nl_attr_get_be16(a);
+        ds_put_format(ds, "check_heartbleed(max_payload=%"PRIu16")", ntohs(maxPayload));
+        break;
+    }
+
     case OVS_ACTION_ATTR_UNSPEC:
     case __OVS_ACTION_ATTR_MAX:
     default:
@@ -708,6 +717,17 @@ parse_odp_action(const char *s, const struct simap *port_names,
         }
     }
 
+    {
+    	struct ovs_action_check_heartbleed check_bleed;
+    	int maxPayload, n = -1;
+    	if (ovs_scan(s, "check_heartbleed(maxPayload=%i)%n", &maxPayload, &n)) {
+    		check_bleed.max_payload = htons( maxPayload );
+    		nl_msg_put_unspec(actions, OVS_ACTION_ATTR_CHECK_HEARTBLEED,
+    		                              &check_bleed, sizeof check_bleed);
+    		return n;
+    	}
+    }
+
     return -EINVAL;
 }
 
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index ce14004..1e1f34b 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -57,6 +57,9 @@ union ofp_action {
     struct ofp11_action_mpls_tc ofp11_mpls_tc;
     struct ofp11_action_mpls_ttl ofp11_mpls_ttl;
     struct ofp11_action_group group;
+
+    struct ofp11_action_check_heartbleed check_heartbleed;	// JvB added
+
     struct ofp12_action_set_field set_field;
     struct nx_action_header nxa_header;
     struct nx_action_resubmit resubmit;
@@ -501,6 +504,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
     case OFPUTIL_NXAST_SAMPLE:
         error = sample_from_openflow(&a->sample, out);
         break;
+
     }
 
     return error;
@@ -1269,6 +1273,10 @@ ofpact_from_openflow11(const union ofp_action *a, enum ofp_version version,
         ofpact_put_GROUP(out)->group_id = ntohl(a->group.group_id);
         break;
 
+    case OFPUTIL_OFPAT11_CHECK_HEARTBLEED:
+    	ofpact_put_CHECK_HEARTBLEED(out)->max_payload = ntohs(a->check_heartbleed.max_payload);
+    	break;
+
 #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         return ofpact_from_nxast(a, code, out);
@@ -1331,6 +1339,8 @@ ofpact_is_set_action(const struct ofpact *a)
     case OFPACT_STRIP_VLAN:
     case OFPACT_WRITE_ACTIONS:
     case OFPACT_WRITE_METADATA:
+
+    case OFPACT_CHECK_HEARTBLEED:
         return false;
     default:
         OVS_NOT_REACHED();
@@ -1369,6 +1379,8 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
     case OFPACT_SET_VLAN_PCP:
     case OFPACT_SET_VLAN_VID:
     case OFPACT_STRIP_VLAN:
+
+    case OFPACT_CHECK_HEARTBLEED:
         return true;
 
     /* In general these actions are excluded because they are not part of
@@ -1628,6 +1640,9 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
     case OFPACT_NOTE:
     case OFPACT_EXIT:
     case OFPACT_SAMPLE:
+
+    case OFPACT_CHECK_HEARTBLEED:
+
     default:
         return OVSINST_OFPIT11_APPLY_ACTIONS;
     }
@@ -2130,6 +2145,7 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
     }
 
     case OFPACT_GROUP:
+    case OFPACT_CHECK_HEARTBLEED:
         return 0;
 
     default:
@@ -2495,6 +2511,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
     case OFPACT_SET_FIELD:
+    case OFPACT_CHECK_HEARTBLEED:
         OVS_NOT_REACHED();
     }
 }
@@ -2595,6 +2612,8 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
+
+    case OFPACT_CHECK_HEARTBLEED:
         /* XXX */
         break;
 
@@ -2634,7 +2653,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
         break;
     }
 }
-
+
 /* Converting ofpacts to OpenFlow 1.1. */
 
 static void
@@ -2803,6 +2822,12 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
             htonl(ofpact_get_GROUP(a)->group_id);
         break;
 
+    case OFPACT_CHECK_HEARTBLEED:
+        ofputil_put_OFPAT11_CHECK_HEARTBLEED(out)->max_payload =
+            htons(ofpact_get_CHECK_HEARTBLEED(a)->max_payload);
+        break;
+
+
     case OFPACT_SET_FIELD:
         set_field_to_openflow(ofpact_get_SET_FIELD(a), out);
         break;
@@ -3151,6 +3176,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
     case OFPACT_GROUP:
+    case OFPACT_CHECK_HEARTBLEED:
     default:
         return false;
     }
@@ -3575,6 +3601,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_format(s, "group:%"PRIu32,
                       ofpact_get_GROUP(a)->group_id);
         break;
+
+    case OFPACT_CHECK_HEARTBLEED:
+        ds_put_format(s, "check_heartbleed:%"PRIu16,
+                      ntohs(ofpact_get_CHECK_HEARTBLEED(a)->max_payload));
+        break;
     }
 }
 
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 89bf867..d03b416 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -102,6 +102,7 @@
     DEFINE_OFPACT(NOTE,            ofpact_note,          data)      \
     DEFINE_OFPACT(EXIT,            ofpact_null,          ofpact)    \
     DEFINE_OFPACT(SAMPLE,          ofpact_sample,        ofpact)    \
+    DEFINE_OFPACT(CHECK_HEARTBLEED,ofpact_check_heartbleed, ofpact) \
                                                                     \
     /* Instructions */                                              \
     DEFINE_OFPACT(METER,           ofpact_meter,         ofpact)    \
@@ -529,6 +530,14 @@ struct ofpact_sample {
     uint32_t obs_point_id;
 };
 
+/* OFPACT_CHECK_HEARTBLEED
+ *
+ * Used for NXAST_CHECK_HEARTBLEED. */
+struct ofpact_check_heartbleed {
+    struct ofpact ofpact;
+    uint16_t max_payload;  // Max payload to allow in case of TLS v3 heartbeat
+};
+
 /* OFPACT_DEC_TTL.
  *
  * Used for OFPAT11_DEC_NW_TTL, NXAST_DEC_TTL and NXAST_DEC_TTL_CNT_IDS. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index d250042..e2c2df5 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -909,6 +909,10 @@ parse_named_action(enum ofputil_action_code code,
         error = str_to_u32(arg, &ofpact_put_GROUP(ofpacts)->group_id);
         break;
 
+    case OFPUTIL_OFPAT11_CHECK_HEARTBLEED:
+    	error = str_to_u16(arg, "max_payload", &ofpact_put_CHECK_HEARTBLEED(ofpacts)->max_payload );
+    	break;
+
     /* FIXME when implement OFPAT13_* */
     case OFPUTIL_OFPAT13_COPY_TTL_OUT:
     case OFPUTIL_OFPAT13_COPY_TTL_IN:
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 44decae..2583f93 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -44,6 +44,9 @@ OFPAT11_ACTION(OFPAT11_DEC_NW_TTL,   ofp_action_header,   0, NULL)
 OFPAT11_ACTION(OFPAT12_SET_FIELD,    ofp12_action_set_field, 1, "set_field")
 OFPAT11_ACTION(OFPAT11_GROUP,        ofp11_action_group,   0, "group")
 
+OFPAT11_ACTION(OFPAT11_CHECK_HEARTBLEED, ofp11_action_check_heartbleed, 0, "check_heartbleed")
+
+
 #ifndef OFPAT13_ACTION
 #define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)
 #endif
diff --git a/lib/packets.c b/lib/packets.c
index 6244c3f..5a9d8e4 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -584,6 +584,38 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
     return data;
 }
 
+/**
+ * JvB: Added to check for potential heartbleed ( i.e. payload in TLS heartbeat response from server )
+ */
+bool check_heartbleed(const struct ofpbuf *packet, ovs_be16 maxPayload)
+{
+	struct ip_header *nh = ofpbuf_l3(packet);
+	size_t l4_size = ofpbuf_l4_size(packet);
+
+	if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
+		size_t tcpData = ofpbuf_l4_size(packet);
+		if ( tcpData > ntohs(maxPayload) ) {
+			const char *payload = ofpbuf_get_tcp_payload(packet);
+
+			// XXX Copied from datapath
+			static const char TLS_HEARTBEAT_MSG = 0x18;
+			static const char TLS_V3 = 0x03;
+			static const char TLS_MINOR_V0_4 = 0x04;
+
+			if /* unlikely */ ( payload[0] == TLS_HEARTBEAT_MSG ) {
+				if ( payload[1] == TLS_V3 ) {
+					if ( payload[2] < TLS_MINOR_V0_4 ) {
+						// pr_warn("check_heartbleed: Potential large TLS heartbeat response, dropping\n" );
+						return true;
+					}
+				}
+			}
+
+		}
+	}
+	return false;	// no heartbleed
+}
+
 static void
 packet_set_ipv4_addr(struct ofpbuf *packet,
                      ovs_16aligned_be32 *addr, ovs_be32 new_addr)
diff --git a/lib/packets.h b/lib/packets.h
index f294d84..5ed9ef2 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -205,6 +205,8 @@ void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos);
 ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos,
                              ovs_be32 label);
 
+bool check_heartbleed(const struct ofpbuf *, ovs_be16 maxPayload);
+
 /* Example:
  *
  * uint8_t mac[ETH_ADDR_LEN];
